1 /* Omit from static analysis. */
2 #ifndef __clang_analyzer__
3 /*
4  *  Single source autogenerated distributable for Duktape 2.4.0.
5  *
6  *  Git commit external (external).
7  *  Git branch external.
8  *
9  *  See Duktape AUTHORS.rst and LICENSE.txt for copyright and
10  *  licensing information.
11  */
12 
13 /* LICENSE.txt */
14 /*
15 *  ===============
16 *  Duktape license
17 *  ===============
18 *
19 *  (http://opensource.org/licenses/MIT)
20 *
21 *  Copyright (c) 2013-2019 by Duktape authors (see AUTHORS.rst)
22 *
23 *  Permission is hereby granted, free of charge, to any person obtaining a copy
24 *  of this software and associated documentation files (the "Software"), to deal
25 *  in the Software without restriction, including without limitation the rights
26 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27 *  copies of the Software, and to permit persons to whom the Software is
28 *  furnished to do so, subject to the following conditions:
29 *
30 *  The above copyright notice and this permission notice shall be included in
31 *  all copies or substantial portions of the Software.
32 *
33 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
39 *  THE SOFTWARE.
40 */
41 
42 /* AUTHORS.rst */
43 /*
44 *  ===============
45 *  Duktape authors
46 *  ===============
47 *
48 *  Copyright
49 *  =========
50 *
51 *  Duktape copyrights are held by its authors.  Each author has a copyright
52 *  to their contribution, and agrees to irrevocably license the contribution
53 *  under the Duktape ``LICENSE.txt``.
54 *
55 *  Authors
56 *  =======
57 *
58 *  Please include an e-mail address, a link to your GitHub profile, or something
59 *  similar to allow your contribution to be identified accurately.
60 *
61 *  The following people have contributed code, website contents, or Wiki contents,
62 *  and agreed to irrevocably license their contributions under the Duktape
63 *  ``LICENSE.txt`` (in order of appearance):
64 *
65 *  * Sami Vaarala <sami.vaarala@iki.fi>
66 *  * Niki Dobrev
67 *  * Andreas \u00d6man <andreas@lonelycoder.com>
68 *  * L\u00e1szl\u00f3 Lang\u00f3 <llango.u-szeged@partner.samsung.com>
69 *  * Legimet <legimet.calc@gmail.com>
70 *  * Karl Skomski <karl@skomski.com>
71 *  * Bruce Pascoe <fatcerberus1@gmail.com>
72 *  * Ren\u00e9 Hollander <rene@rene8888.at>
73 *  * Julien Hamaide (https://github.com/crazyjul)
74 *  * Sebastian G\u00f6tte (https://github.com/jaseg)
75 *  * Tomasz Magulski (https://github.com/magul)
76 *  * \D. Bohdan (https://github.com/dbohdan)
77 *  * Ond\u0159ej Jirman (https://github.com/megous)
78 *  * Sa\u00fal Ibarra Corretg\u00e9 <saghul@gmail.com>
79 *  * Jeremy HU <huxingyi@msn.com>
80 *  * Ole Andr\u00e9 Vadla Ravn\u00e5s (https://github.com/oleavr)
81 *  * Harold Brenes (https://github.com/harold-b)
82 *  * Oliver Crow (https://github.com/ocrow)
83 *  * Jakub Ch\u0142api\u0144ski (https://github.com/jchlapinski)
84 *  * Brett Vickers (https://github.com/beevik)
85 *  * Dominik Okwieka (https://github.com/okitec)
86 *  * Remko Tron\u00e7on (https://el-tramo.be)
87 *  * Romero Malaquias (rbsm@ic.ufal.br)
88 *  * Michael Drake <michael.drake@codethink.co.uk>
89 *  * Steven Don (https://github.com/shdon)
90 *  * Simon Stone (https://github.com/sstone1)
91 *  * \J. McC. (https://github.com/jmhmccr)
92 *  * Jakub Nowakowski (https://github.com/jimvonmoon)
93 *  * Tommy Nguyen (https://github.com/tn0502)
94 *  * Fabrice Fontaine (https://github.com/ffontaine)
95 *  * Christopher Hiller (https://github.com/boneskull)
96 *  * Gonzalo Diethelm (https://github.com/gonzus)
97 *  * Michal Kasperek (https://github.com/michalkas)
98 *  * Andrew Janke (https://github.com/apjanke)
99 *  * Steve Fan (https://github.com/stevefan1999)
100 *  * Edward Betts (https://github.com/edwardbetts)
101 *  * Ozhan Duz (https://github.com/webfolderio)
102 *  * Akos Kiss (https://github.com/akosthekiss)
103 *  * TheBrokenRail (https://github.com/TheBrokenRail)
104 *  * Jesse Doyle (https://github.com/jessedoyle)
105 *  * Gero Kuehn (https://github.com/dc6jgk)
106 *  * James Swift (https://github.com/phraemer)
107 *  * Luis de Bethencourt (https://github.com/luisbg)
108 *  * Ian Whyman (https://github.com/v00d00)
109 *
110 *  Other contributions
111 *  ===================
112 *
113 *  The following people have contributed something other than code (e.g. reported
114 *  bugs, provided ideas, etc; roughly in order of appearance):
115 *
116 *  * Greg Burns
117 *  * Anthony Rabine
118 *  * Carlos Costa
119 *  * Aur\u00e9lien Bouilland
120 *  * Preet Desai (Pris Matic)
121 *  * judofyr (http://www.reddit.com/user/judofyr)
122 *  * Jason Woofenden
123 *  * Micha\u0142 Przyby\u015b
124 *  * Anthony Howe
125 *  * Conrad Pankoff
126 *  * Jim Schimpf
127 *  * Rajaran Gaunker (https://github.com/zimbabao)
128 *  * Andreas \u00d6man
129 *  * Doug Sanden
130 *  * Josh Engebretson (https://github.com/JoshEngebretson)
131 *  * Remo Eichenberger (https://github.com/remoe)
132 *  * Mamod Mehyar (https://github.com/mamod)
133 *  * David Demelier (https://github.com/markand)
134 *  * Tim Caswell (https://github.com/creationix)
135 *  * Mitchell Blank Jr (https://github.com/mitchblank)
136 *  * https://github.com/yushli
137 *  * Seo Sanghyeon (https://github.com/sanxiyn)
138 *  * Han ChoongWoo (https://github.com/tunz)
139 *  * Joshua Peek (https://github.com/josh)
140 *  * Bruce E. Pascoe (https://github.com/fatcerberus)
141 *  * https://github.com/Kelledin
142 *  * https://github.com/sstruchtrup
143 *  * Michael Drake (https://github.com/tlsa)
144 *  * https://github.com/chris-y
145 *  * Laurent Zubiaur (https://github.com/lzubiaur)
146 *  * Neil Kolban (https://github.com/nkolban)
147 *  * Wilhelm Wanecek (https://github.com/wanecek)
148 *  * Andrew Janke (https://github.com/apjanke)
149 *  * Unamer (https://github.com/unamer)
150 *  * Karl Dahlke (eklhad@gmail.com)
151 *
152 *  If you are accidentally missing from this list, send me an e-mail
153 *  (``sami.vaarala@iki.fi``) and I'll fix the omission.
154 */
155 
156 /*
157  *  Replacements for missing platform functions.
158  *
159  *  Unlike the originals, fpclassify() and signbit() replacements don't
160  *  work on any floating point types, only doubles.  The C typing here
161  *  mimics the standard prototypes.
162  */
163 
164 /* #include duk_internal.h */
165 /*
166  *  Top-level include file to be used for all (internal) source files.
167  *
168  *  Source files should not include individual header files, as they
169  *  have not been designed to be individually included.
170  */
171 
172 #if !defined(DUK_INTERNAL_H_INCLUDED)
173 #define DUK_INTERNAL_H_INCLUDED
174 
175 /*
176  *  The 'duktape.h' header provides the public API, but also handles all
177  *  compiler and platform specific feature detection, Duktape feature
178  *  resolution, inclusion of system headers, etc.  These have been merged
179  *  because the public API is also dependent on e.g. detecting appropriate
180  *  C types which is quite platform/compiler specific especially for a non-C99
181  *  build.  The public API is also dependent on the resolved feature set.
182  *
183  *  Some actions taken by the merged header (such as including system headers)
184  *  are not appropriate for building a user application.  The define
185  *  DUK_COMPILING_DUKTAPE allows the merged header to skip/include some
186  *  sections depending on what is being built.
187  */
188 
189 #define DUK_COMPILING_DUKTAPE
190 #include "duktape.h"
191 
192 /*
193  *  Duktape includes (other than duk_features.h)
194  *
195  *  The header files expect to be included in an order which satisfies header
196  *  dependencies correctly (the headers themselves don't include any other
197  *  includes).  Forward declarations are used to break circular struct/typedef
198  *  dependencies.
199  */
200 
201 /* #include duk_dblunion.h */
202 /*
203  *  Union to access IEEE double memory representation, indexes for double
204  *  memory representation, and some macros for double manipulation.
205  *
206  *  Also used by packed duk_tval.  Use a union for bit manipulation to
207  *  minimize aliasing issues in practice.  The C99 standard does not
208  *  guarantee that this should work, but it's a very widely supported
209  *  practice for low level manipulation.
210  *
211  *  IEEE double format summary:
212  *
213  *    seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
214  *       A        B        C        D        E        F        G        H
215  *
216  *    s       sign bit
217  *    eee...  exponent field
218  *    fff...  fraction
219  *
220  *  See http://en.wikipedia.org/wiki/Double_precision_floating-point_format.
221  *
222  *  NaNs are represented as exponent 0x7ff and mantissa != 0.  The NaN is a
223  *  signaling NaN when the highest bit of the mantissa is zero, and a quiet
224  *  NaN when the highest bit is set.
225  *
226  *  At least three memory layouts are relevant here:
227  *
228  *    A B C D E F G H    Big endian (e.g. 68k)           DUK_USE_DOUBLE_BE
229  *    H G F E D C B A    Little endian (e.g. x86)        DUK_USE_DOUBLE_LE
230  *    D C B A H G F E    Mixed/cross endian (e.g. ARM)   DUK_USE_DOUBLE_ME
231  *
232  *  ARM is a special case: ARM double values are in mixed/cross endian
233  *  format while ARM duk_uint64_t values are in standard little endian
234  *  format (H G F E D C B A).  When a double is read as a duk_uint64_t
235  *  from memory, the register will contain the (logical) value
236  *  E F G H A B C D.  This requires some special handling below.
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 		if (DUK__DBLUNION_IS_NAN_NOTFULL((u))) { \
526 			DUK__DBLUNION_SET_NAN_NOTFULL((u)); \
527 		} \
528 	} while (0)
529 
530 /* Concrete macros for NaN handling used by the implementation internals.
531  * Chosen so that they match the duk_tval representation: with a packed
532  * duk_tval, ensure NaNs are properly normalized; with a non-packed duk_tval
533  * these are essentially NOPs.
534  */
535 
536 #if defined(DUK_USE_PACKED_TVAL)
537 #if defined(DUK_USE_FULL_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 #else
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_replacements.h */
626 #if !defined(DUK_REPLACEMENTS_H_INCLUDED)
627 #define DUK_REPLACEMENTS_H_INCLUDED
628 
629 #if !defined(DUK_SINGLE_FILE)
630 #if defined(DUK_USE_COMPUTED_INFINITY)
631 DUK_INTERNAL_DECL double duk_computed_infinity;
632 #endif
633 #if defined(DUK_USE_COMPUTED_NAN)
634 DUK_INTERNAL_DECL double duk_computed_nan;
635 #endif
636 #endif  /* !DUK_SINGLE_FILE */
637 
638 #if defined(DUK_USE_REPL_FPCLASSIFY)
639 DUK_INTERNAL_DECL int duk_repl_fpclassify(double x);
640 #endif
641 #if defined(DUK_USE_REPL_SIGNBIT)
642 DUK_INTERNAL_DECL int duk_repl_signbit(double x);
643 #endif
644 #if defined(DUK_USE_REPL_ISFINITE)
645 DUK_INTERNAL_DECL int duk_repl_isfinite(double x);
646 #endif
647 #if defined(DUK_USE_REPL_ISNAN)
648 DUK_INTERNAL_DECL int duk_repl_isnan(double x);
649 #endif
650 #if defined(DUK_USE_REPL_ISINF)
651 DUK_INTERNAL_DECL int duk_repl_isinf(double x);
652 #endif
653 
654 #endif  /* DUK_REPLACEMENTS_H_INCLUDED */
655 /* #include duk_jmpbuf.h */
656 /*
657  *  Wrapper for jmp_buf.
658  *
659  *  This is used because jmp_buf is an array type for backward compatibility.
660  *  Wrapping jmp_buf in a struct makes pointer references, sizeof, etc,
661  *  behave more intuitively.
662  *
663  *  http://en.wikipedia.org/wiki/Setjmp.h#Member_types
664  */
665 
666 #if !defined(DUK_JMPBUF_H_INCLUDED)
667 #define DUK_JMPBUF_H_INCLUDED
668 
669 #if defined(DUK_USE_CPP_EXCEPTIONS)
670 struct duk_jmpbuf {
671 	duk_small_int_t dummy;  /* unused */
672 };
673 #else
674 struct duk_jmpbuf {
675 	DUK_JMPBUF_TYPE jb;
676 };
677 #endif
678 
679 #endif  /* DUK_JMPBUF_H_INCLUDED */
680 /* #include duk_exception.h */
681 /*
682  *  Exceptions for Duktape internal throws when C++ exceptions are used
683  *  for long control transfers.
684  */
685 
686 #if !defined(DUK_EXCEPTION_H_INCLUDED)
687 #define DUK_EXCEPTION_H_INCLUDED
688 
689 #if defined(DUK_USE_CPP_EXCEPTIONS)
690 /* Internal exception used as a setjmp-longjmp replacement.  User code should
691  * NEVER see or catch this exception, so it doesn't inherit from any base
692  * class which should minimize the chance of user code accidentally catching
693  * the exception.
694  */
695 class duk_internal_exception {
696 	/* intentionally empty */
697 };
698 
699 /* Fatal error, thrown as a specific C++ exception with C++ exceptions
700  * enabled.  It is unsafe to continue; doing so may cause crashes or memory
701  * leaks.  This is intended to be either uncaught, or caught by user code
702  * aware of the "unsafe to continue" semantics.
703  */
704 class duk_fatal_exception : public virtual std::runtime_error {
705  public:
duk_fatal_exception(const char * message)706 	duk_fatal_exception(const char *message) : std::runtime_error(message) {}
707 };
708 #endif
709 
710 #endif  /* DUK_EXCEPTION_H_INCLUDED */
711 /* #include duk_forwdecl.h */
712 /*
713  *  Forward declarations for all Duktape structures.
714  */
715 
716 #if !defined(DUK_FORWDECL_H_INCLUDED)
717 #define DUK_FORWDECL_H_INCLUDED
718 
719 /*
720  *  Forward declarations
721  */
722 
723 #if defined(DUK_USE_CPP_EXCEPTIONS)
724 class duk_internal_exception;
725 #else
726 struct duk_jmpbuf;
727 #endif
728 
729 /* duk_tval intentionally skipped */
730 struct duk_heaphdr;
731 struct duk_heaphdr_string;
732 struct duk_harray;
733 struct duk_hstring;
734 struct duk_hstring_external;
735 struct duk_hobject;
736 struct duk_hcompfunc;
737 struct duk_hnatfunc;
738 struct duk_hboundfunc;
739 struct duk_hthread;
740 struct duk_hbufobj;
741 struct duk_hdecenv;
742 struct duk_hobjenv;
743 struct duk_hproxy;
744 struct duk_hbuffer;
745 struct duk_hbuffer_fixed;
746 struct duk_hbuffer_dynamic;
747 struct duk_hbuffer_external;
748 
749 struct duk_propaccessor;
750 union duk_propvalue;
751 struct duk_propdesc;
752 
753 struct duk_heap;
754 struct duk_breakpoint;
755 
756 struct duk_activation;
757 struct duk_catcher;
758 struct duk_ljstate;
759 struct duk_strcache_entry;
760 struct duk_litcache_entry;
761 struct duk_strtab_entry;
762 
763 #if defined(DUK_USE_DEBUG)
764 struct duk_fixedbuffer;
765 #endif
766 
767 struct duk_bitdecoder_ctx;
768 struct duk_bitencoder_ctx;
769 struct duk_bufwriter_ctx;
770 
771 struct duk_token;
772 struct duk_re_token;
773 struct duk_lexer_point;
774 struct duk_lexer_ctx;
775 struct duk_lexer_codepoint;
776 
777 struct duk_compiler_instr;
778 struct duk_compiler_func;
779 struct duk_compiler_ctx;
780 
781 struct duk_re_matcher_ctx;
782 struct duk_re_compiler_ctx;
783 
784 #if defined(DUK_USE_CPP_EXCEPTIONS)
785 /* no typedef */
786 #else
787 typedef struct duk_jmpbuf duk_jmpbuf;
788 #endif
789 
790 /* duk_tval intentionally skipped */
791 typedef struct duk_heaphdr duk_heaphdr;
792 typedef struct duk_heaphdr_string duk_heaphdr_string;
793 typedef struct duk_harray duk_harray;
794 typedef struct duk_hstring duk_hstring;
795 typedef struct duk_hstring_external duk_hstring_external;
796 typedef struct duk_hobject duk_hobject;
797 typedef struct duk_hcompfunc duk_hcompfunc;
798 typedef struct duk_hnatfunc duk_hnatfunc;
799 typedef struct duk_hboundfunc duk_hboundfunc;
800 typedef struct duk_hthread duk_hthread;
801 typedef struct duk_hbufobj duk_hbufobj;
802 typedef struct duk_hdecenv duk_hdecenv;
803 typedef struct duk_hobjenv duk_hobjenv;
804 typedef struct duk_hproxy duk_hproxy;
805 typedef struct duk_hbuffer duk_hbuffer;
806 typedef struct duk_hbuffer_fixed duk_hbuffer_fixed;
807 typedef struct duk_hbuffer_dynamic duk_hbuffer_dynamic;
808 typedef struct duk_hbuffer_external duk_hbuffer_external;
809 
810 typedef struct duk_propaccessor duk_propaccessor;
811 typedef union duk_propvalue duk_propvalue;
812 typedef struct duk_propdesc duk_propdesc;
813 
814 typedef struct duk_heap duk_heap;
815 typedef struct duk_breakpoint duk_breakpoint;
816 
817 typedef struct duk_activation duk_activation;
818 typedef struct duk_catcher duk_catcher;
819 typedef struct duk_ljstate duk_ljstate;
820 typedef struct duk_strcache_entry duk_strcache_entry;
821 typedef struct duk_litcache_entry duk_litcache_entry;
822 typedef struct duk_strtab_entry duk_strtab_entry;
823 
824 #if defined(DUK_USE_DEBUG)
825 typedef struct duk_fixedbuffer duk_fixedbuffer;
826 #endif
827 
828 typedef struct duk_bitdecoder_ctx duk_bitdecoder_ctx;
829 typedef struct duk_bitencoder_ctx duk_bitencoder_ctx;
830 typedef struct duk_bufwriter_ctx duk_bufwriter_ctx;
831 
832 typedef struct duk_token duk_token;
833 typedef struct duk_re_token duk_re_token;
834 typedef struct duk_lexer_point duk_lexer_point;
835 typedef struct duk_lexer_ctx duk_lexer_ctx;
836 typedef struct duk_lexer_codepoint duk_lexer_codepoint;
837 
838 typedef struct duk_compiler_instr duk_compiler_instr;
839 typedef struct duk_compiler_func duk_compiler_func;
840 typedef struct duk_compiler_ctx duk_compiler_ctx;
841 
842 typedef struct duk_re_matcher_ctx duk_re_matcher_ctx;
843 typedef struct duk_re_compiler_ctx duk_re_compiler_ctx;
844 
845 #endif  /* DUK_FORWDECL_H_INCLUDED */
846 /* #include duk_tval.h */
847 /*
848  *  Tagged type definition (duk_tval) and accessor macros.
849  *
850  *  Access all fields through the accessor macros, as the representation
851  *  is quite tricky.
852  *
853  *  There are two packed type alternatives: an 8-byte representation
854  *  based on an IEEE double (preferred for compactness), and a 12-byte
855  *  representation (portability).  The latter is needed also in e.g.
856  *  64-bit environments (it usually pads to 16 bytes per value).
857  *
858  *  Selecting the tagged type format involves many trade-offs (memory
859  *  use, size and performance of generated code, portability, etc).
860  *
861  *  NB: because macro arguments are often expressions, macros should
862  *  avoid evaluating their argument more than once.
863  */
864 
865 #if !defined(DUK_TVAL_H_INCLUDED)
866 #define DUK_TVAL_H_INCLUDED
867 
868 /* sanity */
869 #if !defined(DUK_USE_DOUBLE_LE) && !defined(DUK_USE_DOUBLE_ME) && !defined(DUK_USE_DOUBLE_BE)
870 #error unsupported: cannot determine byte order variant
871 #endif
872 
873 #if defined(DUK_USE_PACKED_TVAL)
874 /* ======================================================================== */
875 
876 /*
877  *  Packed 8-byte representation
878  */
879 
880 /* use duk_double_union as duk_tval directly */
881 typedef union duk_double_union duk_tval;
882 typedef struct {
883 	duk_uint16_t a;
884 	duk_uint16_t b;
885 	duk_uint16_t c;
886 	duk_uint16_t d;
887 } duk_tval_unused;
888 
889 /* tags */
890 #define DUK_TAG_NORMALIZED_NAN    0x7ff8UL   /* the NaN variant we use */
891 /* avoid tag 0xfff0, no risk of confusion with negative infinity */
892 #define DUK_TAG_MIN               0xfff1UL
893 #if defined(DUK_USE_FASTINT)
894 #define DUK_TAG_FASTINT           0xfff1UL   /* embed: integer value */
895 #endif
896 #define DUK_TAG_UNUSED            0xfff2UL   /* marker; not actual tagged value */
897 #define DUK_TAG_UNDEFINED         0xfff3UL   /* embed: nothing */
898 #define DUK_TAG_NULL              0xfff4UL   /* embed: nothing */
899 #define DUK_TAG_BOOLEAN           0xfff5UL   /* embed: 0 or 1 (false or true) */
900 /* DUK_TAG_NUMBER would logically go here, but it has multiple 'tags' */
901 #define DUK_TAG_POINTER           0xfff6UL   /* embed: void ptr */
902 #define DUK_TAG_LIGHTFUNC         0xfff7UL   /* embed: func ptr */
903 #define DUK_TAG_STRING            0xfff8UL   /* embed: duk_hstring ptr */
904 #define DUK_TAG_OBJECT            0xfff9UL   /* embed: duk_hobject ptr */
905 #define DUK_TAG_BUFFER            0xfffaUL   /* embed: duk_hbuffer ptr */
906 #define DUK_TAG_MAX               0xfffaUL
907 
908 /* for convenience */
909 #define DUK_XTAG_BOOLEAN_FALSE    0xfff50000UL
910 #define DUK_XTAG_BOOLEAN_TRUE     0xfff50001UL
911 
912 #define DUK_TVAL_IS_VALID_TAG(tv) \
913 	(DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)
914 
915 /* DUK_TVAL_UNUSED initializer for duk_tval_unused, works for any endianness. */
916 #define DUK_TVAL_UNUSED_INITIALIZER() \
917 	{ DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED }
918 
919 /* two casts to avoid gcc warning: "warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]" */
920 #if defined(DUK_USE_64BIT_OPS)
921 #if defined(DUK_USE_DOUBLE_ME)
922 #define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \
923 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 16) | (((duk_uint64_t) (duk_uint32_t) (h)) << 32); \
924 	} while (0)
925 #else
926 #define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \
927 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 48) | ((duk_uint64_t) (duk_uint32_t) (h)); \
928 	} while (0)
929 #endif
930 #else  /* DUK_USE_64BIT_OPS */
931 #define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \
932 		duk_tval *duk__tv; \
933 		duk__tv = (tv); \
934 		duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) (tag)) << 16; \
935 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (h); \
936 	} while (0)
937 #endif  /* DUK_USE_64BIT_OPS */
938 
939 #if defined(DUK_USE_64BIT_OPS)
940 /* Double casting for pointer to avoid gcc warning (cast from pointer to integer of different size) */
941 #if defined(DUK_USE_DOUBLE_ME)
942 #define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
943 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 16) | \
944 		                              ((duk_uint64_t) (flags)) | \
945 		                              (((duk_uint64_t) (duk_uint32_t) (fp)) << 32); \
946 	} while (0)
947 #else
948 #define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
949 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 48) | \
950 		                              (((duk_uint64_t) (flags)) << 32) | \
951 		                              ((duk_uint64_t) (duk_uint32_t) (fp)); \
952 	} while (0)
953 #endif
954 #else  /* DUK_USE_64BIT_OPS */
955 #define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
956 		duk_tval *duk__tv; \
957 		duk__tv = (tv); \
958 		duk__tv->ui[DUK_DBL_IDX_UI0] = (((duk_uint32_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint32_t) (flags)); \
959 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (fp); \
960 	} while (0)
961 #endif  /* DUK_USE_64BIT_OPS */
962 
963 #if defined(DUK_USE_FASTINT)
964 /* Note: masking is done for 'i' to deal with negative numbers correctly */
965 #if defined(DUK_USE_DOUBLE_ME)
966 #define DUK__TVAL_SET_I48(tv,i)  do { \
967 		duk_tval *duk__tv; \
968 		duk__tv = (tv); \
969 		duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16 | (((duk_uint32_t) ((i) >> 32)) & 0x0000ffffUL); \
970 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
971 	} while (0)
972 #define DUK__TVAL_SET_U32(tv,i)  do { \
973 		duk_tval *duk__tv; \
974 		duk__tv = (tv); \
975 		duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16; \
976 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
977 	} while (0)
978 #else
979 #define DUK__TVAL_SET_I48(tv,i)  do { \
980 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (((duk_uint64_t) (i)) & DUK_U64_CONSTANT(0x0000ffffffffffff)); \
981 	} while (0)
982 #define DUK__TVAL_SET_U32(tv,i)  do { \
983 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (duk_uint64_t) (i); \
984 	} while (0)
985 #endif
986 
987 /* This needs to go through a cast because sign extension is needed. */
988 #define DUK__TVAL_SET_I32(tv,i)  do { \
989 		duk_int64_t duk__tmp = (duk_int64_t) (i); \
990 		DUK_TVAL_SET_I48((tv), duk__tmp); \
991 	} while (0)
992 
993 /* XXX: Clumsy sign extend and masking of 16 topmost bits. */
994 #if defined(DUK_USE_DOUBLE_ME)
995 #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)
996 #else
997 #define DUK__TVAL_GET_FASTINT(tv)      ((((duk_int64_t) (tv)->ull[DUK_DBL_IDX_ULL0]) << 16) >> 16)
998 #endif
999 #define DUK__TVAL_GET_FASTINT_U32(tv)  ((tv)->ui[DUK_DBL_IDX_UI1])
1000 #define DUK__TVAL_GET_FASTINT_I32(tv)  ((duk_int32_t) (tv)->ui[DUK_DBL_IDX_UI1])
1001 #endif  /* DUK_USE_FASTINT */
1002 
1003 #define DUK_TVAL_SET_UNDEFINED(tv)  do { \
1004 		(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNDEFINED; \
1005 	} while (0)
1006 #define DUK_TVAL_SET_UNUSED(tv)  do { \
1007 		(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNUSED; \
1008 	} while (0)
1009 #define DUK_TVAL_SET_NULL(tv)  do { \
1010 		(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_NULL; \
1011 	} while (0)
1012 
1013 #define DUK_TVAL_SET_BOOLEAN(tv,val)         DUK_DBLUNION_SET_HIGH32((tv), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val)))
1014 
1015 #define DUK_TVAL_SET_NAN(tv)                 DUK_DBLUNION_SET_NAN_FULL((tv))
1016 
1017 /* Assumes that caller has normalized NaNs, otherwise trouble ahead. */
1018 #if defined(DUK_USE_FASTINT)
1019 #define DUK_TVAL_SET_DOUBLE(tv,d)  do { \
1020 		duk_double_t duk__dblval; \
1021 		duk__dblval = (d); \
1022 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
1023 		DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \
1024 	} while (0)
1025 #define DUK_TVAL_SET_I48(tv,i)               DUK__TVAL_SET_I48((tv), (i))
1026 #define DUK_TVAL_SET_I32(tv,i)               DUK__TVAL_SET_I32((tv), (i))
1027 #define DUK_TVAL_SET_U32(tv,i)               DUK__TVAL_SET_U32((tv), (i))
1028 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d)  duk_tval_set_number_chkfast_fast((tv), (d))
1029 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d)  duk_tval_set_number_chkfast_slow((tv), (d))
1030 #define DUK_TVAL_SET_NUMBER(tv,d)            DUK_TVAL_SET_DOUBLE((tv), (d))
1031 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { \
1032 		duk_tval *duk__tv; \
1033 		duk_double_t duk__d; \
1034 		duk__tv = (tv); \
1035 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1036 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1037 			DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
1038 		} \
1039 	} while (0)
1040 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { \
1041 		duk_tval *duk__tv; \
1042 		duk_double_t duk__d; \
1043 		duk__tv = (tv); \
1044 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1045 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1046 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
1047 		} \
1048 	} while (0)
1049 #else  /* DUK_USE_FASTINT */
1050 #define DUK_TVAL_SET_DOUBLE(tv,d)  do { \
1051 		duk_double_t duk__dblval; \
1052 		duk__dblval = (d); \
1053 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
1054 		DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \
1055 	} while (0)
1056 #define DUK_TVAL_SET_I48(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))  /* XXX: fast int-to-double */
1057 #define DUK_TVAL_SET_I32(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
1058 #define DUK_TVAL_SET_U32(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
1059 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d)    DUK_TVAL_SET_DOUBLE((tv), (d))
1060 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d)    DUK_TVAL_SET_DOUBLE((tv), (d))
1061 #define DUK_TVAL_SET_NUMBER(tv,d)            DUK_TVAL_SET_DOUBLE((tv), (d))
1062 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { } while (0)
1063 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { } while (0)
1064 #endif  /* DUK_USE_FASTINT */
1065 
1066 #define DUK_TVAL_SET_FASTINT(tv,i)           DUK_TVAL_SET_I48((tv), (i))  /* alias */
1067 
1068 #define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags)  DUK__TVAL_SET_LIGHTFUNC((tv), (fp), (flags))
1069 #define DUK_TVAL_SET_STRING(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_STRING)
1070 #define DUK_TVAL_SET_OBJECT(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_OBJECT)
1071 #define DUK_TVAL_SET_BUFFER(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_BUFFER)
1072 #define DUK_TVAL_SET_POINTER(tv,p)           DUK__TVAL_SET_TAGGEDPOINTER((tv), (p), DUK_TAG_POINTER)
1073 
1074 #define DUK_TVAL_SET_TVAL(tv,x)              do { *(tv) = *(x); } while (0)
1075 
1076 /* getters */
1077 #define DUK_TVAL_GET_BOOLEAN(tv)             ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US1])
1078 #if defined(DUK_USE_FASTINT)
1079 #define DUK_TVAL_GET_DOUBLE(tv)              ((tv)->d)
1080 #define DUK_TVAL_GET_FASTINT(tv)             DUK__TVAL_GET_FASTINT((tv))
1081 #define DUK_TVAL_GET_FASTINT_U32(tv)         DUK__TVAL_GET_FASTINT_U32((tv))
1082 #define DUK_TVAL_GET_FASTINT_I32(tv)         DUK__TVAL_GET_FASTINT_I32((tv))
1083 #define DUK_TVAL_GET_NUMBER(tv)              duk_tval_get_number_packed((tv))
1084 #else
1085 #define DUK_TVAL_GET_NUMBER(tv)              ((tv)->d)
1086 #define DUK_TVAL_GET_DOUBLE(tv)              ((tv)->d)
1087 #endif
1088 #define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags)  do { \
1089 		(out_flags) = (tv)->ui[DUK_DBL_IDX_UI0] & 0xffffUL; \
1090 		(out_fp) = (duk_c_function) (tv)->ui[DUK_DBL_IDX_UI1]; \
1091 	} while (0)
1092 #define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv)   ((duk_c_function) ((tv)->ui[DUK_DBL_IDX_UI1]))
1093 #define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)     (((duk_small_uint_t) (tv)->ui[DUK_DBL_IDX_UI0]) & 0xffffUL)
1094 #define DUK_TVAL_GET_STRING(tv)              ((duk_hstring *) (tv)->vp[DUK_DBL_IDX_VP1])
1095 #define DUK_TVAL_GET_OBJECT(tv)              ((duk_hobject *) (tv)->vp[DUK_DBL_IDX_VP1])
1096 #define DUK_TVAL_GET_BUFFER(tv)              ((duk_hbuffer *) (tv)->vp[DUK_DBL_IDX_VP1])
1097 #define DUK_TVAL_GET_POINTER(tv)             ((void *) (tv)->vp[DUK_DBL_IDX_VP1])
1098 #define DUK_TVAL_GET_HEAPHDR(tv)             ((duk_heaphdr *) (tv)->vp[DUK_DBL_IDX_VP1])
1099 
1100 /* decoding */
1101 #define DUK_TVAL_GET_TAG(tv)                 ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US0])
1102 
1103 #define DUK_TVAL_IS_UNDEFINED(tv)            (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNDEFINED)
1104 #define DUK_TVAL_IS_UNUSED(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNUSED)
1105 #define DUK_TVAL_IS_NULL(tv)                 (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_NULL)
1106 #define DUK_TVAL_IS_BOOLEAN(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BOOLEAN)
1107 #define DUK_TVAL_IS_BOOLEAN_TRUE(tv)         ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_TRUE)
1108 #define DUK_TVAL_IS_BOOLEAN_FALSE(tv)        ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_FALSE)
1109 #define DUK_TVAL_IS_LIGHTFUNC(tv)            (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_LIGHTFUNC)
1110 #define DUK_TVAL_IS_STRING(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_STRING)
1111 #define DUK_TVAL_IS_OBJECT(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_OBJECT)
1112 #define DUK_TVAL_IS_BUFFER(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BUFFER)
1113 #define DUK_TVAL_IS_POINTER(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_POINTER)
1114 #if defined(DUK_USE_FASTINT)
1115 /* 0xfff0 is -Infinity */
1116 #define DUK_TVAL_IS_DOUBLE(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
1117 #define DUK_TVAL_IS_FASTINT(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_FASTINT)
1118 #define DUK_TVAL_IS_NUMBER(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff1UL)
1119 #else
1120 #define DUK_TVAL_IS_NUMBER(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
1121 #define DUK_TVAL_IS_DOUBLE(tv)               DUK_TVAL_IS_NUMBER((tv))
1122 #endif
1123 
1124 /* This is performance critical because it appears in every DECREF. */
1125 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv)       (DUK_TVAL_GET_TAG((tv)) >= DUK_TAG_STRING)
1126 
1127 #if defined(DUK_USE_FASTINT)
1128 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_packed(duk_tval *tv);
1129 #endif
1130 
1131 #else  /* DUK_USE_PACKED_TVAL */
1132 /* ======================================================================== */
1133 
1134 /*
1135  *  Portable 12-byte representation
1136  */
1137 
1138 /* Note: not initializing all bytes is normally not an issue: Duktape won't
1139  * read or use the uninitialized bytes so valgrind won't issue warnings.
1140  * In some special cases a harmless valgrind warning may be issued though.
1141  * For example, the DumpHeap debugger command writes out a compiled function's
1142  * 'data' area as is, including any uninitialized bytes, which causes a
1143  * valgrind warning.
1144  */
1145 
1146 typedef struct duk_tval_struct duk_tval;
1147 
1148 struct duk_tval_struct {
1149 	duk_small_uint_t t;
1150 	duk_small_uint_t v_extra;
1151 	union {
1152 		duk_double_t d;
1153 		duk_small_int_t i;
1154 #if defined(DUK_USE_FASTINT)
1155 		duk_int64_t fi;  /* if present, forces 16-byte duk_tval */
1156 #endif
1157 		void *voidptr;
1158 		duk_hstring *hstring;
1159 		duk_hobject *hobject;
1160 		duk_hcompfunc *hcompfunc;
1161 		duk_hnatfunc *hnatfunc;
1162 		duk_hthread *hthread;
1163 		duk_hbuffer *hbuffer;
1164 		duk_heaphdr *heaphdr;
1165 		duk_c_function lightfunc;
1166 	} v;
1167 };
1168 
1169 typedef struct {
1170 	duk_small_uint_t t;
1171 	duk_small_uint_t v_extra;
1172 	/* The rest of the fields don't matter except for debug dumps and such
1173 	 * for which a partial initializer may trigger out-ot-bounds memory
1174 	 * reads.  Include a double field which is usually as large or larger
1175 	 * than pointers (not always however).
1176 	 */
1177 	duk_double_t d;
1178 } duk_tval_unused;
1179 
1180 #define DUK_TVAL_UNUSED_INITIALIZER() \
1181 	{ DUK_TAG_UNUSED, 0, 0.0 }
1182 
1183 #define DUK_TAG_MIN                   0
1184 #define DUK_TAG_NUMBER                0  /* DUK_TAG_NUMBER only defined for non-packed duk_tval */
1185 #if defined(DUK_USE_FASTINT)
1186 #define DUK_TAG_FASTINT               1
1187 #endif
1188 #define DUK_TAG_UNDEFINED             2
1189 #define DUK_TAG_NULL                  3
1190 #define DUK_TAG_BOOLEAN               4
1191 #define DUK_TAG_POINTER               5
1192 #define DUK_TAG_LIGHTFUNC             6
1193 #define DUK_TAG_UNUSED                7  /* marker; not actual tagged type */
1194 #define DUK_TAG_STRING                8  /* first heap allocated, match bit boundary */
1195 #define DUK_TAG_OBJECT                9
1196 #define DUK_TAG_BUFFER                10
1197 #define DUK_TAG_MAX                   10
1198 
1199 #define DUK_TVAL_IS_VALID_TAG(tv) \
1200 	(DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)
1201 
1202 /* DUK_TAG_NUMBER is intentionally first, as it is the default clause in code
1203  * to support the 8-byte representation.  Further, it is a non-heap-allocated
1204  * type so it should come before DUK_TAG_STRING.  Finally, it should not break
1205  * the tag value ranges covered by case-clauses in a switch-case.
1206  */
1207 
1208 /* setters */
1209 #define DUK_TVAL_SET_UNDEFINED(tv)  do { \
1210 		duk_tval *duk__tv; \
1211 		duk__tv = (tv); \
1212 		duk__tv->t = DUK_TAG_UNDEFINED; \
1213 	} while (0)
1214 
1215 #define DUK_TVAL_SET_UNUSED(tv)  do { \
1216 		duk_tval *duk__tv; \
1217 		duk__tv = (tv); \
1218 		duk__tv->t = DUK_TAG_UNUSED; \
1219 	} while (0)
1220 
1221 #define DUK_TVAL_SET_NULL(tv)  do { \
1222 		duk_tval *duk__tv; \
1223 		duk__tv = (tv); \
1224 		duk__tv->t = DUK_TAG_NULL; \
1225 	} while (0)
1226 
1227 #define DUK_TVAL_SET_BOOLEAN(tv,val)  do { \
1228 		duk_tval *duk__tv; \
1229 		duk__tv = (tv); \
1230 		duk__tv->t = DUK_TAG_BOOLEAN; \
1231 		duk__tv->v.i = (duk_small_int_t) (val); \
1232 	} while (0)
1233 
1234 #if defined(DUK_USE_FASTINT)
1235 #define DUK_TVAL_SET_DOUBLE(tv,val)  do { \
1236 		duk_tval *duk__tv; \
1237 		duk_double_t duk__dblval; \
1238 		duk__dblval = (val); \
1239 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \
1240 		duk__tv = (tv); \
1241 		duk__tv->t = DUK_TAG_NUMBER; \
1242 		duk__tv->v.d = duk__dblval; \
1243 	} while (0)
1244 #define DUK_TVAL_SET_I48(tv,val)  do { \
1245 		duk_tval *duk__tv; \
1246 		duk__tv = (tv); \
1247 		duk__tv->t = DUK_TAG_FASTINT; \
1248 		duk__tv->v.fi = (val); \
1249 	} while (0)
1250 #define DUK_TVAL_SET_U32(tv,val)  do { \
1251 		duk_tval *duk__tv; \
1252 		duk__tv = (tv); \
1253 		duk__tv->t = DUK_TAG_FASTINT; \
1254 		duk__tv->v.fi = (duk_int64_t) (val); \
1255 	} while (0)
1256 #define DUK_TVAL_SET_I32(tv,val)  do { \
1257 		duk_tval *duk__tv; \
1258 		duk__tv = (tv); \
1259 		duk__tv->t = DUK_TAG_FASTINT; \
1260 		duk__tv->v.fi = (duk_int64_t) (val); \
1261 	} while (0)
1262 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \
1263 	duk_tval_set_number_chkfast_fast((tv), (d))
1264 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \
1265 	duk_tval_set_number_chkfast_slow((tv), (d))
1266 #define DUK_TVAL_SET_NUMBER(tv,val) \
1267 	DUK_TVAL_SET_DOUBLE((tv), (val))
1268 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { \
1269 		duk_tval *duk__tv; \
1270 		duk_double_t duk__d; \
1271 		duk__tv = (tv); \
1272 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1273 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1274 			DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
1275 		} \
1276 	} while (0)
1277 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { \
1278 		duk_tval *duk__tv; \
1279 		duk_double_t duk__d; \
1280 		duk__tv = (tv); \
1281 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1282 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1283 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
1284 		} \
1285 	} while (0)
1286 #else  /* DUK_USE_FASTINT */
1287 #define DUK_TVAL_SET_DOUBLE(tv,d) \
1288 	DUK_TVAL_SET_NUMBER((tv), (d))
1289 #define DUK_TVAL_SET_I48(tv,val) \
1290 	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))  /* XXX: fast int-to-double */
1291 #define DUK_TVAL_SET_U32(tv,val) \
1292 	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
1293 #define DUK_TVAL_SET_I32(tv,val) \
1294 	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
1295 #define DUK_TVAL_SET_NUMBER(tv,val)  do { \
1296 		duk_tval *duk__tv; \
1297 		duk_double_t duk__dblval; \
1298 		duk__dblval = (val); \
1299 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \
1300 		duk__tv = (tv); \
1301 		duk__tv->t = DUK_TAG_NUMBER; \
1302 		duk__tv->v.d = duk__dblval; \
1303 	} while (0)
1304 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \
1305 	DUK_TVAL_SET_NUMBER((tv), (d))
1306 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \
1307 	DUK_TVAL_SET_NUMBER((tv), (d))
1308 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { } while (0)
1309 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { } while (0)
1310 #endif  /* DUK_USE_FASTINT */
1311 
1312 #define DUK_TVAL_SET_FASTINT(tv,i) \
1313 	DUK_TVAL_SET_I48((tv), (i))  /* alias */
1314 
1315 #define DUK_TVAL_SET_POINTER(tv,hptr)  do { \
1316 		duk_tval *duk__tv; \
1317 		duk__tv = (tv); \
1318 		duk__tv->t = DUK_TAG_POINTER; \
1319 		duk__tv->v.voidptr = (hptr); \
1320 	} while (0)
1321 
1322 #define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
1323 		duk_tval *duk__tv; \
1324 		duk__tv = (tv); \
1325 		duk__tv->t = DUK_TAG_LIGHTFUNC; \
1326 		duk__tv->v_extra = (flags); \
1327 		duk__tv->v.lightfunc = (duk_c_function) (fp); \
1328 	} while (0)
1329 
1330 #define DUK_TVAL_SET_STRING(tv,hptr)  do { \
1331 		duk_tval *duk__tv; \
1332 		duk__tv = (tv); \
1333 		duk__tv->t = DUK_TAG_STRING; \
1334 		duk__tv->v.hstring = (hptr); \
1335 	} while (0)
1336 
1337 #define DUK_TVAL_SET_OBJECT(tv,hptr)  do { \
1338 		duk_tval *duk__tv; \
1339 		duk__tv = (tv); \
1340 		duk__tv->t = DUK_TAG_OBJECT; \
1341 		duk__tv->v.hobject = (hptr); \
1342 	} while (0)
1343 
1344 #define DUK_TVAL_SET_BUFFER(tv,hptr)  do { \
1345 		duk_tval *duk__tv; \
1346 		duk__tv = (tv); \
1347 		duk__tv->t = DUK_TAG_BUFFER; \
1348 		duk__tv->v.hbuffer = (hptr); \
1349 	} while (0)
1350 
1351 #define DUK_TVAL_SET_NAN(tv)  do { \
1352 		/* in non-packed representation we don't care about which NaN is used */ \
1353 		duk_tval *duk__tv; \
1354 		duk__tv = (tv); \
1355 		duk__tv->t = DUK_TAG_NUMBER; \
1356 		duk__tv->v.d = DUK_DOUBLE_NAN; \
1357 	} while (0)
1358 
1359 #define DUK_TVAL_SET_TVAL(tv,x)            do { *(tv) = *(x); } while (0)
1360 
1361 /* getters */
1362 #define DUK_TVAL_GET_BOOLEAN(tv)           ((duk_small_uint_t) (tv)->v.i)
1363 #if defined(DUK_USE_FASTINT)
1364 #define DUK_TVAL_GET_DOUBLE(tv)            ((tv)->v.d)
1365 #define DUK_TVAL_GET_FASTINT(tv)           ((tv)->v.fi)
1366 #define DUK_TVAL_GET_FASTINT_U32(tv)       ((duk_uint32_t) ((tv)->v.fi))
1367 #define DUK_TVAL_GET_FASTINT_I32(tv)       ((duk_int32_t) ((tv)->v.fi))
1368 #if 0
1369 #define DUK_TVAL_GET_NUMBER(tv)            (DUK_TVAL_IS_FASTINT((tv)) ? \
1370                                                (duk_double_t) DUK_TVAL_GET_FASTINT((tv)) : \
1371                                                DUK_TVAL_GET_DOUBLE((tv)))
1372 #define DUK_TVAL_GET_NUMBER(tv)            duk_tval_get_number_unpacked((tv))
1373 #else
1374 /* This seems reasonable overall. */
1375 #define DUK_TVAL_GET_NUMBER(tv)            (DUK_TVAL_IS_FASTINT((tv)) ? \
1376                                                duk_tval_get_number_unpacked_fastint((tv)) : \
1377                                                DUK_TVAL_GET_DOUBLE((tv)))
1378 #endif
1379 #else
1380 #define DUK_TVAL_GET_NUMBER(tv)            ((tv)->v.d)
1381 #define DUK_TVAL_GET_DOUBLE(tv)            ((tv)->v.d)
1382 #endif  /* DUK_USE_FASTINT */
1383 #define DUK_TVAL_GET_POINTER(tv)           ((tv)->v.voidptr)
1384 #define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags)  do { \
1385 		(out_flags) = (duk_uint32_t) (tv)->v_extra; \
1386 		(out_fp) = (tv)->v.lightfunc; \
1387 	} while (0)
1388 #define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((tv)->v.lightfunc)
1389 #define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)   ((duk_small_uint_t) ((tv)->v_extra))
1390 #define DUK_TVAL_GET_STRING(tv)            ((tv)->v.hstring)
1391 #define DUK_TVAL_GET_OBJECT(tv)            ((tv)->v.hobject)
1392 #define DUK_TVAL_GET_BUFFER(tv)            ((tv)->v.hbuffer)
1393 #define DUK_TVAL_GET_HEAPHDR(tv)           ((tv)->v.heaphdr)
1394 
1395 /* decoding */
1396 #define DUK_TVAL_GET_TAG(tv)               ((tv)->t)
1397 #define DUK_TVAL_IS_UNDEFINED(tv)          ((tv)->t == DUK_TAG_UNDEFINED)
1398 #define DUK_TVAL_IS_UNUSED(tv)             ((tv)->t == DUK_TAG_UNUSED)
1399 #define DUK_TVAL_IS_NULL(tv)               ((tv)->t == DUK_TAG_NULL)
1400 #define DUK_TVAL_IS_BOOLEAN(tv)            ((tv)->t == DUK_TAG_BOOLEAN)
1401 #define DUK_TVAL_IS_BOOLEAN_TRUE(tv)       (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i != 0))
1402 #define DUK_TVAL_IS_BOOLEAN_FALSE(tv)      (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i == 0))
1403 #if defined(DUK_USE_FASTINT)
1404 #define DUK_TVAL_IS_DOUBLE(tv)             ((tv)->t == DUK_TAG_NUMBER)
1405 #define DUK_TVAL_IS_FASTINT(tv)            ((tv)->t == DUK_TAG_FASTINT)
1406 #define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK_TAG_NUMBER || \
1407                                             (tv)->t == DUK_TAG_FASTINT)
1408 #else
1409 #define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK_TAG_NUMBER)
1410 #define DUK_TVAL_IS_DOUBLE(tv)             DUK_TVAL_IS_NUMBER((tv))
1411 #endif  /* DUK_USE_FASTINT */
1412 #define DUK_TVAL_IS_POINTER(tv)            ((tv)->t == DUK_TAG_POINTER)
1413 #define DUK_TVAL_IS_LIGHTFUNC(tv)          ((tv)->t == DUK_TAG_LIGHTFUNC)
1414 #define DUK_TVAL_IS_STRING(tv)             ((tv)->t == DUK_TAG_STRING)
1415 #define DUK_TVAL_IS_OBJECT(tv)             ((tv)->t == DUK_TAG_OBJECT)
1416 #define DUK_TVAL_IS_BUFFER(tv)             ((tv)->t == DUK_TAG_BUFFER)
1417 
1418 /* This is performance critical because it's needed for every DECREF.
1419  * Take advantage of the fact that the first heap allocated tag is 8,
1420  * so that bit 3 is set for all heap allocated tags (and never set for
1421  * non-heap-allocated tags).
1422  */
1423 #if 0
1424 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv)     ((tv)->t >= DUK_TAG_STRING)
1425 #endif
1426 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv)     ((tv)->t & 0x08)
1427 
1428 #if defined(DUK_USE_FASTINT)
1429 #if 0
1430 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv);
1431 #endif
1432 DUK_INTERNAL_DECL DUK_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv);
1433 #endif
1434 
1435 #endif  /* DUK_USE_PACKED_TVAL */
1436 
1437 /*
1438  *  Convenience (independent of representation)
1439  */
1440 
1441 #define DUK_TVAL_SET_BOOLEAN_TRUE(tv)        DUK_TVAL_SET_BOOLEAN((tv), 1)
1442 #define DUK_TVAL_SET_BOOLEAN_FALSE(tv)       DUK_TVAL_SET_BOOLEAN((tv), 0)
1443 
1444 #define DUK_TVAL_STRING_IS_SYMBOL(tv) \
1445 	DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING((tv)))
1446 
1447 /* Lightfunc flags packing and unpacking. */
1448 /* Sign extend: 0x0000##00 -> 0x##000000 -> sign extend to 0xssssss##.
1449  * Avoid signed shifts due to portability limitations.
1450  */
1451 #define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags) \
1452 	((duk_int32_t) (duk_int8_t) (((duk_uint16_t) (lf_flags)) >> 8))
1453 #define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags) \
1454 	(((lf_flags) >> 4) & 0x0fU)
1455 #define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags) \
1456 	((lf_flags) & 0x0fU)
1457 #define DUK_LFUNC_FLAGS_PACK(magic,length,nargs) \
1458 	((((duk_small_uint_t) (magic)) & 0xffU) << 8) | ((length) << 4) | (nargs)
1459 
1460 #define DUK_LFUNC_NARGS_VARARGS             0x0f   /* varargs marker */
1461 #define DUK_LFUNC_NARGS_MIN                 0x00
1462 #define DUK_LFUNC_NARGS_MAX                 0x0e   /* max, excl. varargs marker */
1463 #define DUK_LFUNC_LENGTH_MIN                0x00
1464 #define DUK_LFUNC_LENGTH_MAX                0x0f
1465 #define DUK_LFUNC_MAGIC_MIN                 (-0x80)
1466 #define DUK_LFUNC_MAGIC_MAX                 0x7f
1467 
1468 /* fastint constants etc */
1469 #if defined(DUK_USE_FASTINT)
1470 #define DUK_FASTINT_MIN           (DUK_I64_CONSTANT(-0x800000000000))
1471 #define DUK_FASTINT_MAX           (DUK_I64_CONSTANT(0x7fffffffffff))
1472 #define DUK_FASTINT_BITS          48
1473 
1474 DUK_INTERNAL_DECL DUK_INLINE void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x);
1475 DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x);
1476 #endif
1477 
1478 #if defined(DUK_USE_ASSERTIONS)
1479 DUK_INTERNAL_DECL void duk_tval_assert_valid(duk_tval *tv);
1480 #define DUK_TVAL_ASSERT_VALID(tv)  do { duk_tval_assert_valid((tv)); } while (0)
1481 #else
1482 #define DUK_TVAL_ASSERT_VALID(tv)  do {} while (0)
1483 #endif
1484 
1485 #endif  /* DUK_TVAL_H_INCLUDED */
1486 /* #include duk_builtins.h */
1487 /*
1488  *  Automatically generated by genbuiltins.py, do not edit!
1489  */
1490 
1491 #if !defined(DUK_BUILTINS_H_INCLUDED)
1492 #define DUK_BUILTINS_H_INCLUDED
1493 
1494 #if defined(DUK_USE_ROM_STRINGS)
1495 #error ROM support not enabled, rerun configure.py with --rom-support
1496 #else  /* DUK_USE_ROM_STRINGS */
1497 #define DUK_STRIDX_UC_UNDEFINED                                       0                              /* 'Undefined' */
1498 #define DUK_HEAP_STRING_UC_UNDEFINED(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_UNDEFINED)
1499 #define DUK_HTHREAD_STRING_UC_UNDEFINED(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_UNDEFINED)
1500 #define DUK_STRIDX_UC_NULL                                            1                              /* 'Null' */
1501 #define DUK_HEAP_STRING_UC_NULL(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NULL)
1502 #define DUK_HTHREAD_STRING_UC_NULL(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NULL)
1503 #define DUK_STRIDX_UC_SYMBOL                                          2                              /* 'Symbol' */
1504 #define DUK_HEAP_STRING_UC_SYMBOL(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_SYMBOL)
1505 #define DUK_HTHREAD_STRING_UC_SYMBOL(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_SYMBOL)
1506 #define DUK_STRIDX_UC_ARGUMENTS                                       3                              /* 'Arguments' */
1507 #define DUK_HEAP_STRING_UC_ARGUMENTS(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARGUMENTS)
1508 #define DUK_HTHREAD_STRING_UC_ARGUMENTS(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARGUMENTS)
1509 #define DUK_STRIDX_UC_OBJECT                                          4                              /* 'Object' */
1510 #define DUK_HEAP_STRING_UC_OBJECT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_OBJECT)
1511 #define DUK_HTHREAD_STRING_UC_OBJECT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_OBJECT)
1512 #define DUK_STRIDX_UC_FUNCTION                                        5                              /* 'Function' */
1513 #define DUK_HEAP_STRING_UC_FUNCTION(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_FUNCTION)
1514 #define DUK_HTHREAD_STRING_UC_FUNCTION(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_FUNCTION)
1515 #define DUK_STRIDX_ARRAY                                              6                              /* 'Array' */
1516 #define DUK_HEAP_STRING_ARRAY(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY)
1517 #define DUK_HTHREAD_STRING_ARRAY(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY)
1518 #define DUK_STRIDX_UC_STRING                                          7                              /* 'String' */
1519 #define DUK_HEAP_STRING_UC_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_STRING)
1520 #define DUK_HTHREAD_STRING_UC_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_STRING)
1521 #define DUK_STRIDX_UC_BOOLEAN                                         8                              /* 'Boolean' */
1522 #define DUK_HEAP_STRING_UC_BOOLEAN(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BOOLEAN)
1523 #define DUK_HTHREAD_STRING_UC_BOOLEAN(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BOOLEAN)
1524 #define DUK_STRIDX_UC_NUMBER                                          9                              /* 'Number' */
1525 #define DUK_HEAP_STRING_UC_NUMBER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NUMBER)
1526 #define DUK_HTHREAD_STRING_UC_NUMBER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NUMBER)
1527 #define DUK_STRIDX_DATE                                               10                             /* 'Date' */
1528 #define DUK_HEAP_STRING_DATE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATE)
1529 #define DUK_HTHREAD_STRING_DATE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATE)
1530 #define DUK_STRIDX_REG_EXP                                            11                             /* 'RegExp' */
1531 #define DUK_HEAP_STRING_REG_EXP(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REG_EXP)
1532 #define DUK_HTHREAD_STRING_REG_EXP(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_REG_EXP)
1533 #define DUK_STRIDX_UC_ERROR                                           12                             /* 'Error' */
1534 #define DUK_HEAP_STRING_UC_ERROR(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ERROR)
1535 #define DUK_HTHREAD_STRING_UC_ERROR(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ERROR)
1536 #define DUK_STRIDX_MATH                                               13                             /* 'Math' */
1537 #define DUK_HEAP_STRING_MATH(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MATH)
1538 #define DUK_HTHREAD_STRING_MATH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MATH)
1539 #define DUK_STRIDX_JSON                                               14                             /* 'JSON' */
1540 #define DUK_HEAP_STRING_JSON(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON)
1541 #define DUK_HTHREAD_STRING_JSON(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON)
1542 #define DUK_STRIDX_EMPTY_STRING                                       15                             /* '' */
1543 #define DUK_HEAP_STRING_EMPTY_STRING(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING)
1544 #define DUK_HTHREAD_STRING_EMPTY_STRING(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING)
1545 #define DUK_STRIDX_ARRAY_BUFFER                                       16                             /* 'ArrayBuffer' */
1546 #define DUK_HEAP_STRING_ARRAY_BUFFER(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER)
1547 #define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER)
1548 #define DUK_STRIDX_DATA_VIEW                                          17                             /* 'DataView' */
1549 #define DUK_HEAP_STRING_DATA_VIEW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW)
1550 #define DUK_HTHREAD_STRING_DATA_VIEW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW)
1551 #define DUK_STRIDX_INT8_ARRAY                                         18                             /* 'Int8Array' */
1552 #define DUK_HEAP_STRING_INT8_ARRAY(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY)
1553 #define DUK_HTHREAD_STRING_INT8_ARRAY(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY)
1554 #define DUK_STRIDX_UINT8_ARRAY                                        19                             /* 'Uint8Array' */
1555 #define DUK_HEAP_STRING_UINT8_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY)
1556 #define DUK_HTHREAD_STRING_UINT8_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY)
1557 #define DUK_STRIDX_UINT8_CLAMPED_ARRAY                                20                             /* 'Uint8ClampedArray' */
1558 #define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap)                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
1559 #define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr)                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
1560 #define DUK_STRIDX_INT16_ARRAY                                        21                             /* 'Int16Array' */
1561 #define DUK_HEAP_STRING_INT16_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY)
1562 #define DUK_HTHREAD_STRING_INT16_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY)
1563 #define DUK_STRIDX_UINT16_ARRAY                                       22                             /* 'Uint16Array' */
1564 #define DUK_HEAP_STRING_UINT16_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY)
1565 #define DUK_HTHREAD_STRING_UINT16_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY)
1566 #define DUK_STRIDX_INT32_ARRAY                                        23                             /* 'Int32Array' */
1567 #define DUK_HEAP_STRING_INT32_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY)
1568 #define DUK_HTHREAD_STRING_INT32_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY)
1569 #define DUK_STRIDX_UINT32_ARRAY                                       24                             /* 'Uint32Array' */
1570 #define DUK_HEAP_STRING_UINT32_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY)
1571 #define DUK_HTHREAD_STRING_UINT32_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY)
1572 #define DUK_STRIDX_FLOAT32_ARRAY                                      25                             /* 'Float32Array' */
1573 #define DUK_HEAP_STRING_FLOAT32_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY)
1574 #define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY)
1575 #define DUK_STRIDX_FLOAT64_ARRAY                                      26                             /* 'Float64Array' */
1576 #define DUK_HEAP_STRING_FLOAT64_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY)
1577 #define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY)
1578 #define DUK_STRIDX_GLOBAL                                             27                             /* 'global' */
1579 #define DUK_HEAP_STRING_GLOBAL(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL)
1580 #define DUK_HTHREAD_STRING_GLOBAL(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GLOBAL)
1581 #define DUK_STRIDX_OBJ_ENV                                            28                             /* 'ObjEnv' */
1582 #define DUK_HEAP_STRING_OBJ_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV)
1583 #define DUK_HTHREAD_STRING_OBJ_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV)
1584 #define DUK_STRIDX_DEC_ENV                                            29                             /* 'DecEnv' */
1585 #define DUK_HEAP_STRING_DEC_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV)
1586 #define DUK_HTHREAD_STRING_DEC_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV)
1587 #define DUK_STRIDX_UC_BUFFER                                          30                             /* 'Buffer' */
1588 #define DUK_HEAP_STRING_UC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER)
1589 #define DUK_HTHREAD_STRING_UC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER)
1590 #define DUK_STRIDX_UC_POINTER                                         31                             /* 'Pointer' */
1591 #define DUK_HEAP_STRING_UC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER)
1592 #define DUK_HTHREAD_STRING_UC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER)
1593 #define DUK_STRIDX_UC_THREAD                                          32                             /* 'Thread' */
1594 #define DUK_HEAP_STRING_UC_THREAD(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_THREAD)
1595 #define DUK_HTHREAD_STRING_UC_THREAD(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD)
1596 #define DUK_STRIDX_EVAL                                               33                             /* 'eval' */
1597 #define DUK_HEAP_STRING_EVAL(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EVAL)
1598 #define DUK_HTHREAD_STRING_EVAL(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EVAL)
1599 #define DUK_STRIDX_VALUE                                              34                             /* 'value' */
1600 #define DUK_HEAP_STRING_VALUE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE)
1601 #define DUK_HTHREAD_STRING_VALUE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE)
1602 #define DUK_STRIDX_WRITABLE                                           35                             /* 'writable' */
1603 #define DUK_HEAP_STRING_WRITABLE(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITABLE)
1604 #define DUK_HTHREAD_STRING_WRITABLE(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITABLE)
1605 #define DUK_STRIDX_CONFIGURABLE                                       36                             /* 'configurable' */
1606 #define DUK_HEAP_STRING_CONFIGURABLE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONFIGURABLE)
1607 #define DUK_HTHREAD_STRING_CONFIGURABLE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONFIGURABLE)
1608 #define DUK_STRIDX_ENUMERABLE                                         37                             /* 'enumerable' */
1609 #define DUK_HEAP_STRING_ENUMERABLE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUMERABLE)
1610 #define DUK_HTHREAD_STRING_ENUMERABLE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUMERABLE)
1611 #define DUK_STRIDX_JOIN                                               38                             /* 'join' */
1612 #define DUK_HEAP_STRING_JOIN(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JOIN)
1613 #define DUK_HTHREAD_STRING_JOIN(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JOIN)
1614 #define DUK_STRIDX_TO_LOCALE_STRING                                   39                             /* 'toLocaleString' */
1615 #define DUK_HEAP_STRING_TO_LOCALE_STRING(heap)                        DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_LOCALE_STRING)
1616 #define DUK_HTHREAD_STRING_TO_LOCALE_STRING(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_LOCALE_STRING)
1617 #define DUK_STRIDX_VALUE_OF                                           40                             /* 'valueOf' */
1618 #define DUK_HEAP_STRING_VALUE_OF(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE_OF)
1619 #define DUK_HTHREAD_STRING_VALUE_OF(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE_OF)
1620 #define DUK_STRIDX_TO_UTC_STRING                                      41                             /* 'toUTCString' */
1621 #define DUK_HEAP_STRING_TO_UTC_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_UTC_STRING)
1622 #define DUK_HTHREAD_STRING_TO_UTC_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_UTC_STRING)
1623 #define DUK_STRIDX_TO_ISO_STRING                                      42                             /* 'toISOString' */
1624 #define DUK_HEAP_STRING_TO_ISO_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_ISO_STRING)
1625 #define DUK_HTHREAD_STRING_TO_ISO_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_ISO_STRING)
1626 #define DUK_STRIDX_TO_GMT_STRING                                      43                             /* 'toGMTString' */
1627 #define DUK_HEAP_STRING_TO_GMT_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_GMT_STRING)
1628 #define DUK_HTHREAD_STRING_TO_GMT_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_GMT_STRING)
1629 #define DUK_STRIDX_SOURCE                                             44                             /* 'source' */
1630 #define DUK_HEAP_STRING_SOURCE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SOURCE)
1631 #define DUK_HTHREAD_STRING_SOURCE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SOURCE)
1632 #define DUK_STRIDX_IGNORE_CASE                                        45                             /* 'ignoreCase' */
1633 #define DUK_HEAP_STRING_IGNORE_CASE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IGNORE_CASE)
1634 #define DUK_HTHREAD_STRING_IGNORE_CASE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IGNORE_CASE)
1635 #define DUK_STRIDX_MULTILINE                                          46                             /* 'multiline' */
1636 #define DUK_HEAP_STRING_MULTILINE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MULTILINE)
1637 #define DUK_HTHREAD_STRING_MULTILINE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MULTILINE)
1638 #define DUK_STRIDX_LAST_INDEX                                         47                             /* 'lastIndex' */
1639 #define DUK_HEAP_STRING_LAST_INDEX(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LAST_INDEX)
1640 #define DUK_HTHREAD_STRING_LAST_INDEX(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LAST_INDEX)
1641 #define DUK_STRIDX_FLAGS                                              48                             /* 'flags' */
1642 #define DUK_HEAP_STRING_FLAGS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLAGS)
1643 #define DUK_HTHREAD_STRING_FLAGS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLAGS)
1644 #define DUK_STRIDX_INDEX                                              49                             /* 'index' */
1645 #define DUK_HEAP_STRING_INDEX(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INDEX)
1646 #define DUK_HTHREAD_STRING_INDEX(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INDEX)
1647 #define DUK_STRIDX_PROTOTYPE                                          50                             /* 'prototype' */
1648 #define DUK_HEAP_STRING_PROTOTYPE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTOTYPE)
1649 #define DUK_HTHREAD_STRING_PROTOTYPE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTOTYPE)
1650 #define DUK_STRIDX_CONSTRUCTOR                                        51                             /* 'constructor' */
1651 #define DUK_HEAP_STRING_CONSTRUCTOR(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCTOR)
1652 #define DUK_HTHREAD_STRING_CONSTRUCTOR(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCTOR)
1653 #define DUK_STRIDX_MESSAGE                                            52                             /* 'message' */
1654 #define DUK_HEAP_STRING_MESSAGE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MESSAGE)
1655 #define DUK_HTHREAD_STRING_MESSAGE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MESSAGE)
1656 #define DUK_STRIDX_LC_BOOLEAN                                         53                             /* 'boolean' */
1657 #define DUK_HEAP_STRING_LC_BOOLEAN(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BOOLEAN)
1658 #define DUK_HTHREAD_STRING_LC_BOOLEAN(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BOOLEAN)
1659 #define DUK_STRIDX_LC_NUMBER                                          54                             /* 'number' */
1660 #define DUK_HEAP_STRING_LC_NUMBER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NUMBER)
1661 #define DUK_HTHREAD_STRING_LC_NUMBER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NUMBER)
1662 #define DUK_STRIDX_LC_STRING                                          55                             /* 'string' */
1663 #define DUK_HEAP_STRING_LC_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_STRING)
1664 #define DUK_HTHREAD_STRING_LC_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_STRING)
1665 #define DUK_STRIDX_LC_SYMBOL                                          56                             /* 'symbol' */
1666 #define DUK_HEAP_STRING_LC_SYMBOL(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_SYMBOL)
1667 #define DUK_HTHREAD_STRING_LC_SYMBOL(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_SYMBOL)
1668 #define DUK_STRIDX_LC_OBJECT                                          57                             /* 'object' */
1669 #define DUK_HEAP_STRING_LC_OBJECT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_OBJECT)
1670 #define DUK_HTHREAD_STRING_LC_OBJECT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_OBJECT)
1671 #define DUK_STRIDX_LC_UNDEFINED                                       58                             /* 'undefined' */
1672 #define DUK_HEAP_STRING_LC_UNDEFINED(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_UNDEFINED)
1673 #define DUK_HTHREAD_STRING_LC_UNDEFINED(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_UNDEFINED)
1674 #define DUK_STRIDX_NAN                                                59                             /* 'NaN' */
1675 #define DUK_HEAP_STRING_NAN(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAN)
1676 #define DUK_HTHREAD_STRING_NAN(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAN)
1677 #define DUK_STRIDX_INFINITY                                           60                             /* 'Infinity' */
1678 #define DUK_HEAP_STRING_INFINITY(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INFINITY)
1679 #define DUK_HTHREAD_STRING_INFINITY(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INFINITY)
1680 #define DUK_STRIDX_MINUS_INFINITY                                     61                             /* '-Infinity' */
1681 #define DUK_HEAP_STRING_MINUS_INFINITY(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_INFINITY)
1682 #define DUK_HTHREAD_STRING_MINUS_INFINITY(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_INFINITY)
1683 #define DUK_STRIDX_MINUS_ZERO                                         62                             /* '-0' */
1684 #define DUK_HEAP_STRING_MINUS_ZERO(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_ZERO)
1685 #define DUK_HTHREAD_STRING_MINUS_ZERO(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_ZERO)
1686 #define DUK_STRIDX_COMMA                                              63                             /* ',' */
1687 #define DUK_HEAP_STRING_COMMA(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMMA)
1688 #define DUK_HTHREAD_STRING_COMMA(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMMA)
1689 #define DUK_STRIDX_NEWLINE_4SPACE                                     64                             /* '\n    ' */
1690 #define DUK_HEAP_STRING_NEWLINE_4SPACE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEWLINE_4SPACE)
1691 #define DUK_HTHREAD_STRING_NEWLINE_4SPACE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEWLINE_4SPACE)
1692 #define DUK_STRIDX_BRACKETED_ELLIPSIS                                 65                             /* '[...]' */
1693 #define DUK_HEAP_STRING_BRACKETED_ELLIPSIS(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BRACKETED_ELLIPSIS)
1694 #define DUK_HTHREAD_STRING_BRACKETED_ELLIPSIS(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BRACKETED_ELLIPSIS)
1695 #define DUK_STRIDX_INVALID_DATE                                       66                             /* 'Invalid Date' */
1696 #define DUK_HEAP_STRING_INVALID_DATE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INVALID_DATE)
1697 #define DUK_HTHREAD_STRING_INVALID_DATE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INVALID_DATE)
1698 #define DUK_STRIDX_LC_ARGUMENTS                                       67                             /* 'arguments' */
1699 #define DUK_HEAP_STRING_LC_ARGUMENTS(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_ARGUMENTS)
1700 #define DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_ARGUMENTS)
1701 #define DUK_STRIDX_CALLEE                                             68                             /* 'callee' */
1702 #define DUK_HEAP_STRING_CALLEE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLEE)
1703 #define DUK_HTHREAD_STRING_CALLEE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLEE)
1704 #define DUK_STRIDX_CALLER                                             69                             /* 'caller' */
1705 #define DUK_HEAP_STRING_CALLER(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLER)
1706 #define DUK_HTHREAD_STRING_CALLER(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLER)
1707 #define DUK_STRIDX_APPLY                                              70                             /* 'apply' */
1708 #define DUK_HEAP_STRING_APPLY(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_APPLY)
1709 #define DUK_HTHREAD_STRING_APPLY(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_APPLY)
1710 #define DUK_STRIDX_CONSTRUCT                                          71                             /* 'construct' */
1711 #define DUK_HEAP_STRING_CONSTRUCT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCT)
1712 #define DUK_HTHREAD_STRING_CONSTRUCT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCT)
1713 #define DUK_STRIDX_DELETE_PROPERTY                                    72                             /* 'deleteProperty' */
1714 #define DUK_HEAP_STRING_DELETE_PROPERTY(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE_PROPERTY)
1715 #define DUK_HTHREAD_STRING_DELETE_PROPERTY(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE_PROPERTY)
1716 #define DUK_STRIDX_GET                                                73                             /* 'get' */
1717 #define DUK_HEAP_STRING_GET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET)
1718 #define DUK_HTHREAD_STRING_GET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET)
1719 #define DUK_STRIDX_HAS                                                74                             /* 'has' */
1720 #define DUK_HEAP_STRING_HAS(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HAS)
1721 #define DUK_HTHREAD_STRING_HAS(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HAS)
1722 #define DUK_STRIDX_OWN_KEYS                                           75                             /* 'ownKeys' */
1723 #define DUK_HEAP_STRING_OWN_KEYS(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OWN_KEYS)
1724 #define DUK_HTHREAD_STRING_OWN_KEYS(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OWN_KEYS)
1725 #define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE                      76                             /* '\x81Symbol.toPrimitive\xff' */
1726 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_TO_PRIMITIVE(heap)           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)
1727 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_TO_PRIMITIVE(thr)         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)
1728 #define DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE                      77                             /* '\x81Symbol.hasInstance\xff' */
1729 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_HAS_INSTANCE(heap)           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)
1730 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_HAS_INSTANCE(thr)         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)
1731 #define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG                     78                             /* '\x81Symbol.toStringTag\xff' */
1732 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_TO_STRING_TAG(heap)          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG)
1733 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_TO_STRING_TAG(thr)        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG)
1734 #define DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE              79                             /* '\x81Symbol.isConcatSpreadable\xff' */
1735 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE(heap)   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE)
1736 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE(thr)  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE)
1737 #define DUK_STRIDX_SET_PROTOTYPE_OF                                   80                             /* 'setPrototypeOf' */
1738 #define DUK_HEAP_STRING_SET_PROTOTYPE_OF(heap)                        DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_PROTOTYPE_OF)
1739 #define DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_PROTOTYPE_OF)
1740 #define DUK_STRIDX___PROTO__                                          81                             /* '__proto__' */
1741 #define DUK_HEAP_STRING___PROTO__(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX___PROTO__)
1742 #define DUK_HTHREAD_STRING___PROTO__(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX___PROTO__)
1743 #define DUK_STRIDX_TO_STRING                                          82                             /* 'toString' */
1744 #define DUK_HEAP_STRING_TO_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_STRING)
1745 #define DUK_HTHREAD_STRING_TO_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_STRING)
1746 #define DUK_STRIDX_TO_JSON                                            83                             /* 'toJSON' */
1747 #define DUK_HEAP_STRING_TO_JSON(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_JSON)
1748 #define DUK_HTHREAD_STRING_TO_JSON(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_JSON)
1749 #define DUK_STRIDX_TYPE                                               84                             /* 'type' */
1750 #define DUK_HEAP_STRING_TYPE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE)
1751 #define DUK_HTHREAD_STRING_TYPE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE)
1752 #define DUK_STRIDX_DATA                                               85                             /* 'data' */
1753 #define DUK_HEAP_STRING_DATA(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA)
1754 #define DUK_HTHREAD_STRING_DATA(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA)
1755 #define DUK_STRIDX_LENGTH                                             86                             /* 'length' */
1756 #define DUK_HEAP_STRING_LENGTH(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LENGTH)
1757 #define DUK_HTHREAD_STRING_LENGTH(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LENGTH)
1758 #define DUK_STRIDX_SET                                                87                             /* 'set' */
1759 #define DUK_HEAP_STRING_SET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET)
1760 #define DUK_HTHREAD_STRING_SET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET)
1761 #define DUK_STRIDX_STACK                                              88                             /* 'stack' */
1762 #define DUK_HEAP_STRING_STACK(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STACK)
1763 #define DUK_HTHREAD_STRING_STACK(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STACK)
1764 #define DUK_STRIDX_PC                                                 89                             /* 'pc' */
1765 #define DUK_HEAP_STRING_PC(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PC)
1766 #define DUK_HTHREAD_STRING_PC(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PC)
1767 #define DUK_STRIDX_LINE_NUMBER                                        90                             /* 'lineNumber' */
1768 #define DUK_HEAP_STRING_LINE_NUMBER(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER)
1769 #define DUK_HTHREAD_STRING_LINE_NUMBER(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER)
1770 #define DUK_STRIDX_INT_TRACEDATA                                      91                             /* '\x82Tracedata' */
1771 #define DUK_HEAP_STRING_INT_TRACEDATA(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA)
1772 #define DUK_HTHREAD_STRING_INT_TRACEDATA(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA)
1773 #define DUK_STRIDX_NAME                                               92                             /* 'name' */
1774 #define DUK_HEAP_STRING_NAME(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAME)
1775 #define DUK_HTHREAD_STRING_NAME(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAME)
1776 #define DUK_STRIDX_FILE_NAME                                          93                             /* 'fileName' */
1777 #define DUK_HEAP_STRING_FILE_NAME(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME)
1778 #define DUK_HTHREAD_STRING_FILE_NAME(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILE_NAME)
1779 #define DUK_STRIDX_LC_POINTER                                         94                             /* 'pointer' */
1780 #define DUK_HEAP_STRING_LC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER)
1781 #define DUK_HTHREAD_STRING_LC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER)
1782 #define DUK_STRIDX_INT_TARGET                                         95                             /* '\x82Target' */
1783 #define DUK_HEAP_STRING_INT_TARGET(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TARGET)
1784 #define DUK_HTHREAD_STRING_INT_TARGET(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TARGET)
1785 #define DUK_STRIDX_INT_NEXT                                           96                             /* '\x82Next' */
1786 #define DUK_HEAP_STRING_INT_NEXT(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_NEXT)
1787 #define DUK_HTHREAD_STRING_INT_NEXT(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_NEXT)
1788 #define DUK_STRIDX_INT_BYTECODE                                       97                             /* '\x82Bytecode' */
1789 #define DUK_HEAP_STRING_INT_BYTECODE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_BYTECODE)
1790 #define DUK_HTHREAD_STRING_INT_BYTECODE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_BYTECODE)
1791 #define DUK_STRIDX_INT_FORMALS                                        98                             /* '\x82Formals' */
1792 #define DUK_HEAP_STRING_INT_FORMALS(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FORMALS)
1793 #define DUK_HTHREAD_STRING_INT_FORMALS(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FORMALS)
1794 #define DUK_STRIDX_INT_VARMAP                                         99                             /* '\x82Varmap' */
1795 #define DUK_HEAP_STRING_INT_VARMAP(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARMAP)
1796 #define DUK_HTHREAD_STRING_INT_VARMAP(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARMAP)
1797 #define DUK_STRIDX_INT_SOURCE                                         100                            /* '\x82Source' */
1798 #define DUK_HEAP_STRING_INT_SOURCE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_SOURCE)
1799 #define DUK_HTHREAD_STRING_INT_SOURCE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_SOURCE)
1800 #define DUK_STRIDX_INT_PC2LINE                                        101                            /* '\x82Pc2line' */
1801 #define DUK_HEAP_STRING_INT_PC2LINE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_PC2LINE)
1802 #define DUK_HTHREAD_STRING_INT_PC2LINE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_PC2LINE)
1803 #define DUK_STRIDX_INT_MAP                                            102                            /* '\x82Map' */
1804 #define DUK_HEAP_STRING_INT_MAP(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_MAP)
1805 #define DUK_HTHREAD_STRING_INT_MAP(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_MAP)
1806 #define DUK_STRIDX_INT_VARENV                                         103                            /* '\x82Varenv' */
1807 #define DUK_HEAP_STRING_INT_VARENV(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARENV)
1808 #define DUK_HTHREAD_STRING_INT_VARENV(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARENV)
1809 #define DUK_STRIDX_INT_FINALIZER                                      104                            /* '\x82Finalizer' */
1810 #define DUK_HEAP_STRING_INT_FINALIZER(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FINALIZER)
1811 #define DUK_HTHREAD_STRING_INT_FINALIZER(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FINALIZER)
1812 #define DUK_STRIDX_INT_VALUE                                          105                            /* '\x82Value' */
1813 #define DUK_HEAP_STRING_INT_VALUE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VALUE)
1814 #define DUK_HTHREAD_STRING_INT_VALUE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE)
1815 #define DUK_STRIDX_COMPILE                                            106                            /* 'compile' */
1816 #define DUK_HEAP_STRING_COMPILE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPILE)
1817 #define DUK_HTHREAD_STRING_COMPILE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPILE)
1818 #define DUK_STRIDX_INPUT                                              107                            /* 'input' */
1819 #define DUK_HEAP_STRING_INPUT(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INPUT)
1820 #define DUK_HTHREAD_STRING_INPUT(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INPUT)
1821 #define DUK_STRIDX_ERR_CREATE                                         108                            /* 'errCreate' */
1822 #define DUK_HEAP_STRING_ERR_CREATE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_CREATE)
1823 #define DUK_HTHREAD_STRING_ERR_CREATE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_CREATE)
1824 #define DUK_STRIDX_ERR_THROW                                          109                            /* 'errThrow' */
1825 #define DUK_HEAP_STRING_ERR_THROW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_THROW)
1826 #define DUK_HTHREAD_STRING_ERR_THROW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_THROW)
1827 #define DUK_STRIDX_ENV                                                110                            /* 'env' */
1828 #define DUK_HEAP_STRING_ENV(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENV)
1829 #define DUK_HTHREAD_STRING_ENV(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENV)
1830 #define DUK_STRIDX_HEX                                                111                            /* 'hex' */
1831 #define DUK_HEAP_STRING_HEX(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HEX)
1832 #define DUK_HTHREAD_STRING_HEX(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HEX)
1833 #define DUK_STRIDX_BASE64                                             112                            /* 'base64' */
1834 #define DUK_HEAP_STRING_BASE64(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BASE64)
1835 #define DUK_HTHREAD_STRING_BASE64(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BASE64)
1836 #define DUK_STRIDX_JX                                                 113                            /* 'jx' */
1837 #define DUK_HEAP_STRING_JX(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JX)
1838 #define DUK_HTHREAD_STRING_JX(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JX)
1839 #define DUK_STRIDX_JC                                                 114                            /* 'jc' */
1840 #define DUK_HEAP_STRING_JC(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JC)
1841 #define DUK_HTHREAD_STRING_JC(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JC)
1842 #define DUK_STRIDX_JSON_EXT_UNDEFINED                                 115                            /* '{"_undef":true}' */
1843 #define DUK_HEAP_STRING_JSON_EXT_UNDEFINED(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_UNDEFINED)
1844 #define DUK_HTHREAD_STRING_JSON_EXT_UNDEFINED(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_UNDEFINED)
1845 #define DUK_STRIDX_JSON_EXT_NAN                                       116                            /* '{"_nan":true}' */
1846 #define DUK_HEAP_STRING_JSON_EXT_NAN(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NAN)
1847 #define DUK_HTHREAD_STRING_JSON_EXT_NAN(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NAN)
1848 #define DUK_STRIDX_JSON_EXT_POSINF                                    117                            /* '{"_inf":true}' */
1849 #define DUK_HEAP_STRING_JSON_EXT_POSINF(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_POSINF)
1850 #define DUK_HTHREAD_STRING_JSON_EXT_POSINF(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_POSINF)
1851 #define DUK_STRIDX_JSON_EXT_NEGINF                                    118                            /* '{"_ninf":true}' */
1852 #define DUK_HEAP_STRING_JSON_EXT_NEGINF(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NEGINF)
1853 #define DUK_HTHREAD_STRING_JSON_EXT_NEGINF(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NEGINF)
1854 #define DUK_STRIDX_JSON_EXT_FUNCTION1                                 119                            /* '{"_func":true}' */
1855 #define DUK_HEAP_STRING_JSON_EXT_FUNCTION1(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION1)
1856 #define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION1(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION1)
1857 #define DUK_STRIDX_JSON_EXT_FUNCTION2                                 120                            /* '{_func:true}' */
1858 #define DUK_HEAP_STRING_JSON_EXT_FUNCTION2(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION2)
1859 #define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION2(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION2)
1860 #define DUK_STRIDX_BREAK                                              121                            /* 'break' */
1861 #define DUK_HEAP_STRING_BREAK(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BREAK)
1862 #define DUK_HTHREAD_STRING_BREAK(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BREAK)
1863 #define DUK_STRIDX_CASE                                               122                            /* 'case' */
1864 #define DUK_HEAP_STRING_CASE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CASE)
1865 #define DUK_HTHREAD_STRING_CASE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CASE)
1866 #define DUK_STRIDX_CATCH                                              123                            /* 'catch' */
1867 #define DUK_HEAP_STRING_CATCH(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CATCH)
1868 #define DUK_HTHREAD_STRING_CATCH(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CATCH)
1869 #define DUK_STRIDX_CONTINUE                                           124                            /* 'continue' */
1870 #define DUK_HEAP_STRING_CONTINUE(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONTINUE)
1871 #define DUK_HTHREAD_STRING_CONTINUE(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONTINUE)
1872 #define DUK_STRIDX_DEBUGGER                                           125                            /* 'debugger' */
1873 #define DUK_HEAP_STRING_DEBUGGER(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEBUGGER)
1874 #define DUK_HTHREAD_STRING_DEBUGGER(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEBUGGER)
1875 #define DUK_STRIDX_DEFAULT                                            126                            /* 'default' */
1876 #define DUK_HEAP_STRING_DEFAULT(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFAULT)
1877 #define DUK_HTHREAD_STRING_DEFAULT(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFAULT)
1878 #define DUK_STRIDX_DELETE                                             127                            /* 'delete' */
1879 #define DUK_HEAP_STRING_DELETE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE)
1880 #define DUK_HTHREAD_STRING_DELETE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE)
1881 #define DUK_STRIDX_DO                                                 128                            /* 'do' */
1882 #define DUK_HEAP_STRING_DO(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DO)
1883 #define DUK_HTHREAD_STRING_DO(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DO)
1884 #define DUK_STRIDX_ELSE                                               129                            /* 'else' */
1885 #define DUK_HEAP_STRING_ELSE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ELSE)
1886 #define DUK_HTHREAD_STRING_ELSE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ELSE)
1887 #define DUK_STRIDX_FINALLY                                            130                            /* 'finally' */
1888 #define DUK_HEAP_STRING_FINALLY(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FINALLY)
1889 #define DUK_HTHREAD_STRING_FINALLY(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FINALLY)
1890 #define DUK_STRIDX_FOR                                                131                            /* 'for' */
1891 #define DUK_HEAP_STRING_FOR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FOR)
1892 #define DUK_HTHREAD_STRING_FOR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FOR)
1893 #define DUK_STRIDX_LC_FUNCTION                                        132                            /* 'function' */
1894 #define DUK_HEAP_STRING_LC_FUNCTION(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FUNCTION)
1895 #define DUK_HTHREAD_STRING_LC_FUNCTION(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FUNCTION)
1896 #define DUK_STRIDX_IF                                                 133                            /* 'if' */
1897 #define DUK_HEAP_STRING_IF(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IF)
1898 #define DUK_HTHREAD_STRING_IF(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IF)
1899 #define DUK_STRIDX_IN                                                 134                            /* 'in' */
1900 #define DUK_HEAP_STRING_IN(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IN)
1901 #define DUK_HTHREAD_STRING_IN(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IN)
1902 #define DUK_STRIDX_INSTANCEOF                                         135                            /* 'instanceof' */
1903 #define DUK_HEAP_STRING_INSTANCEOF(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INSTANCEOF)
1904 #define DUK_HTHREAD_STRING_INSTANCEOF(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INSTANCEOF)
1905 #define DUK_STRIDX_NEW                                                136                            /* 'new' */
1906 #define DUK_HEAP_STRING_NEW(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEW)
1907 #define DUK_HTHREAD_STRING_NEW(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEW)
1908 #define DUK_STRIDX_RETURN                                             137                            /* 'return' */
1909 #define DUK_HEAP_STRING_RETURN(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RETURN)
1910 #define DUK_HTHREAD_STRING_RETURN(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RETURN)
1911 #define DUK_STRIDX_SWITCH                                             138                            /* 'switch' */
1912 #define DUK_HEAP_STRING_SWITCH(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SWITCH)
1913 #define DUK_HTHREAD_STRING_SWITCH(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SWITCH)
1914 #define DUK_STRIDX_THIS                                               139                            /* 'this' */
1915 #define DUK_HEAP_STRING_THIS(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THIS)
1916 #define DUK_HTHREAD_STRING_THIS(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THIS)
1917 #define DUK_STRIDX_THROW                                              140                            /* 'throw' */
1918 #define DUK_HEAP_STRING_THROW(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THROW)
1919 #define DUK_HTHREAD_STRING_THROW(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW)
1920 #define DUK_STRIDX_TRY                                                141                            /* 'try' */
1921 #define DUK_HEAP_STRING_TRY(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRY)
1922 #define DUK_HTHREAD_STRING_TRY(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRY)
1923 #define DUK_STRIDX_TYPEOF                                             142                            /* 'typeof' */
1924 #define DUK_HEAP_STRING_TYPEOF(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPEOF)
1925 #define DUK_HTHREAD_STRING_TYPEOF(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
1926 #define DUK_STRIDX_VAR                                                143                            /* 'var' */
1927 #define DUK_HEAP_STRING_VAR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR)
1928 #define DUK_HTHREAD_STRING_VAR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR)
1929 #define DUK_STRIDX_CONST                                              144                            /* 'const' */
1930 #define DUK_HEAP_STRING_CONST(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
1931 #define DUK_HTHREAD_STRING_CONST(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
1932 #define DUK_STRIDX_VOID                                               145                            /* 'void' */
1933 #define DUK_HEAP_STRING_VOID(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID)
1934 #define DUK_HTHREAD_STRING_VOID(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID)
1935 #define DUK_STRIDX_WHILE                                              146                            /* 'while' */
1936 #define DUK_HEAP_STRING_WHILE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
1937 #define DUK_HTHREAD_STRING_WHILE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WHILE)
1938 #define DUK_STRIDX_WITH                                               147                            /* 'with' */
1939 #define DUK_HEAP_STRING_WITH(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WITH)
1940 #define DUK_HTHREAD_STRING_WITH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
1941 #define DUK_STRIDX_CLASS                                              148                            /* 'class' */
1942 #define DUK_HEAP_STRING_CLASS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS)
1943 #define DUK_HTHREAD_STRING_CLASS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS)
1944 #define DUK_STRIDX_ENUM                                               149                            /* 'enum' */
1945 #define DUK_HEAP_STRING_ENUM(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM)
1946 #define DUK_HTHREAD_STRING_ENUM(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM)
1947 #define DUK_STRIDX_EXPORT                                             150                            /* 'export' */
1948 #define DUK_HEAP_STRING_EXPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
1949 #define DUK_HTHREAD_STRING_EXPORT(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORT)
1950 #define DUK_STRIDX_EXTENDS                                            151                            /* 'extends' */
1951 #define DUK_HEAP_STRING_EXTENDS(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXTENDS)
1952 #define DUK_HTHREAD_STRING_EXTENDS(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXTENDS)
1953 #define DUK_STRIDX_IMPORT                                             152                            /* 'import' */
1954 #define DUK_HEAP_STRING_IMPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPORT)
1955 #define DUK_HTHREAD_STRING_IMPORT(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPORT)
1956 #define DUK_STRIDX_SUPER                                              153                            /* 'super' */
1957 #define DUK_HEAP_STRING_SUPER(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUPER)
1958 #define DUK_HTHREAD_STRING_SUPER(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUPER)
1959 #define DUK_STRIDX_LC_NULL                                            154                            /* 'null' */
1960 #define DUK_HEAP_STRING_LC_NULL(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NULL)
1961 #define DUK_HTHREAD_STRING_LC_NULL(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NULL)
1962 #define DUK_STRIDX_TRUE                                               155                            /* 'true' */
1963 #define DUK_HEAP_STRING_TRUE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRUE)
1964 #define DUK_HTHREAD_STRING_TRUE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRUE)
1965 #define DUK_STRIDX_FALSE                                              156                            /* 'false' */
1966 #define DUK_HEAP_STRING_FALSE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FALSE)
1967 #define DUK_HTHREAD_STRING_FALSE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FALSE)
1968 #define DUK_STRIDX_IMPLEMENTS                                         157                            /* 'implements' */
1969 #define DUK_HEAP_STRING_IMPLEMENTS(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPLEMENTS)
1970 #define DUK_HTHREAD_STRING_IMPLEMENTS(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPLEMENTS)
1971 #define DUK_STRIDX_INTERFACE                                          158                            /* 'interface' */
1972 #define DUK_HEAP_STRING_INTERFACE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INTERFACE)
1973 #define DUK_HTHREAD_STRING_INTERFACE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INTERFACE)
1974 #define DUK_STRIDX_LET                                                159                            /* 'let' */
1975 #define DUK_HEAP_STRING_LET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LET)
1976 #define DUK_HTHREAD_STRING_LET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LET)
1977 #define DUK_STRIDX_PACKAGE                                            160                            /* 'package' */
1978 #define DUK_HEAP_STRING_PACKAGE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PACKAGE)
1979 #define DUK_HTHREAD_STRING_PACKAGE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PACKAGE)
1980 #define DUK_STRIDX_PRIVATE                                            161                            /* 'private' */
1981 #define DUK_HEAP_STRING_PRIVATE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PRIVATE)
1982 #define DUK_HTHREAD_STRING_PRIVATE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PRIVATE)
1983 #define DUK_STRIDX_PROTECTED                                          162                            /* 'protected' */
1984 #define DUK_HEAP_STRING_PROTECTED(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTECTED)
1985 #define DUK_HTHREAD_STRING_PROTECTED(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTECTED)
1986 #define DUK_STRIDX_PUBLIC                                             163                            /* 'public' */
1987 #define DUK_HEAP_STRING_PUBLIC(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PUBLIC)
1988 #define DUK_HTHREAD_STRING_PUBLIC(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PUBLIC)
1989 #define DUK_STRIDX_STATIC                                             164                            /* 'static' */
1990 #define DUK_HEAP_STRING_STATIC(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STATIC)
1991 #define DUK_HTHREAD_STRING_STATIC(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STATIC)
1992 #define DUK_STRIDX_YIELD                                              165                            /* 'yield' */
1993 #define DUK_HEAP_STRING_YIELD(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD)
1994 #define DUK_HTHREAD_STRING_YIELD(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD)
1995 
1996 #define DUK_HEAP_NUM_STRINGS                                          166
1997 #define DUK_STRIDX_START_RESERVED                                     121
1998 #define DUK_STRIDX_START_STRICT_RESERVED                              157
1999 #define DUK_STRIDX_END_RESERVED                                       166                            /* exclusive endpoint */
2000 
2001 /* To convert a heap stridx to a token number, subtract
2002  * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
2003  */
2004 #if !defined(DUK_SINGLE_FILE)
2005 DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[967];
2006 #endif  /* !DUK_SINGLE_FILE */
2007 #define DUK_STRDATA_MAX_STRLEN                                        27
2008 #define DUK_STRDATA_DATA_LENGTH                                       967
2009 #endif  /* DUK_USE_ROM_STRINGS */
2010 
2011 #if defined(DUK_USE_ROM_OBJECTS)
2012 #error RAM support not enabled, rerun configure.py with --ram-support
2013 #else  /* DUK_USE_ROM_OBJECTS */
2014 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor(duk_context *ctx);
2015 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_constructor(duk_context *ctx);
2016 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_context *ctx);
2017 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor(duk_context *ctx);
2018 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor(duk_context *ctx);
2019 DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx);
2020 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_constructor(duk_context *ctx);
2021 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor(duk_context *ctx);
2022 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx);
2023 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx);
2024 DUK_INTERNAL_DECL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx);
2025 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx);
2026 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx);
2027 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_constructor(duk_context *ctx);
2028 DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx);
2029 DUK_INTERNAL_DECL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx);
2030 DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_constructor_shared(duk_context *ctx);
2031 DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx);
2032 DUK_INTERNAL_DECL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx);
2033 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx);
2034 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx);
2035 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_constructor(duk_context *ctx);
2036 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_constructor(duk_context *ctx);
2037 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_eval(duk_context *ctx);
2038 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx);
2039 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx);
2040 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx);
2041 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx);
2042 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx);
2043 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx);
2044 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_escape(duk_context *ctx);
2045 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx);
2046 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx);
2047 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx);
2048 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx);
2049 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx);
2050 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_assign(duk_context *ctx);
2051 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx);
2052 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx);
2053 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx);
2054 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx);
2055 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx);
2056 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx);
2057 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx);
2058 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is(duk_context *ctx);
2059 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx);
2060 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx);
2061 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx);
2062 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx);
2063 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx);
2064 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx);
2065 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_defineaccessor(duk_context *ctx);
2066 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_context *ctx);
2067 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx);
2068 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx);
2069 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx);
2070 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx);
2071 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_hasinstance(duk_context *ctx);
2072 DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_length(duk_context *ctx);
2073 DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_name(duk_context *ctx);
2074 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx);
2075 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx);
2076 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx);
2077 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx);
2078 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx);
2079 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx);
2080 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx);
2081 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx);
2082 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx);
2083 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx);
2084 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx);
2085 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx);
2086 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx);
2087 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx);
2088 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx);
2089 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx);
2090 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_code_point(duk_context *ctx);
2091 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx);
2092 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx);
2093 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx);
2094 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx);
2095 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx);
2096 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx);
2097 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx);
2098 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx);
2099 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx);
2100 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx);
2101 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx);
2102 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx);
2103 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx);
2104 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx);
2105 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_repeat(duk_context *ctx);
2106 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_context *ctx);
2107 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_includes(duk_context *ctx);
2108 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx);
2109 DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx);
2110 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_check_shared(duk_context *ctx);
2111 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx);
2112 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx);
2113 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx);
2114 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx);
2115 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx);
2116 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx);
2117 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx);
2118 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx);
2119 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_now(duk_context *ctx);
2120 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx);
2121 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx);
2122 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx);
2123 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx);
2124 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx);
2125 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx);
2126 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx);
2127 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_toprimitive(duk_context *ctx);
2128 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx);
2129 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx);
2130 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_tostring(duk_context *ctx);
2131 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_flags(duk_context *ctx);
2132 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_context *ctx);
2133 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx);
2134 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx);
2135 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx);
2136 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx);
2137 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx);
2138 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx);
2139 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx);
2140 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx);
2141 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx);
2142 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_clz32(duk_context *ctx);
2143 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_hypot(duk_context *ctx);
2144 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_imul(duk_context *ctx);
2145 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_max(duk_context *ctx);
2146 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_min(duk_context *ctx);
2147 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_random(duk_context *ctx);
2148 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_sign(duk_context *ctx);
2149 DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_parse(duk_context *ctx);
2150 DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx);
2151 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx);
2152 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_act(duk_context *ctx);
2153 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx);
2154 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx);
2155 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx);
2156 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx);
2157 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx);
2158 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_yield(duk_context *ctx);
2159 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_resume(duk_context *ctx);
2160 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_current(duk_context *ctx);
2161 DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx);
2162 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_apply(duk_context *ctx);
2163 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_construct(duk_context *ctx);
2164 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_delete_property(duk_context *ctx);
2165 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_get(duk_context *ctx);
2166 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_has(duk_context *ctx);
2167 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_set(duk_context *ctx);
2168 DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_key_for(duk_context *ctx);
2169 DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_tostring_shared(duk_context *ctx);
2170 DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_toprimitive(duk_context *ctx);
2171 DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx);
2172 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_context *ctx);
2173 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx);
2174 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_context *ctx);
2175 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_buffer_getter(duk_context *ctx);
2176 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx);
2177 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx);
2178 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_set(duk_context *ctx);
2179 DUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_allocplain(duk_context *ctx);
2180 DUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_plainof(duk_context *ctx);
2181 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx);
2182 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx);
2183 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx);
2184 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx);
2185 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx);
2186 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx);
2187 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx);
2188 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx);
2189 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx);
2190 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx);
2191 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_context *ctx);
2192 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encode(duk_context *ctx);
2193 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_context *ctx);
2194 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_context *ctx);
2195 DUK_INTERNAL_DECL duk_ret_t duk_bi_performance_now(duk_context *ctx);
2196 #if !defined(DUK_SINGLE_FILE)
2197 DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[183];
2198 #endif  /* !DUK_SINGLE_FILE */
2199 #define DUK_BIDX_GLOBAL                                               0
2200 #define DUK_BIDX_GLOBAL_ENV                                           1
2201 #define DUK_BIDX_OBJECT_CONSTRUCTOR                                   2
2202 #define DUK_BIDX_OBJECT_PROTOTYPE                                     3
2203 #define DUK_BIDX_FUNCTION_CONSTRUCTOR                                 4
2204 #define DUK_BIDX_FUNCTION_PROTOTYPE                                   5
2205 #define DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE                            6
2206 #define DUK_BIDX_ARRAY_CONSTRUCTOR                                    7
2207 #define DUK_BIDX_ARRAY_PROTOTYPE                                      8
2208 #define DUK_BIDX_STRING_CONSTRUCTOR                                   9
2209 #define DUK_BIDX_STRING_PROTOTYPE                                     10
2210 #define DUK_BIDX_BOOLEAN_CONSTRUCTOR                                  11
2211 #define DUK_BIDX_BOOLEAN_PROTOTYPE                                    12
2212 #define DUK_BIDX_NUMBER_CONSTRUCTOR                                   13
2213 #define DUK_BIDX_NUMBER_PROTOTYPE                                     14
2214 #define DUK_BIDX_DATE_CONSTRUCTOR                                     15
2215 #define DUK_BIDX_DATE_PROTOTYPE                                       16
2216 #define DUK_BIDX_REGEXP_CONSTRUCTOR                                   17
2217 #define DUK_BIDX_REGEXP_PROTOTYPE                                     18
2218 #define DUK_BIDX_ERROR_CONSTRUCTOR                                    19
2219 #define DUK_BIDX_ERROR_PROTOTYPE                                      20
2220 #define DUK_BIDX_EVAL_ERROR_CONSTRUCTOR                               21
2221 #define DUK_BIDX_EVAL_ERROR_PROTOTYPE                                 22
2222 #define DUK_BIDX_RANGE_ERROR_CONSTRUCTOR                              23
2223 #define DUK_BIDX_RANGE_ERROR_PROTOTYPE                                24
2224 #define DUK_BIDX_REFERENCE_ERROR_CONSTRUCTOR                          25
2225 #define DUK_BIDX_REFERENCE_ERROR_PROTOTYPE                            26
2226 #define DUK_BIDX_SYNTAX_ERROR_CONSTRUCTOR                             27
2227 #define DUK_BIDX_SYNTAX_ERROR_PROTOTYPE                               28
2228 #define DUK_BIDX_TYPE_ERROR_CONSTRUCTOR                               29
2229 #define DUK_BIDX_TYPE_ERROR_PROTOTYPE                                 30
2230 #define DUK_BIDX_URI_ERROR_CONSTRUCTOR                                31
2231 #define DUK_BIDX_URI_ERROR_PROTOTYPE                                  32
2232 #define DUK_BIDX_TYPE_ERROR_THROWER                                   33
2233 #define DUK_BIDX_DUKTAPE                                              34
2234 #define DUK_BIDX_THREAD_PROTOTYPE                                     35
2235 #define DUK_BIDX_POINTER_PROTOTYPE                                    36
2236 #define DUK_BIDX_DOUBLE_ERROR                                         37
2237 #define DUK_BIDX_SYMBOL_PROTOTYPE                                     38
2238 #define DUK_BIDX_ARRAYBUFFER_PROTOTYPE                                39
2239 #define DUK_BIDX_DATAVIEW_PROTOTYPE                                   40
2240 #define DUK_BIDX_INT8ARRAY_PROTOTYPE                                  41
2241 #define DUK_BIDX_UINT8ARRAY_PROTOTYPE                                 42
2242 #define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE                          43
2243 #define DUK_BIDX_INT16ARRAY_PROTOTYPE                                 44
2244 #define DUK_BIDX_UINT16ARRAY_PROTOTYPE                                45
2245 #define DUK_BIDX_INT32ARRAY_PROTOTYPE                                 46
2246 #define DUK_BIDX_UINT32ARRAY_PROTOTYPE                                47
2247 #define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE                               48
2248 #define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE                               49
2249 #define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE                              50
2250 #define DUK_NUM_BUILTINS                                              51
2251 #define DUK_NUM_BIDX_BUILTINS                                         51
2252 #define DUK_NUM_ALL_BUILTINS                                          79
2253 #if defined(DUK_USE_DOUBLE_LE)
2254 #if !defined(DUK_SINGLE_FILE)
2255 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4251];
2256 #endif  /* !DUK_SINGLE_FILE */
2257 #define DUK_BUILTINS_DATA_LENGTH                                      4251
2258 #elif defined(DUK_USE_DOUBLE_BE)
2259 #if !defined(DUK_SINGLE_FILE)
2260 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4251];
2261 #endif  /* !DUK_SINGLE_FILE */
2262 #define DUK_BUILTINS_DATA_LENGTH                                      4251
2263 #elif defined(DUK_USE_DOUBLE_ME)
2264 #if !defined(DUK_SINGLE_FILE)
2265 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4251];
2266 #endif  /* !DUK_SINGLE_FILE */
2267 #define DUK_BUILTINS_DATA_LENGTH                                      4251
2268 #else
2269 #error invalid endianness defines
2270 #endif
2271 #endif  /* DUK_USE_ROM_OBJECTS */
2272 #endif  /* DUK_BUILTINS_H_INCLUDED */
2273 
2274 /* #include duk_util.h */
2275 /*
2276  *  Utilities
2277  */
2278 
2279 #if !defined(DUK_UTIL_H_INCLUDED)
2280 #define DUK_UTIL_H_INCLUDED
2281 
2282 #if defined(DUK_USE_GET_RANDOM_DOUBLE)
2283 #define DUK_UTIL_GET_RANDOM_DOUBLE(thr) DUK_USE_GET_RANDOM_DOUBLE((thr)->heap_udata)
2284 #else
2285 #define DUK_UTIL_GET_RANDOM_DOUBLE(thr) duk_util_tinyrandom_get_double(thr)
2286 #endif
2287 
2288 /*
2289  *  Some useful constants
2290  */
2291 
2292 #define DUK_DOUBLE_2TO32     4294967296.0
2293 #define DUK_DOUBLE_2TO31     2147483648.0
2294 #define DUK_DOUBLE_LOG2E     1.4426950408889634
2295 #define DUK_DOUBLE_LOG10E    0.4342944819032518
2296 
2297 /*
2298  *  Endian conversion
2299  */
2300 
2301 #if defined(DUK_USE_INTEGER_LE)
2302 #define DUK_HTON32(x) DUK_BSWAP32((x))
2303 #define DUK_NTOH32(x) DUK_BSWAP32((x))
2304 #define DUK_HTON16(x) DUK_BSWAP16((x))
2305 #define DUK_NTOH16(x) DUK_BSWAP16((x))
2306 #elif defined(DUK_USE_INTEGER_BE)
2307 #define DUK_HTON32(x) (x)
2308 #define DUK_NTOH32(x) (x)
2309 #define DUK_HTON16(x) (x)
2310 #define DUK_NTOH16(x) (x)
2311 #else
2312 #error internal error, endianness defines broken
2313 #endif
2314 
2315 /*
2316  *  Bitstream decoder
2317  */
2318 
2319 struct duk_bitdecoder_ctx {
2320 	const duk_uint8_t *data;
2321 	duk_size_t offset;
2322 	duk_size_t length;
2323 	duk_uint32_t currval;
2324 	duk_small_int_t currbits;
2325 };
2326 
2327 #define DUK_BD_BITPACKED_STRING_MAXLEN 256
2328 
2329 /*
2330  *  Bitstream encoder
2331  */
2332 
2333 struct duk_bitencoder_ctx {
2334 	duk_uint8_t *data;
2335 	duk_size_t offset;
2336 	duk_size_t length;
2337 	duk_uint32_t currval;
2338 	duk_small_int_t currbits;
2339 	duk_small_int_t truncated;
2340 };
2341 
2342 /*
2343  *  Raw write/read macros for big endian, unaligned basic values.
2344  *  Caller ensures there's enough space.  The macros update the pointer
2345  *  argument automatically on resizes.  The idiom seems a bit odd, but
2346  *  leads to compact code.
2347  */
2348 
2349 #define DUK_RAW_WRITE_U8(ptr,val)  do { \
2350 		*(ptr)++ = (duk_uint8_t) (val); \
2351 	} while (0)
2352 #define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be(&(ptr), (duk_uint16_t) (val))
2353 #define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be(&(ptr), (duk_uint32_t) (val))
2354 #define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be(&(ptr), (duk_double_t) (val))
2355 #define DUK_RAW_WRITE_XUTF8(ptr,val)  do { \
2356 		/* 'ptr' is evaluated both as LHS and RHS. */ \
2357 		duk_uint8_t *duk__ptr; \
2358 		duk_small_int_t duk__len; \
2359 		duk__ptr = (duk_uint8_t *) (ptr); \
2360 		duk__len = duk_unicode_encode_xutf8((duk_ucodepoint_t) (val), duk__ptr); \
2361 		duk__ptr += duk__len; \
2362 		(ptr) = duk__ptr; \
2363 	} while (0)
2364 #define DUK_RAW_WRITE_CESU8(ptr,val)  do { \
2365 		/* 'ptr' is evaluated both as LHS and RHS. */ \
2366 		duk_uint8_t *duk__ptr; \
2367 		duk_small_int_t duk__len; \
2368 		duk__ptr = (duk_uint8_t *) (ptr); \
2369 		duk__len = duk_unicode_encode_cesu8((duk_ucodepoint_t) (val), duk__ptr); \
2370 		duk__ptr += duk__len; \
2371 		(ptr) = duk__ptr; \
2372 	} while (0)
2373 
2374 #define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)++))
2375 #define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be(&(ptr));
2376 #define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be(&(ptr));
2377 #define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be(&(ptr));
2378 
2379 /*
2380  *  Buffer writer (dynamic buffer only)
2381  *
2382  *  Helper for writing to a dynamic buffer with a concept of a "slack" area
2383  *  to reduce resizes.  You can ensure there is enough space beforehand and
2384  *  then write for a while without further checks, relying on a stable data
2385  *  pointer.  Slack handling is automatic so call sites only indicate how
2386  *  much data they need right now.
2387  *
2388  *  There are several ways to write using bufwriter.  The best approach
2389  *  depends mainly on how much performance matters over code footprint.
2390  *  The key issues are (1) ensuring there is space and (2) keeping the
2391  *  pointers consistent.  Fast code should ensure space for multiple writes
2392  *  with one ensure call.  Fastest inner loop code can temporarily borrow
2393  *  the 'p' pointer but must write it back eventually.
2394  *
2395  *  Be careful to ensure all macro arguments (other than static pointers like
2396  *  'thr' and 'bw_ctx') are evaluated exactly once, using temporaries if
2397  *  necessary (if that's not possible, there should be a note near the macro).
2398  *  Buffer write arguments often contain arithmetic etc so this is
2399  *  particularly important here.
2400  */
2401 
2402 /* XXX: Migrate bufwriter and other read/write helpers to its own header? */
2403 
2404 struct duk_bufwriter_ctx {
2405 	duk_uint8_t *p;
2406 	duk_uint8_t *p_base;
2407 	duk_uint8_t *p_limit;
2408 	duk_hbuffer_dynamic *buf;
2409 };
2410 
2411 #if defined(DUK_USE_PREFER_SIZE)
2412 #define DUK_BW_SLACK_ADD           64
2413 #define DUK_BW_SLACK_SHIFT         4    /* 2^4 -> 1/16 = 6.25% slack */
2414 #else
2415 #define DUK_BW_SLACK_ADD           64
2416 #define DUK_BW_SLACK_SHIFT         2    /* 2^2 -> 1/4 = 25% slack */
2417 #endif
2418 
2419 /* Initialization and finalization (compaction), converting to other types. */
2420 
2421 #define DUK_BW_INIT_PUSHBUF(thr,bw_ctx,sz) do { \
2422 		duk_bw_init_pushbuf((thr), (bw_ctx), (sz)); \
2423 	} while (0)
2424 #define DUK_BW_INIT_WITHBUF(thr,bw_ctx,buf) do { \
2425 		duk_bw_init((thr), (bw_ctx), (buf)); \
2426 	} while (0)
2427 #define DUK_BW_COMPACT(thr,bw_ctx) do { \
2428 		/* Make underlying buffer compact to match DUK_BW_GET_SIZE(). */ \
2429 		duk_bw_compact((thr), (bw_ctx)); \
2430 	} while (0)
2431 #define DUK_BW_PUSH_AS_STRING(thr,bw_ctx) do { \
2432 		duk_push_lstring((thr), \
2433 		                 (const char *) (bw_ctx)->p_base, \
2434 		                 (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
2435 	} while (0)
2436 
2437 /* Pointers may be NULL for a while when 'buf' size is zero and before any
2438  * ENSURE calls have been made.  Once an ENSURE has been made, the pointers
2439  * are required to be non-NULL so that it's always valid to use memcpy() and
2440  * memmove(), even for zero size.
2441  */
2442 #if defined(DUK_USE_ASSERTIONS)
2443 DUK_INTERNAL_DECL void duk_bw_assert_valid(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
2444 #define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx)  (duk_bw_assert_valid((thr), (bw_ctx)))
2445 #define DUK_BW_ASSERT_VALID(thr,bw_ctx)  do { duk_bw_assert_valid((thr), (bw_ctx)); } while (0)
2446 #else
2447 #define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx)  DUK_ASSERT_EXPR(1)
2448 #define DUK_BW_ASSERT_VALID(thr,bw_ctx)  do {} while (0)
2449 #endif
2450 
2451 /* Working with the pointer and current size. */
2452 
2453 #define DUK_BW_GET_PTR(thr,bw_ctx) \
2454 	((bw_ctx)->p)
2455 #define DUK_BW_SET_PTR(thr,bw_ctx,ptr) do { \
2456 		(bw_ctx)->p = (ptr); \
2457 	} while (0)
2458 #define DUK_BW_ADD_PTR(thr,bw_ctx,delta) do { \
2459 		(bw_ctx)->p += (delta); \
2460 	} while (0)
2461 #define DUK_BW_GET_BASEPTR(thr,bw_ctx) \
2462 	((bw_ctx)->p_base)
2463 #define DUK_BW_GET_LIMITPTR(thr,bw_ctx) \
2464 	((bw_ctx)->p_limit)
2465 #define DUK_BW_GET_SIZE(thr,bw_ctx) \
2466 	((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base))
2467 #define DUK_BW_SET_SIZE(thr,bw_ctx,sz) do { \
2468 		DUK_ASSERT((duk_size_t) (sz) <= (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
2469 		(bw_ctx)->p = (bw_ctx)->p_base + (sz); \
2470 	} while (0)
2471 #define DUK_BW_RESET_SIZE(thr,bw_ctx) do { \
2472 		/* Reset to zero size, keep current limit. */ \
2473 		(bw_ctx)->p = (bw_ctx)->p_base; \
2474 	} while (0)
2475 #define DUK_BW_GET_BUFFER(thr,bw_ctx) \
2476 	((bw_ctx)->buf)
2477 
2478 /* Ensuring (reserving) space. */
2479 
2480 #define DUK_BW_ENSURE(thr,bw_ctx,sz) do { \
2481 		duk_size_t duk__sz, duk__space; \
2482 		DUK_BW_ASSERT_VALID((thr), (bw_ctx)); \
2483 		duk__sz = (sz); \
2484 		duk__space = (duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p); \
2485 		if (duk__space < duk__sz) { \
2486 			(void) duk_bw_resize((thr), (bw_ctx), duk__sz); \
2487 		} \
2488 	} while (0)
2489 /* NOTE: Multiple evaluation of 'ptr' in this macro. */
2490 /* XXX: Rework to use an always-inline function? */
2491 #define DUK_BW_ENSURE_RAW(thr,bw_ctx,sz,ptr) \
2492 	(((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? \
2493 	 (ptr) : \
2494 	 ((bw_ctx)->p = (ptr), duk_bw_resize((thr),(bw_ctx),(sz))))
2495 #define DUK_BW_ENSURE_GETPTR(thr,bw_ctx,sz) \
2496 	DUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p)
2497 #define DUK_BW_ASSERT_SPACE_EXPR(thr,bw_ctx,sz) \
2498 	(DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)), \
2499 	 DUK_ASSERT_EXPR((duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p) >= (duk_size_t) (sz)))
2500 #define DUK_BW_ASSERT_SPACE(thr,bw_ctx,sz) do { \
2501 		DUK_BW_ASSERT_SPACE_EXPR((thr), (bw_ctx), (sz)); \
2502 	} while (0)
2503 
2504 /* Miscellaneous. */
2505 
2506 #define DUK_BW_SETPTR_AND_COMPACT(thr,bw_ctx,ptr) do { \
2507 		(bw_ctx)->p = (ptr); \
2508 		duk_bw_compact((thr), (bw_ctx)); \
2509 	} while (0)
2510 
2511 /* Fast write calls which assume you control the slack beforehand.
2512  * Multibyte write variants exist and use a temporary write pointer
2513  * because byte writes alias with anything: with a stored pointer
2514  * explicit pointer load/stores get generated (e.g. gcc -Os).
2515  */
2516 
2517 #define DUK_BW_WRITE_RAW_U8(thr,bw_ctx,val) do { \
2518 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 1); \
2519 		*(bw_ctx)->p++ = (duk_uint8_t) (val); \
2520 	} while (0)
2521 #define DUK_BW_WRITE_RAW_U8_2(thr,bw_ctx,val1,val2) do { \
2522 		duk_uint8_t *duk__p; \
2523 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 2); \
2524 		duk__p = (bw_ctx)->p; \
2525 		*duk__p++ = (duk_uint8_t) (val1); \
2526 		*duk__p++ = (duk_uint8_t) (val2); \
2527 		(bw_ctx)->p = duk__p; \
2528 	} while (0)
2529 #define DUK_BW_WRITE_RAW_U8_3(thr,bw_ctx,val1,val2,val3) do { \
2530 		duk_uint8_t *duk__p; \
2531 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 3); \
2532 		duk__p = (bw_ctx)->p; \
2533 		*duk__p++ = (duk_uint8_t) (val1); \
2534 		*duk__p++ = (duk_uint8_t) (val2); \
2535 		*duk__p++ = (duk_uint8_t) (val3); \
2536 		(bw_ctx)->p = duk__p; \
2537 	} while (0)
2538 #define DUK_BW_WRITE_RAW_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
2539 		duk_uint8_t *duk__p; \
2540 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 4); \
2541 		duk__p = (bw_ctx)->p; \
2542 		*duk__p++ = (duk_uint8_t) (val1); \
2543 		*duk__p++ = (duk_uint8_t) (val2); \
2544 		*duk__p++ = (duk_uint8_t) (val3); \
2545 		*duk__p++ = (duk_uint8_t) (val4); \
2546 		(bw_ctx)->p = duk__p; \
2547 	} while (0)
2548 #define DUK_BW_WRITE_RAW_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
2549 		duk_uint8_t *duk__p; \
2550 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 5); \
2551 		duk__p = (bw_ctx)->p; \
2552 		*duk__p++ = (duk_uint8_t) (val1); \
2553 		*duk__p++ = (duk_uint8_t) (val2); \
2554 		*duk__p++ = (duk_uint8_t) (val3); \
2555 		*duk__p++ = (duk_uint8_t) (val4); \
2556 		*duk__p++ = (duk_uint8_t) (val5); \
2557 		(bw_ctx)->p = duk__p; \
2558 	} while (0)
2559 #define DUK_BW_WRITE_RAW_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
2560 		duk_uint8_t *duk__p; \
2561 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 6); \
2562 		duk__p = (bw_ctx)->p; \
2563 		*duk__p++ = (duk_uint8_t) (val1); \
2564 		*duk__p++ = (duk_uint8_t) (val2); \
2565 		*duk__p++ = (duk_uint8_t) (val3); \
2566 		*duk__p++ = (duk_uint8_t) (val4); \
2567 		*duk__p++ = (duk_uint8_t) (val5); \
2568 		*duk__p++ = (duk_uint8_t) (val6); \
2569 		(bw_ctx)->p = duk__p; \
2570 	} while (0)
2571 #define DUK_BW_WRITE_RAW_XUTF8(thr,bw_ctx,cp) do { \
2572 		duk_ucodepoint_t duk__cp; \
2573 		duk_small_int_t duk__enc_len; \
2574 		duk__cp = (duk_ucodepoint_t) (cp); \
2575 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_xutf8_length(duk__cp)); \
2576 		duk__enc_len = duk_unicode_encode_xutf8(duk__cp, (bw_ctx)->p); \
2577 		(bw_ctx)->p += duk__enc_len; \
2578 	} while (0)
2579 #define DUK_BW_WRITE_RAW_CESU8(thr,bw_ctx,cp) do { \
2580 		duk_ucodepoint_t duk__cp; \
2581 		duk_small_int_t duk__enc_len; \
2582 		duk__cp = (duk_ucodepoint_t) (cp); \
2583 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_cesu8_length(duk__cp)); \
2584 		duk__enc_len = duk_unicode_encode_cesu8(duk__cp, (bw_ctx)->p); \
2585 		(bw_ctx)->p += duk__enc_len; \
2586 	} while (0)
2587 /* XXX: add temporary duk__p pointer here too; sharing */
2588 /* XXX: avoid unsafe variants */
2589 #define DUK_BW_WRITE_RAW_BYTES(thr,bw_ctx,valptr,valsz) do { \
2590 		const void *duk__valptr; \
2591 		duk_size_t duk__valsz; \
2592 		duk__valptr = (const void *) (valptr); \
2593 		duk__valsz = (duk_size_t) (valsz); \
2594 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2595 		(bw_ctx)->p += duk__valsz; \
2596 	} while (0)
2597 #define DUK_BW_WRITE_RAW_CSTRING(thr,bw_ctx,val) do { \
2598 		const duk_uint8_t *duk__val; \
2599 		duk_size_t duk__val_len; \
2600 		duk__val = (const duk_uint8_t *) (val); \
2601 		duk__val_len = DUK_STRLEN((const char *) duk__val); \
2602 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2603 		(bw_ctx)->p += duk__val_len; \
2604 	} while (0)
2605 #define DUK_BW_WRITE_RAW_HSTRING(thr,bw_ctx,val) do { \
2606 		duk_size_t duk__val_len; \
2607 		duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2608 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2609 		(bw_ctx)->p += duk__val_len; \
2610 	} while (0)
2611 #define DUK_BW_WRITE_RAW_HBUFFER(thr,bw_ctx,val) do { \
2612 		duk_size_t duk__val_len; \
2613 		duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2614 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2615 		(bw_ctx)->p += duk__val_len; \
2616 	} while (0)
2617 #define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr,bw_ctx,val) do { \
2618 		duk_size_t duk__val_len; \
2619 		duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2620 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2621 		(bw_ctx)->p += duk__val_len; \
2622 	} while (0)
2623 #define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
2624 		duk_size_t duk__val_len; \
2625 		duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2626 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2627 		(bw_ctx)->p += duk__val_len; \
2628 	} while (0)
2629 
2630 /* Append bytes from a slice already in the buffer. */
2631 #define DUK_BW_WRITE_RAW_SLICE(thr,bw,dst_off,dst_len) \
2632 	duk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len))
2633 
2634 /* Insert bytes in the middle of the buffer from an external buffer. */
2635 #define DUK_BW_INSERT_RAW_BYTES(thr,bw,dst_off,buf,len) \
2636 	duk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len))
2637 
2638 /* Insert bytes in the middle of the buffer from a slice already
2639  * in the buffer.  Source offset is interpreted "before" the operation.
2640  */
2641 #define DUK_BW_INSERT_RAW_SLICE(thr,bw,dst_off,src_off,len) \
2642 	duk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len))
2643 
2644 /* Insert a reserved area somewhere in the buffer; caller fills it.
2645  * Evaluates to a (duk_uint_t *) pointing to the start of the reserved
2646  * area for convenience.
2647  */
2648 #define DUK_BW_INSERT_RAW_AREA(thr,bw,off,len) \
2649 	duk_bw_insert_raw_area((thr), (bw), (off), (len))
2650 
2651 /* Remove a slice from inside buffer. */
2652 #define DUK_BW_REMOVE_RAW_SLICE(thr,bw,off,len) \
2653 	duk_bw_remove_raw_slice((thr), (bw), (off), (len))
2654 
2655 /* Safe write calls which will ensure space first. */
2656 
2657 #define DUK_BW_WRITE_ENSURE_U8(thr,bw_ctx,val) do { \
2658 		DUK_BW_ENSURE((thr), (bw_ctx), 1); \
2659 		DUK_BW_WRITE_RAW_U8((thr), (bw_ctx), (val)); \
2660 	} while (0)
2661 #define DUK_BW_WRITE_ENSURE_U8_2(thr,bw_ctx,val1,val2) do { \
2662 		DUK_BW_ENSURE((thr), (bw_ctx), 2); \
2663 		DUK_BW_WRITE_RAW_U8_2((thr), (bw_ctx), (val1), (val2)); \
2664 	} while (0)
2665 #define DUK_BW_WRITE_ENSURE_U8_3(thr,bw_ctx,val1,val2,val3) do { \
2666 		DUK_BW_ENSURE((thr), (bw_ctx), 3); \
2667 		DUK_BW_WRITE_RAW_U8_3((thr), (bw_ctx), (val1), (val2), (val3)); \
2668 	} while (0)
2669 #define DUK_BW_WRITE_ENSURE_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
2670 		DUK_BW_ENSURE((thr), (bw_ctx), 4); \
2671 		DUK_BW_WRITE_RAW_U8_4((thr), (bw_ctx), (val1), (val2), (val3), (val4)); \
2672 	} while (0)
2673 #define DUK_BW_WRITE_ENSURE_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
2674 		DUK_BW_ENSURE((thr), (bw_ctx), 5); \
2675 		DUK_BW_WRITE_RAW_U8_5((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5)); \
2676 	} while (0)
2677 #define DUK_BW_WRITE_ENSURE_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
2678 		DUK_BW_ENSURE((thr), (bw_ctx), 6); \
2679 		DUK_BW_WRITE_RAW_U8_6((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5), (val6)); \
2680 	} while (0)
2681 #define DUK_BW_WRITE_ENSURE_XUTF8(thr,bw_ctx,cp) do { \
2682 		DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_XUTF8_LENGTH); \
2683 		DUK_BW_WRITE_RAW_XUTF8((thr), (bw_ctx), (cp)); \
2684 	} while (0)
2685 #define DUK_BW_WRITE_ENSURE_CESU8(thr,bw_ctx,cp) do { \
2686 		DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_CESU8_LENGTH); \
2687 		DUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \
2688 	} while (0)
2689 /* XXX: add temporary duk__p pointer here too; sharing */
2690 /* XXX: avoid unsafe */
2691 #define DUK_BW_WRITE_ENSURE_BYTES(thr,bw_ctx,valptr,valsz) do { \
2692 		const void *duk__valptr; \
2693 		duk_size_t duk__valsz; \
2694 		duk__valptr = (const void *) (valptr); \
2695 		duk__valsz = (duk_size_t) (valsz); \
2696 		DUK_BW_ENSURE((thr), (bw_ctx), duk__valsz); \
2697 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2698 		(bw_ctx)->p += duk__valsz; \
2699 	} while (0)
2700 #define DUK_BW_WRITE_ENSURE_CSTRING(thr,bw_ctx,val) do { \
2701 		const duk_uint8_t *duk__val; \
2702 		duk_size_t duk__val_len; \
2703 		duk__val = (const duk_uint8_t *) (val); \
2704 		duk__val_len = DUK_STRLEN((const char *) duk__val); \
2705 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2706 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2707 		(bw_ctx)->p += duk__val_len; \
2708 	} while (0)
2709 #define DUK_BW_WRITE_ENSURE_HSTRING(thr,bw_ctx,val) do { \
2710 		duk_size_t duk__val_len; \
2711 		duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2712 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2713 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2714 		(bw_ctx)->p += duk__val_len; \
2715 	} while (0)
2716 #define DUK_BW_WRITE_ENSURE_HBUFFER(thr,bw_ctx,val) do { \
2717 		duk_size_t duk__val_len; \
2718 		duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2719 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2720 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2721 		(bw_ctx)->p += duk__val_len; \
2722 	} while (0)
2723 #define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr,bw_ctx,val) do { \
2724 		duk_size_t duk__val_len; \
2725 		duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2726 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2727 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2728 		(bw_ctx)->p += duk__val_len; \
2729 	} while (0)
2730 #define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
2731 		duk_size_t duk__val_len; \
2732 		duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2733 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2734 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2735 		(bw_ctx)->p += duk__val_len; \
2736 	} while (0)
2737 
2738 #define DUK_BW_WRITE_ENSURE_SLICE(thr,bw,dst_off,dst_len) \
2739 	duk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len))
2740 #define DUK_BW_INSERT_ENSURE_BYTES(thr,bw,dst_off,buf,len) \
2741 	duk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len))
2742 #define DUK_BW_INSERT_ENSURE_SLICE(thr,bw,dst_off,src_off,len) \
2743 	duk_bw_insert_ensure_slice((thr), (bw), (dst_off), (src_off), (len))
2744 #define DUK_BW_INSERT_ENSURE_AREA(thr,bw,off,len) \
2745 	/* Evaluates to (duk_uint8_t *) pointing to start of area. */ \
2746 	duk_bw_insert_ensure_area((thr), (bw), (off), (len))
2747 #define DUK_BW_REMOVE_ENSURE_SLICE(thr,bw,off,len) \
2748 	/* No difference between raw/ensure because the buffer shrinks. */ \
2749 	DUK_BW_REMOVE_RAW_SLICE((thr), (bw), (off), (len))
2750 
2751 /*
2752  *  Externs and prototypes
2753  */
2754 
2755 #if !defined(DUK_SINGLE_FILE)
2756 DUK_INTERNAL_DECL const duk_uint8_t duk_lc_digits[36];
2757 DUK_INTERNAL_DECL const duk_uint8_t duk_uc_nybbles[16];
2758 DUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256];
2759 #if defined(DUK_USE_HEX_FASTPATH)
2760 DUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256];
2761 DUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256];
2762 #endif
2763 #endif  /* !DUK_SINGLE_FILE */
2764 
2765 /* Note: assumes that duk_util_probe_steps size is 32 */
2766 #if defined(DUK_USE_HOBJECT_HASH_PART)
2767 #if !defined(DUK_SINGLE_FILE)
2768 DUK_INTERNAL_DECL duk_uint8_t duk_util_probe_steps[32];
2769 #endif  /* !DUK_SINGLE_FILE */
2770 #endif
2771 
2772 #if defined(DUK_USE_STRHASH_DENSE)
2773 DUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed);
2774 #endif
2775 
2776 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits);
2777 DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx);
2778 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value);
2779 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);
2780 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx);
2781 DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out);
2782 
2783 DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits);
2784 DUK_INTERNAL_DECL void duk_be_finish(duk_bitencoder_ctx *ctx);
2785 
2786 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
2787 DUK_INTERNAL_DECL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr);
2788 DUK_INTERNAL_DECL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr);
2789 #endif
2790 
2791 DUK_INTERNAL_DECL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf);
2792 DUK_INTERNAL_DECL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size);
2793 DUK_INTERNAL_DECL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz);
2794 DUK_INTERNAL_DECL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
2795 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);
2796 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);
2797 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);
2798 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);
2799 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);
2800 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);
2801 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);
2802 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);
2803 DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);
2804 /* No duk_bw_remove_ensure_slice(), functionality would be identical. */
2805 
2806 DUK_INTERNAL_DECL DUK_INLINE duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p);
2807 DUK_INTERNAL_DECL DUK_INLINE duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p);
2808 DUK_INTERNAL_DECL DUK_INLINE duk_double_t duk_raw_read_double_be(duk_uint8_t **p);
2809 DUK_INTERNAL_DECL DUK_INLINE void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val);
2810 DUK_INTERNAL_DECL DUK_INLINE void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val);
2811 DUK_INTERNAL_DECL DUK_INLINE void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val);
2812 
2813 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* For now only needed by the debugger. */
2814 DUK_INTERNAL_DECL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len);
2815 #endif
2816 
2817 /* memcpy(), memmove() etc wrappers.  The plain variants like duk_memcpy()
2818  * assume C99+ and 'src' and 'dst' pointers must be non-NULL even when the
2819  * operation size is zero.  The unsafe variants like duk_memcpy_safe() deal
2820  * with the zero size case explicitly, and allow NULL pointers in that case
2821  * (which is undefined behavior in C99+).  For the majority of actual targets
2822  * a NULL pointer with a zero length is fine in practice.  These wrappers are
2823  * macros to force inlining; because there are hundreds of call sites, even a
2824  * few extra bytes per call site adds up to ~1kB footprint.
2825  */
2826 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
2827 #define duk_memcpy(dst,src,len)  do { \
2828 		void *duk__dst = (dst); \
2829 		const void *duk__src = (src); \
2830 		duk_size_t duk__len = (len); \
2831 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2832 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2833 		(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
2834 	} while (0)
2835 #define duk_memcpy_unsafe(dst,src,len)  duk_memcpy((dst), (src), (len))
2836 #define duk_memmove(dst,src,len)  do { \
2837 		void *duk__dst = (dst); \
2838 		const void *duk__src = (src); \
2839 		duk_size_t duk__len = (len); \
2840 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2841 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2842 		(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
2843 	} while (0)
2844 #define duk_memmove_unsafe(dst,src,len)  duk_memmove((dst), (src), (len))
2845 #define duk_memset(dst,val,len)  do { \
2846 		void *duk__dst = (dst); \
2847 		duk_small_int_t duk__val = (val); \
2848 		duk_size_t duk__len = (len); \
2849 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2850 		(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
2851 	} while (0)
2852 #define duk_memset_unsafe(dst,val,len)  duk_memset((dst), (val), (len))
2853 #define duk_memzero(dst,len)  do { \
2854 		void *duk__dst = (dst); \
2855 		duk_size_t duk__len = (len); \
2856 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2857 		(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
2858 	} while (0)
2859 #define duk_memzero_unsafe(dst,len)  duk_memzero((dst), (len))
2860 #else  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
2861 #define duk_memcpy(dst,src,len)  do { \
2862 		void *duk__dst = (dst); \
2863 		const void *duk__src = (src); \
2864 		duk_size_t duk__len = (len); \
2865 		DUK_ASSERT(duk__dst != NULL); \
2866 		DUK_ASSERT(duk__src != NULL); \
2867 		(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
2868 	} while (0)
2869 #define duk_memcpy_unsafe(dst,src,len)  do { \
2870 		void *duk__dst = (dst); \
2871 		const void *duk__src = (src); \
2872 		duk_size_t duk__len = (len); \
2873 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2874 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2875 		if (DUK_LIKELY(duk__len > 0U)) { \
2876 			DUK_ASSERT(duk__dst != NULL); \
2877 			DUK_ASSERT(duk__src != NULL); \
2878 			(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
2879 		} \
2880 	} while (0)
2881 #define duk_memmove(dst,src,len)  do { \
2882 		void *duk__dst = (dst); \
2883 		const void *duk__src = (src); \
2884 		duk_size_t duk__len = (len); \
2885 		DUK_ASSERT(duk__dst != NULL); \
2886 		DUK_ASSERT(duk__src != NULL); \
2887 		(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
2888 	} while (0)
2889 #define duk_memmove_unsafe(dst,src,len)  do { \
2890 		void *duk__dst = (dst); \
2891 		const void *duk__src = (src); \
2892 		duk_size_t duk__len = (len); \
2893 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2894 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2895 		if (DUK_LIKELY(duk__len > 0U)) { \
2896 			DUK_ASSERT(duk__dst != NULL); \
2897 			DUK_ASSERT(duk__src != NULL); \
2898 			(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
2899 		} \
2900 	} while (0)
2901 #define duk_memset(dst,val,len)  do { \
2902 		void *duk__dst = (dst); \
2903 		duk_small_int_t duk__val = (val); \
2904 		duk_size_t duk__len = (len); \
2905 		DUK_ASSERT(duk__dst != NULL); \
2906 		(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
2907 	} while (0)
2908 #define duk_memset_unsafe(dst,val,len)  do { \
2909 		void *duk__dst = (dst); \
2910 		duk_small_int_t duk__val = (val); \
2911 		duk_size_t duk__len = (len); \
2912 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2913 		if (DUK_LIKELY(duk__len > 0U)) { \
2914 			DUK_ASSERT(duk__dst != NULL); \
2915 			(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
2916 		} \
2917 	} while (0)
2918 #define duk_memzero(dst,len)  do { \
2919 		void *duk__dst = (dst); \
2920 		duk_size_t duk__len = (len); \
2921 		DUK_ASSERT(duk__dst != NULL); \
2922 		(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
2923 	} while (0)
2924 #define duk_memzero_unsafe(dst,len)  do { \
2925 		void *duk__dst = (dst); \
2926 		duk_size_t duk__len = (len); \
2927 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2928 		if (DUK_LIKELY(duk__len > 0U)) { \
2929 			DUK_ASSERT(duk__dst != NULL); \
2930 			(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
2931 		} \
2932 	} while (0)
2933 #endif  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
2934 
2935 DUK_INTERNAL_DECL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len);
2936 DUK_INTERNAL_DECL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len);
2937 
2938 DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival);
2939 DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival);
2940 DUK_INTERNAL_DECL duk_bool_t duk_double_is_anyinf(duk_double_t x);
2941 DUK_INTERNAL_DECL duk_bool_t duk_double_is_posinf(duk_double_t x);
2942 DUK_INTERNAL_DECL duk_bool_t duk_double_is_neginf(duk_double_t x);
2943 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan(duk_double_t x);
2944 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x);
2945 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x);
2946 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x);
2947 DUK_INTERNAL_DECL duk_small_uint_t duk_double_signbit(duk_double_t x);
2948 DUK_INTERNAL_DECL duk_double_t duk_double_trunc_towards_zero(duk_double_t x);
2949 DUK_INTERNAL_DECL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y);
2950 DUK_INTERNAL_DECL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y);
2951 DUK_INTERNAL_DECL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y);
2952 DUK_INTERNAL_DECL duk_bool_t duk_double_is_finite(duk_double_t x);
2953 DUK_INTERNAL_DECL duk_bool_t duk_double_is_integer(duk_double_t x);
2954 DUK_INTERNAL_DECL duk_bool_t duk_double_is_safe_integer(duk_double_t x);
2955 
2956 DUK_INTERNAL_DECL DUK_INLINE duk_double_t duk_double_div(duk_double_t x, duk_double_t y);
2957 DUK_INTERNAL_DECL duk_int_t duk_double_to_int_t(duk_double_t x);
2958 DUK_INTERNAL_DECL duk_uint_t duk_double_to_uint_t(duk_double_t x);
2959 DUK_INTERNAL_DECL duk_int32_t duk_double_to_int32_t(duk_double_t x);
2960 DUK_INTERNAL_DECL duk_uint32_t duk_double_to_uint32_t(duk_double_t x);
2961 DUK_INTERNAL_DECL duk_float_t duk_double_to_float_t(duk_double_t x);
2962 
2963 /*
2964  *  Miscellaneous
2965  */
2966 
2967 /* Example: x     = 0x10 = 0b00010000
2968  *          x - 1 = 0x0f = 0b00001111
2969  *          x & (x - 1) == 0
2970  *
2971  *          x     = 0x07 = 0b00000111
2972  *          x - 1 = 0x06 = 0b00000110
2973  *          x & (x - 1) != 0
2974  *
2975  * However, incorrectly true for x == 0 so check for that explicitly.
2976  */
2977 #define DUK_IS_POWER_OF_TWO(x) \
2978 	((x) != 0U && ((x) & ((x) - 1U)) == 0U)
2979 
2980 #endif  /* DUK_UTIL_H_INCLUDED */
2981 /* #include duk_strings.h */
2982 /*
2983  *  Shared string macros.
2984  *
2985  *  Using shared macros helps minimize strings data size because it's easy
2986  *  to check if an existing string could be used.  String constants don't
2987  *  need to be all defined here; defining a string here makes sense if there's
2988  *  a high chance the string could be reused.  Also, using macros allows
2989  *  a call site express the exact string needed, but the macro may map to an
2990  *  approximate string to reduce unique string count.  Macros can also be
2991  *  more easily tuned for low memory targets than #if defined()s throughout
2992  *  the code base.
2993  *
2994  *  Because format strings behave differently in the call site (they need to
2995  *  be followed by format arguments), they use a special prefix DUK_STR_FMT_.
2996  *
2997  *  On some compilers using explicit shared strings is preferable; on others
2998  *  it may be better to use straight literals because the compiler will combine
2999  *  them anyway, and such strings won't end up unnecessarily in a symbol table.
3000  */
3001 
3002 #if !defined(DUK_ERRMSG_H_INCLUDED)
3003 #define DUK_ERRMSG_H_INCLUDED
3004 
3005 /* Mostly API and built-in method related */
3006 #define DUK_STR_INTERNAL_ERROR                   "internal error"
3007 #define DUK_STR_UNSUPPORTED                      "unsupported"
3008 #define DUK_STR_INVALID_COUNT                    "invalid count"
3009 #define DUK_STR_INVALID_ARGS                     "invalid args"
3010 #define DUK_STR_INVALID_STATE                    "invalid state"
3011 #define DUK_STR_INVALID_INPUT                    "invalid input"
3012 #define DUK_STR_INVALID_LENGTH                   "invalid length"
3013 #define DUK_STR_NOT_CONSTRUCTABLE                "not constructable"
3014 #define DUK_STR_CONSTRUCT_ONLY                   "constructor requires 'new'"
3015 #define DUK_STR_NOT_CALLABLE                     "not callable"
3016 #define DUK_STR_NOT_EXTENSIBLE                   "not extensible"
3017 #define DUK_STR_NOT_WRITABLE                     "not writable"
3018 #define DUK_STR_NOT_CONFIGURABLE                 "not configurable"
3019 #define DUK_STR_INVALID_CONTEXT                  "invalid context"
3020 #define DUK_STR_INVALID_INDEX                    "invalid args"
3021 #define DUK_STR_PUSH_BEYOND_ALLOC_STACK          "cannot push beyond allocated stack"
3022 #define DUK_STR_NOT_UNDEFINED                    "unexpected type"
3023 #define DUK_STR_NOT_NULL                         "unexpected type"
3024 #define DUK_STR_NOT_BOOLEAN                      "unexpected type"
3025 #define DUK_STR_NOT_NUMBER                       "unexpected type"
3026 #define DUK_STR_NOT_STRING                       "unexpected type"
3027 #define DUK_STR_NOT_OBJECT                       "unexpected type"
3028 #define DUK_STR_NOT_POINTER                      "unexpected type"
3029 #define DUK_STR_NOT_BUFFER                       "not buffer"  /* still in use with verbose messages */
3030 #define DUK_STR_UNEXPECTED_TYPE                  "unexpected type"
3031 #define DUK_STR_NOT_THREAD                       "unexpected type"
3032 #define DUK_STR_NOT_COMPFUNC                     "unexpected type"
3033 #define DUK_STR_NOT_NATFUNC                      "unexpected type"
3034 #define DUK_STR_NOT_C_FUNCTION                   "unexpected type"
3035 #define DUK_STR_NOT_FUNCTION                     "unexpected type"
3036 #define DUK_STR_NOT_REGEXP                       "unexpected type"
3037 #define DUK_STR_TOPRIMITIVE_FAILED               "coercion to primitive failed"
3038 #define DUK_STR_NUMBER_OUTSIDE_RANGE             "number outside range"
3039 #define DUK_STR_NOT_OBJECT_COERCIBLE             "not object coercible"
3040 #define DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL      "cannot number coerce Symbol"
3041 #define DUK_STR_CANNOT_STRING_COERCE_SYMBOL      "cannot string coerce Symbol"
3042 #define DUK_STR_STRING_TOO_LONG                  "string too long"
3043 #define DUK_STR_BUFFER_TOO_LONG                  "buffer too long"
3044 #define DUK_STR_ALLOC_FAILED                     "alloc failed"
3045 #define DUK_STR_WRONG_BUFFER_TYPE                "wrong buffer type"
3046 #define DUK_STR_BASE64_ENCODE_FAILED             "base64 encode failed"
3047 #define DUK_STR_SOURCE_DECODE_FAILED             "source decode failed"
3048 #define DUK_STR_UTF8_DECODE_FAILED               "utf-8 decode failed"
3049 #define DUK_STR_BASE64_DECODE_FAILED             "base64 decode failed"
3050 #define DUK_STR_HEX_DECODE_FAILED                "hex decode failed"
3051 #define DUK_STR_INVALID_BYTECODE                 "invalid bytecode"
3052 #define DUK_STR_NO_SOURCECODE                    "no sourcecode"
3053 #define DUK_STR_RESULT_TOO_LONG                  "result too long"
3054 #define DUK_STR_INVALID_CFUNC_RC                 "invalid C function rc"
3055 #define DUK_STR_INVALID_INSTANCEOF_RVAL          "invalid instanceof rval"
3056 #define DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO  "instanceof rval has no .prototype"
3057 
3058 /* JSON */
3059 #define DUK_STR_FMT_PTR                          "%p"
3060 #define DUK_STR_FMT_INVALID_JSON                 "invalid json (at offset %ld)"
3061 #define DUK_STR_JSONDEC_RECLIMIT                 "json decode recursion limit"
3062 #define DUK_STR_JSONENC_RECLIMIT                 "json encode recursion limit"
3063 #define DUK_STR_CYCLIC_INPUT                     "cyclic input"
3064 
3065 /* Object property access */
3066 #define DUK_STR_INVALID_BASE                     "invalid base value"
3067 #define DUK_STR_STRICT_CALLER_READ               "cannot read strict 'caller'"
3068 #define DUK_STR_PROXY_REJECTED                   "proxy rejected"
3069 #define DUK_STR_INVALID_ARRAY_LENGTH             "invalid array length"
3070 #define DUK_STR_SETTER_UNDEFINED                 "setter undefined"
3071 #define DUK_STR_INVALID_DESCRIPTOR               "invalid descriptor"
3072 
3073 /* Proxy */
3074 #define DUK_STR_PROXY_REVOKED                    "proxy revoked"
3075 #define DUK_STR_INVALID_TRAP_RESULT              "invalid trap result"
3076 
3077 /* Variables */
3078 
3079 /* Lexer */
3080 #define DUK_STR_INVALID_ESCAPE                   "invalid escape"
3081 #define DUK_STR_UNTERMINATED_STRING              "unterminated string"
3082 #define DUK_STR_UNTERMINATED_COMMENT             "unterminated comment"
3083 #define DUK_STR_UNTERMINATED_REGEXP              "unterminated regexp"
3084 #define DUK_STR_TOKEN_LIMIT                      "token limit"
3085 #define DUK_STR_REGEXP_SUPPORT_DISABLED          "regexp support disabled"
3086 #define DUK_STR_INVALID_NUMBER_LITERAL           "invalid number literal"
3087 #define DUK_STR_INVALID_TOKEN                    "invalid token"
3088 
3089 /* Compiler */
3090 #define DUK_STR_PARSE_ERROR                      "parse error"
3091 #define DUK_STR_DUPLICATE_LABEL                  "duplicate label"
3092 #define DUK_STR_INVALID_LABEL                    "invalid label"
3093 #define DUK_STR_INVALID_ARRAY_LITERAL            "invalid array literal"
3094 #define DUK_STR_INVALID_OBJECT_LITERAL           "invalid object literal"
3095 #define DUK_STR_INVALID_VAR_DECLARATION          "invalid variable declaration"
3096 #define DUK_STR_CANNOT_DELETE_IDENTIFIER         "cannot delete identifier"
3097 #define DUK_STR_INVALID_EXPRESSION               "invalid expression"
3098 #define DUK_STR_INVALID_LVALUE                   "invalid lvalue"
3099 #define DUK_STR_INVALID_NEWTARGET                "invalid new.target"
3100 #define DUK_STR_EXPECTED_IDENTIFIER              "expected identifier"
3101 #define DUK_STR_EMPTY_EXPR_NOT_ALLOWED           "empty expression not allowed"
3102 #define DUK_STR_INVALID_FOR                      "invalid for statement"
3103 #define DUK_STR_INVALID_SWITCH                   "invalid switch statement"
3104 #define DUK_STR_INVALID_BREAK_CONT_LABEL         "invalid break/continue label"
3105 #define DUK_STR_INVALID_RETURN                   "invalid return"
3106 #define DUK_STR_INVALID_TRY                      "invalid try"
3107 #define DUK_STR_INVALID_THROW                    "invalid throw"
3108 #define DUK_STR_WITH_IN_STRICT_MODE              "with in strict mode"
3109 #define DUK_STR_FUNC_STMT_NOT_ALLOWED            "function statement not allowed"
3110 #define DUK_STR_UNTERMINATED_STMT                "unterminated statement"
3111 #define DUK_STR_INVALID_ARG_NAME                 "invalid argument name"
3112 #define DUK_STR_INVALID_FUNC_NAME                "invalid function name"
3113 #define DUK_STR_INVALID_GETSET_NAME              "invalid getter/setter name"
3114 #define DUK_STR_FUNC_NAME_REQUIRED               "function name required"
3115 
3116 /* RegExp */
3117 #define DUK_STR_INVALID_QUANTIFIER               "invalid regexp quantifier"
3118 #define DUK_STR_INVALID_QUANTIFIER_NO_ATOM       "quantifier without preceding atom"
3119 #define DUK_STR_INVALID_QUANTIFIER_VALUES        "quantifier values invalid (qmin > qmax)"
3120 #define DUK_STR_QUANTIFIER_TOO_MANY_COPIES       "quantifier requires too many atom copies"
3121 #define DUK_STR_UNEXPECTED_CLOSING_PAREN         "unexpected closing parenthesis"
3122 #define DUK_STR_UNEXPECTED_END_OF_PATTERN        "unexpected end of pattern"
3123 #define DUK_STR_UNEXPECTED_REGEXP_TOKEN          "unexpected token in regexp"
3124 #define DUK_STR_INVALID_REGEXP_FLAGS             "invalid regexp flags"
3125 #define DUK_STR_INVALID_REGEXP_ESCAPE            "invalid regexp escape"
3126 #define DUK_STR_INVALID_BACKREFS                 "invalid backreference(s)"
3127 #define DUK_STR_INVALID_REGEXP_CHARACTER         "invalid regexp character"
3128 #define DUK_STR_INVALID_REGEXP_GROUP             "invalid regexp group"
3129 #define DUK_STR_UNTERMINATED_CHARCLASS           "unterminated character class"
3130 #define DUK_STR_INVALID_RANGE                    "invalid range"
3131 
3132 /* Limits */
3133 #define DUK_STR_VALSTACK_LIMIT                   "valstack limit"
3134 #define DUK_STR_CALLSTACK_LIMIT                  "callstack limit"
3135 #define DUK_STR_PROTOTYPE_CHAIN_LIMIT            "prototype chain limit"
3136 #define DUK_STR_BOUND_CHAIN_LIMIT                "function call bound chain limit"
3137 #define DUK_STR_NATIVE_STACK_LIMIT               "C stack depth limit"
3138 #define DUK_STR_COMPILER_RECURSION_LIMIT         "compiler recursion limit"
3139 #define DUK_STR_BYTECODE_LIMIT                   "bytecode limit"
3140 #define DUK_STR_REG_LIMIT                        "register limit"
3141 #define DUK_STR_TEMP_LIMIT                       "temp limit"
3142 #define DUK_STR_CONST_LIMIT                      "const limit"
3143 #define DUK_STR_FUNC_LIMIT                       "function limit"
3144 #define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT  "regexp compiler recursion limit"
3145 #define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT  "regexp executor recursion limit"
3146 #define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT       "regexp step limit"
3147 
3148 #endif  /* DUK_ERRMSG_H_INCLUDED */
3149 /* #include duk_js_bytecode.h */
3150 /*
3151  *  ECMAScript bytecode
3152  */
3153 
3154 #if !defined(DUK_JS_BYTECODE_H_INCLUDED)
3155 #define DUK_JS_BYTECODE_H_INCLUDED
3156 
3157 /*
3158  *  Bytecode instruction layout
3159  *  ===========================
3160  *
3161  *  Instructions are unsigned 32-bit integers divided as follows:
3162  *
3163  *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
3164  *  !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!
3165  *  +-----------------------------------------------+---------------+
3166  *  !       C       !       B       !       A       !       OP      !
3167  *  +-----------------------------------------------+---------------+
3168  *
3169  *  OP (8 bits):  opcode (DUK_OP_*), access should be fastest
3170  *                consecutive opcodes allocated when opcode needs flags
3171  *   A (8 bits):  typically a target register number
3172  *   B (8 bits):  typically first source register/constant number
3173  *   C (8 bits):  typically second source register/constant number
3174  *
3175  *  Some instructions combine BC or ABC together for larger parameter values.
3176  *  Signed integers (e.g. jump offsets) are encoded as unsigned, with an
3177  *  opcode specific bias.
3178  *
3179  *  Some opcodes have flags which are handled by allocating consecutive
3180  *  opcodes to make space for 1-N flags.  Flags can also be e.g. in the 'A'
3181  *  field when there's room for the specific opcode.
3182  *
3183  *  For example, if three flags were needed, they could be allocated from
3184  *  the opcode field as follows:
3185  *
3186  *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
3187  *  !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!
3188  *  +-----------------------------------------------+---------------+
3189  *  !       C       !       B       !       A       !    OP   !Z!Y!X!
3190  *  +-----------------------------------------------+---------------+
3191  *
3192  *  Some opcodes accept a reg/const argument which is handled by allocating
3193  *  flags in the OP field, see DUK_BC_ISREG() and DUK_BC_ISCONST().  The
3194  *  following convention is shared by most opcodes, so that the compiler
3195  *  can handle reg/const flagging without opcode specific code paths:
3196  *
3197  *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
3198  *  !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!
3199  *  +-----------------------------------------------+---------------+
3200  *  !       C       !       B       !       A       !     OP    !Y!X!
3201  *  +-----------------------------------------------+---------------+
3202  *
3203  *    X  1=B is const, 0=B is reg
3204  *    Y  1=C is const, 0=C is reg
3205  *
3206  *    In effect OP, OP + 1, OP + 2, and OP + 3 are allocated from the
3207  *    8-bit opcode space for a single logical opcode.  The base opcode
3208  *    number should be divisible by 4.  If the opcode is called 'FOO'
3209  *    the following opcode constants would be defined:
3210  *
3211  *      DUK_OP_FOO     100       // base opcode number
3212  *      DUK_OP_FOO_RR  100       // FOO, B=reg, C=reg
3213  *      DUK_OP_FOO_CR  101       // FOO, B=const, C=reg
3214  *      DUK_OP_FOO_RC  102       // FOO, B=reg, C=const
3215  *      DUK_OP_FOO_CC  103       // FOO, B=const, C=const
3216  *
3217  *  If only B or C is a reg/const, the unused opcode combinations can be
3218  *  used for other opcodes (which take no reg/const argument).  However,
3219  *  such opcode values are initially reserved, at least while opcode space
3220  *  is available.  For example, if 'BAR' uses B for a register field and
3221  *  C is a reg/const:
3222  *
3223  *      DUK_OP_BAR            116    // base opcode number
3224  *      DUK_OP_BAR_RR         116    // BAR, B=reg, C=reg
3225  *      DUK_OP_BAR_CR_UNUSED  117    // unused, could be repurposed
3226  *      DUK_OP_BAR_RC         118    // BAR, B=reg, C=const
3227  *      DUK_OP_BAR_CC_UNUSED  119    // unused, could be repurposed
3228  *
3229  *  Macro naming is a bit misleading, e.g. "ABC" in macro name but the
3230  *  field layout is concretely "CBA" in the register.
3231  */
3232 
3233 typedef duk_uint32_t duk_instr_t;
3234 
3235 #define DUK_BC_SHIFT_OP             0
3236 #define DUK_BC_SHIFT_A              8
3237 #define DUK_BC_SHIFT_B              16
3238 #define DUK_BC_SHIFT_C              24
3239 #define DUK_BC_SHIFT_BC             DUK_BC_SHIFT_B
3240 #define DUK_BC_SHIFT_ABC            DUK_BC_SHIFT_A
3241 
3242 #define DUK_BC_UNSHIFTED_MASK_OP    0xffUL
3243 #define DUK_BC_UNSHIFTED_MASK_A     0xffUL
3244 #define DUK_BC_UNSHIFTED_MASK_B     0xffUL
3245 #define DUK_BC_UNSHIFTED_MASK_C     0xffUL
3246 #define DUK_BC_UNSHIFTED_MASK_BC    0xffffUL
3247 #define DUK_BC_UNSHIFTED_MASK_ABC   0xffffffUL
3248 
3249 #define DUK_BC_SHIFTED_MASK_OP      (DUK_BC_UNSHIFTED_MASK_OP << DUK_BC_SHIFT_OP)
3250 #define DUK_BC_SHIFTED_MASK_A       (DUK_BC_UNSHIFTED_MASK_A << DUK_BC_SHIFT_A)
3251 #define DUK_BC_SHIFTED_MASK_B       (DUK_BC_UNSHIFTED_MASK_B << DUK_BC_SHIFT_B)
3252 #define DUK_BC_SHIFTED_MASK_C       (DUK_BC_UNSHIFTED_MASK_C << DUK_BC_SHIFT_C)
3253 #define DUK_BC_SHIFTED_MASK_BC      (DUK_BC_UNSHIFTED_MASK_BC << DUK_BC_SHIFT_BC)
3254 #define DUK_BC_SHIFTED_MASK_ABC     (DUK_BC_UNSHIFTED_MASK_ABC << DUK_BC_SHIFT_ABC)
3255 
3256 #define DUK_DEC_OP(x)               ((x) & 0xffUL)
3257 #define DUK_DEC_A(x)                (((x) >> 8) & 0xffUL)
3258 #define DUK_DEC_B(x)                (((x) >> 16) & 0xffUL)
3259 #define DUK_DEC_C(x)                (((x) >> 24) & 0xffUL)
3260 #define DUK_DEC_BC(x)               (((x) >> 16) & 0xffffUL)
3261 #define DUK_DEC_ABC(x)              (((x) >> 8) & 0xffffffUL)
3262 
3263 #define DUK_ENC_OP(op)              ((duk_instr_t) (op))
3264 #define DUK_ENC_OP_ABC(op,abc)      ((duk_instr_t) ( \
3265                                         (((duk_instr_t) (abc)) << 8) | \
3266                                         ((duk_instr_t) (op)) \
3267                                     ))
3268 #define DUK_ENC_OP_A_BC(op,a,bc)    ((duk_instr_t) ( \
3269                                         (((duk_instr_t) (bc)) << 16) | \
3270                                         (((duk_instr_t) (a)) << 8) | \
3271                                         ((duk_instr_t) (op)) \
3272                                     ))
3273 #define DUK_ENC_OP_A_B_C(op,a,b,c)  ((duk_instr_t) ( \
3274                                         (((duk_instr_t) (c)) << 24) | \
3275                                         (((duk_instr_t) (b)) << 16) | \
3276                                         (((duk_instr_t) (a)) << 8) | \
3277                                         ((duk_instr_t) (op)) \
3278                                     ))
3279 #define DUK_ENC_OP_A_B(op,a,b)      DUK_ENC_OP_A_B_C((op),(a),(b),0)
3280 #define DUK_ENC_OP_A(op,a)          DUK_ENC_OP_A_B_C((op),(a),0,0)
3281 #define DUK_ENC_OP_BC(op,bc)        DUK_ENC_OP_A_BC((op),0,(bc))
3282 
3283 /* Get opcode base value with B/C reg/const flags cleared. */
3284 #define DUK_BC_NOREGCONST_OP(op)    ((op) & 0xfc)
3285 
3286 /* Constants should be signed so that signed arithmetic involving them
3287  * won't cause values to be coerced accidentally to unsigned.
3288  */
3289 #define DUK_BC_OP_MIN               0
3290 #define DUK_BC_OP_MAX               0xffL
3291 #define DUK_BC_A_MIN                0
3292 #define DUK_BC_A_MAX                0xffL
3293 #define DUK_BC_B_MIN                0
3294 #define DUK_BC_B_MAX                0xffL
3295 #define DUK_BC_C_MIN                0
3296 #define DUK_BC_C_MAX                0xffL
3297 #define DUK_BC_BC_MIN               0
3298 #define DUK_BC_BC_MAX               0xffffL
3299 #define DUK_BC_ABC_MIN              0
3300 #define DUK_BC_ABC_MAX              0xffffffL
3301 
3302 /* Masks for B/C reg/const indicator in opcode field. */
3303 #define DUK_BC_REGCONST_B           (0x01UL)
3304 #define DUK_BC_REGCONST_C           (0x02UL)
3305 
3306 /* Misc. masks for opcode field. */
3307 #define DUK_BC_INCDECP_FLAG_DEC     (0x04UL)
3308 #define DUK_BC_INCDECP_FLAG_POST    (0x08UL)
3309 
3310 /* Opcodes. */
3311 #define DUK_OP_LDREG                0
3312 #define DUK_OP_STREG                1
3313 #define DUK_OP_JUMP                 2
3314 #define DUK_OP_LDCONST              3
3315 #define DUK_OP_LDINT                4
3316 #define DUK_OP_LDINTX               5
3317 #define DUK_OP_LDTHIS               6
3318 #define DUK_OP_LDUNDEF              7
3319 #define DUK_OP_LDNULL               8
3320 #define DUK_OP_LDTRUE               9
3321 #define DUK_OP_LDFALSE              10
3322 #define DUK_OP_GETVAR               11
3323 #define DUK_OP_BNOT                 12
3324 #define DUK_OP_LNOT                 13
3325 #define DUK_OP_UNM                  14
3326 #define DUK_OP_UNP                  15
3327 #define DUK_OP_EQ                   16
3328 #define DUK_OP_EQ_RR                16
3329 #define DUK_OP_EQ_CR                17
3330 #define DUK_OP_EQ_RC                18
3331 #define DUK_OP_EQ_CC                19
3332 #define DUK_OP_NEQ                  20
3333 #define DUK_OP_NEQ_RR               20
3334 #define DUK_OP_NEQ_CR               21
3335 #define DUK_OP_NEQ_RC               22
3336 #define DUK_OP_NEQ_CC               23
3337 #define DUK_OP_SEQ                  24
3338 #define DUK_OP_SEQ_RR               24
3339 #define DUK_OP_SEQ_CR               25
3340 #define DUK_OP_SEQ_RC               26
3341 #define DUK_OP_SEQ_CC               27
3342 #define DUK_OP_SNEQ                 28
3343 #define DUK_OP_SNEQ_RR              28
3344 #define DUK_OP_SNEQ_CR              29
3345 #define DUK_OP_SNEQ_RC              30
3346 #define DUK_OP_SNEQ_CC              31
3347 #define DUK_OP_GT                   32
3348 #define DUK_OP_GT_RR                32
3349 #define DUK_OP_GT_CR                33
3350 #define DUK_OP_GT_RC                34
3351 #define DUK_OP_GT_CC                35
3352 #define DUK_OP_GE                   36
3353 #define DUK_OP_GE_RR                36
3354 #define DUK_OP_GE_CR                37
3355 #define DUK_OP_GE_RC                38
3356 #define DUK_OP_GE_CC                39
3357 #define DUK_OP_LT                   40
3358 #define DUK_OP_LT_RR                40
3359 #define DUK_OP_LT_CR                41
3360 #define DUK_OP_LT_RC                42
3361 #define DUK_OP_LT_CC                43
3362 #define DUK_OP_LE                   44
3363 #define DUK_OP_LE_RR                44
3364 #define DUK_OP_LE_CR                45
3365 #define DUK_OP_LE_RC                46
3366 #define DUK_OP_LE_CC                47
3367 #define DUK_OP_IFTRUE               48
3368 #define DUK_OP_IFTRUE_R             48
3369 #define DUK_OP_IFTRUE_C             49
3370 #define DUK_OP_IFFALSE              50
3371 #define DUK_OP_IFFALSE_R            50
3372 #define DUK_OP_IFFALSE_C            51
3373 #define DUK_OP_ADD                  52
3374 #define DUK_OP_ADD_RR               52
3375 #define DUK_OP_ADD_CR               53
3376 #define DUK_OP_ADD_RC               54
3377 #define DUK_OP_ADD_CC               55
3378 #define DUK_OP_SUB                  56
3379 #define DUK_OP_SUB_RR               56
3380 #define DUK_OP_SUB_CR               57
3381 #define DUK_OP_SUB_RC               58
3382 #define DUK_OP_SUB_CC               59
3383 #define DUK_OP_MUL                  60
3384 #define DUK_OP_MUL_RR               60
3385 #define DUK_OP_MUL_CR               61
3386 #define DUK_OP_MUL_RC               62
3387 #define DUK_OP_MUL_CC               63
3388 #define DUK_OP_DIV                  64
3389 #define DUK_OP_DIV_RR               64
3390 #define DUK_OP_DIV_CR               65
3391 #define DUK_OP_DIV_RC               66
3392 #define DUK_OP_DIV_CC               67
3393 #define DUK_OP_MOD                  68
3394 #define DUK_OP_MOD_RR               68
3395 #define DUK_OP_MOD_CR               69
3396 #define DUK_OP_MOD_RC               70
3397 #define DUK_OP_MOD_CC               71
3398 #define DUK_OP_EXP                  72
3399 #define DUK_OP_EXP_RR               72
3400 #define DUK_OP_EXP_CR               73
3401 #define DUK_OP_EXP_RC               74
3402 #define DUK_OP_EXP_CC               75
3403 #define DUK_OP_BAND                 76
3404 #define DUK_OP_BAND_RR              76
3405 #define DUK_OP_BAND_CR              77
3406 #define DUK_OP_BAND_RC              78
3407 #define DUK_OP_BAND_CC              79
3408 #define DUK_OP_BOR                  80
3409 #define DUK_OP_BOR_RR               80
3410 #define DUK_OP_BOR_CR               81
3411 #define DUK_OP_BOR_RC               82
3412 #define DUK_OP_BOR_CC               83
3413 #define DUK_OP_BXOR                 84
3414 #define DUK_OP_BXOR_RR              84
3415 #define DUK_OP_BXOR_CR              85
3416 #define DUK_OP_BXOR_RC              86
3417 #define DUK_OP_BXOR_CC              87
3418 #define DUK_OP_BASL                 88
3419 #define DUK_OP_BASL_RR              88
3420 #define DUK_OP_BASL_CR              89
3421 #define DUK_OP_BASL_RC              90
3422 #define DUK_OP_BASL_CC              91
3423 #define DUK_OP_BLSR                 92
3424 #define DUK_OP_BLSR_RR              92
3425 #define DUK_OP_BLSR_CR              93
3426 #define DUK_OP_BLSR_RC              94
3427 #define DUK_OP_BLSR_CC              95
3428 #define DUK_OP_BASR                 96
3429 #define DUK_OP_BASR_RR              96
3430 #define DUK_OP_BASR_CR              97
3431 #define DUK_OP_BASR_RC              98
3432 #define DUK_OP_BASR_CC              99
3433 #define DUK_OP_INSTOF               100
3434 #define DUK_OP_INSTOF_RR            100
3435 #define DUK_OP_INSTOF_CR            101
3436 #define DUK_OP_INSTOF_RC            102
3437 #define DUK_OP_INSTOF_CC            103
3438 #define DUK_OP_IN                   104
3439 #define DUK_OP_IN_RR                104
3440 #define DUK_OP_IN_CR                105
3441 #define DUK_OP_IN_RC                106
3442 #define DUK_OP_IN_CC                107
3443 #define DUK_OP_GETPROP              108
3444 #define DUK_OP_GETPROP_RR           108
3445 #define DUK_OP_GETPROP_CR           109
3446 #define DUK_OP_GETPROP_RC           110
3447 #define DUK_OP_GETPROP_CC           111
3448 #define DUK_OP_PUTPROP              112
3449 #define DUK_OP_PUTPROP_RR           112
3450 #define DUK_OP_PUTPROP_CR           113
3451 #define DUK_OP_PUTPROP_RC           114
3452 #define DUK_OP_PUTPROP_CC           115
3453 #define DUK_OP_DELPROP              116
3454 #define DUK_OP_DELPROP_RR           116
3455 #define DUK_OP_DELPROP_CR_UNUSED    117  /* unused now */
3456 #define DUK_OP_DELPROP_RC           118
3457 #define DUK_OP_DELPROP_CC_UNUSED    119  /* unused now */
3458 #define DUK_OP_PREINCR              120  /* pre/post opcode values have constraints, */
3459 #define DUK_OP_PREDECR              121  /* see duk_js_executor.c and duk_js_compiler.c. */
3460 #define DUK_OP_POSTINCR             122
3461 #define DUK_OP_POSTDECR             123
3462 #define DUK_OP_PREINCV              124
3463 #define DUK_OP_PREDECV              125
3464 #define DUK_OP_POSTINCV             126
3465 #define DUK_OP_POSTDECV             127
3466 #define DUK_OP_PREINCP              128  /* pre/post inc/dec prop opcodes have constraints */
3467 #define DUK_OP_PREINCP_RR           128
3468 #define DUK_OP_PREINCP_CR           129
3469 #define DUK_OP_PREINCP_RC           130
3470 #define DUK_OP_PREINCP_CC           131
3471 #define DUK_OP_PREDECP              132
3472 #define DUK_OP_PREDECP_RR           132
3473 #define DUK_OP_PREDECP_CR           133
3474 #define DUK_OP_PREDECP_RC           134
3475 #define DUK_OP_PREDECP_CC           135
3476 #define DUK_OP_POSTINCP             136
3477 #define DUK_OP_POSTINCP_RR          136
3478 #define DUK_OP_POSTINCP_CR          137
3479 #define DUK_OP_POSTINCP_RC          138
3480 #define DUK_OP_POSTINCP_CC          139
3481 #define DUK_OP_POSTDECP             140
3482 #define DUK_OP_POSTDECP_RR          140
3483 #define DUK_OP_POSTDECP_CR          141
3484 #define DUK_OP_POSTDECP_RC          142
3485 #define DUK_OP_POSTDECP_CC          143
3486 #define DUK_OP_DECLVAR              144
3487 #define DUK_OP_DECLVAR_RR           144
3488 #define DUK_OP_DECLVAR_CR           145
3489 #define DUK_OP_DECLVAR_RC           146
3490 #define DUK_OP_DECLVAR_CC           147
3491 #define DUK_OP_REGEXP               148
3492 #define DUK_OP_REGEXP_RR            148
3493 #define DUK_OP_REGEXP_CR            149
3494 #define DUK_OP_REGEXP_RC            150
3495 #define DUK_OP_REGEXP_CC            151
3496 #define DUK_OP_CLOSURE              152
3497 #define DUK_OP_TYPEOF               153
3498 #define DUK_OP_TYPEOFID             154
3499 #define DUK_OP_PUTVAR               155
3500 #define DUK_OP_DELVAR               156
3501 #define DUK_OP_RETREG               157
3502 #define DUK_OP_RETUNDEF             158
3503 #define DUK_OP_RETCONST             159
3504 #define DUK_OP_RETCONSTN            160  /* return const without incref (e.g. number) */
3505 #define DUK_OP_LABEL                161
3506 #define DUK_OP_ENDLABEL             162
3507 #define DUK_OP_BREAK                163
3508 #define DUK_OP_CONTINUE             164
3509 #define DUK_OP_TRYCATCH             165
3510 #define DUK_OP_ENDTRY               166
3511 #define DUK_OP_ENDCATCH             167
3512 #define DUK_OP_ENDFIN               168
3513 #define DUK_OP_THROW                169
3514 #define DUK_OP_INVLHS               170
3515 #define DUK_OP_CSREG                171
3516 #define DUK_OP_CSVAR                172
3517 #define DUK_OP_CSVAR_RR             172
3518 #define DUK_OP_CSVAR_CR             173
3519 #define DUK_OP_CSVAR_RC             174
3520 #define DUK_OP_CSVAR_CC             175
3521 #define DUK_OP_CALL0                176  /* DUK_OP_CALL0 & 0x0F must be zero. */
3522 #define DUK_OP_CALL1                177
3523 #define DUK_OP_CALL2                178
3524 #define DUK_OP_CALL3                179
3525 #define DUK_OP_CALL4                180
3526 #define DUK_OP_CALL5                181
3527 #define DUK_OP_CALL6                182
3528 #define DUK_OP_CALL7                183
3529 #define DUK_OP_CALL8                184
3530 #define DUK_OP_CALL9                185
3531 #define DUK_OP_CALL10               186
3532 #define DUK_OP_CALL11               187
3533 #define DUK_OP_CALL12               188
3534 #define DUK_OP_CALL13               189
3535 #define DUK_OP_CALL14               190
3536 #define DUK_OP_CALL15               191
3537 #define DUK_OP_NEWOBJ               192
3538 #define DUK_OP_NEWARR               193
3539 #define DUK_OP_MPUTOBJ              194
3540 #define DUK_OP_MPUTOBJI             195
3541 #define DUK_OP_INITSET              196
3542 #define DUK_OP_INITGET              197
3543 #define DUK_OP_MPUTARR              198
3544 #define DUK_OP_MPUTARRI             199
3545 #define DUK_OP_SETALEN              200
3546 #define DUK_OP_INITENUM             201
3547 #define DUK_OP_NEXTENUM             202
3548 #define DUK_OP_NEWTARGET            203
3549 #define DUK_OP_DEBUGGER             204
3550 #define DUK_OP_NOP                  205
3551 #define DUK_OP_INVALID              206
3552 #define DUK_OP_UNUSED207            207
3553 #define DUK_OP_GETPROPC             208
3554 #define DUK_OP_GETPROPC_RR          208
3555 #define DUK_OP_GETPROPC_CR          209
3556 #define DUK_OP_GETPROPC_RC          210
3557 #define DUK_OP_GETPROPC_CC          211
3558 #define DUK_OP_UNUSED212            212
3559 #define DUK_OP_UNUSED213            213
3560 #define DUK_OP_UNUSED214            214
3561 #define DUK_OP_UNUSED215            215
3562 #define DUK_OP_UNUSED216            216
3563 #define DUK_OP_UNUSED217            217
3564 #define DUK_OP_UNUSED218            218
3565 #define DUK_OP_UNUSED219            219
3566 #define DUK_OP_UNUSED220            220
3567 #define DUK_OP_UNUSED221            221
3568 #define DUK_OP_UNUSED222            222
3569 #define DUK_OP_UNUSED223            223
3570 #define DUK_OP_UNUSED224            224
3571 #define DUK_OP_UNUSED225            225
3572 #define DUK_OP_UNUSED226            226
3573 #define DUK_OP_UNUSED227            227
3574 #define DUK_OP_UNUSED228            228
3575 #define DUK_OP_UNUSED229            229
3576 #define DUK_OP_UNUSED230            230
3577 #define DUK_OP_UNUSED231            231
3578 #define DUK_OP_UNUSED232            232
3579 #define DUK_OP_UNUSED233            233
3580 #define DUK_OP_UNUSED234            234
3581 #define DUK_OP_UNUSED235            235
3582 #define DUK_OP_UNUSED236            236
3583 #define DUK_OP_UNUSED237            237
3584 #define DUK_OP_UNUSED238            238
3585 #define DUK_OP_UNUSED239            239
3586 #define DUK_OP_UNUSED240            240
3587 #define DUK_OP_UNUSED241            241
3588 #define DUK_OP_UNUSED242            242
3589 #define DUK_OP_UNUSED243            243
3590 #define DUK_OP_UNUSED244            244
3591 #define DUK_OP_UNUSED245            245
3592 #define DUK_OP_UNUSED246            246
3593 #define DUK_OP_UNUSED247            247
3594 #define DUK_OP_UNUSED248            248
3595 #define DUK_OP_UNUSED249            249
3596 #define DUK_OP_UNUSED250            250
3597 #define DUK_OP_UNUSED251            251
3598 #define DUK_OP_UNUSED252            252
3599 #define DUK_OP_UNUSED253            253
3600 #define DUK_OP_UNUSED254            254
3601 #define DUK_OP_UNUSED255            255
3602 #define DUK_OP_NONE                 256  /* dummy value used as marker (doesn't fit in 8-bit field) */
3603 
3604 /* XXX: Allocate flags from opcode field?  Would take 16 opcode slots
3605  * but avoids shuffling in more cases.  Maybe not worth it.
3606  */
3607 /* DUK_OP_TRYCATCH flags in A. */
3608 #define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH     (1U << 0)
3609 #define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY   (1U << 1)
3610 #define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING  (1U << 2)
3611 #define DUK_BC_TRYCATCH_FLAG_WITH_BINDING   (1U << 3)
3612 
3613 /* DUK_OP_DECLVAR flags in A; bottom bits are reserved for propdesc flags
3614  * (DUK_PROPDESC_FLAG_XXX).
3615  */
3616 #define DUK_BC_DECLVAR_FLAG_FUNC_DECL       (1U << 4)  /* function declaration */
3617 
3618 /* DUK_OP_CALLn flags, part of opcode field.  Three lowest bits must match
3619  * DUK_CALL_FLAG_xxx directly.
3620  */
3621 #define DUK_BC_CALL_FLAG_TAILCALL           (1U << 0)
3622 #define DUK_BC_CALL_FLAG_CONSTRUCT          (1U << 1)
3623 #define DUK_BC_CALL_FLAG_CALLED_AS_EVAL     (1U << 2)
3624 #define DUK_BC_CALL_FLAG_INDIRECT           (1U << 3)
3625 
3626 /* Misc constants and helper macros. */
3627 #define DUK_BC_LDINT_BIAS           (1L << 15)
3628 #define DUK_BC_LDINTX_SHIFT         16
3629 #define DUK_BC_JUMP_BIAS            (1L << 23)
3630 
3631 #endif  /* DUK_JS_BYTECODE_H_INCLUDED */
3632 /* #include duk_lexer.h */
3633 /*
3634  *  Lexer defines.
3635  */
3636 
3637 #if !defined(DUK_LEXER_H_INCLUDED)
3638 #define DUK_LEXER_H_INCLUDED
3639 
3640 typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct);
3641 
3642 /*
3643  *  A token is interpreted as any possible production of InputElementDiv
3644  *  and InputElementRegExp, see E5 Section 7 in its entirety.  Note that
3645  *  the E5 "Token" production does not cover all actual tokens of the
3646  *  language (which is explicitly stated in the specification, Section 7.5).
3647  *  Null and boolean literals are defined as part of both ReservedWord
3648  *  (E5 Section 7.6.1) and Literal (E5 Section 7.8) productions.  Here,
3649  *  null and boolean values have literal tokens, and are not reserved
3650  *  words.
3651  *
3652  *  Decimal literal negative/positive sign is -not- part of DUK_TOK_NUMBER.
3653  *  The number tokens always have a non-negative value.  The unary minus
3654  *  operator in "-1.0" is optimized during compilation to yield a single
3655  *  negative constant.
3656  *
3657  *  Token numbering is free except that reserved words are required to be
3658  *  in a continuous range and in a particular order.  See genstrings.py.
3659  */
3660 
3661 #define DUK_LEXER_INITCTX(ctx)        duk_lexer_initctx((ctx))
3662 
3663 #define DUK_LEXER_SETPOINT(ctx,pt)    duk_lexer_setpoint((ctx), (pt))
3664 
3665 #define DUK_LEXER_GETPOINT(ctx,pt)    duk_lexer_getpoint((ctx), (pt))
3666 
3667 /* Currently 6 characters of lookup are actually needed (duk_lexer.c). */
3668 #define DUK_LEXER_WINDOW_SIZE                     6
3669 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
3670 #define DUK_LEXER_BUFFER_SIZE                     64
3671 #endif
3672 
3673 #define DUK_TOK_MINVAL                            0
3674 
3675 /* returned after EOF (infinite amount) */
3676 #define DUK_TOK_EOF                               0
3677 
3678 /* identifier names (E5 Section 7.6) */
3679 #define DUK_TOK_IDENTIFIER                        1
3680 
3681 /* reserved words: keywords */
3682 #define DUK_TOK_START_RESERVED                    2
3683 #define DUK_TOK_BREAK                             2
3684 #define DUK_TOK_CASE                              3
3685 #define DUK_TOK_CATCH                             4
3686 #define DUK_TOK_CONTINUE                          5
3687 #define DUK_TOK_DEBUGGER                          6
3688 #define DUK_TOK_DEFAULT                           7
3689 #define DUK_TOK_DELETE                            8
3690 #define DUK_TOK_DO                                9
3691 #define DUK_TOK_ELSE                              10
3692 #define DUK_TOK_FINALLY                           11
3693 #define DUK_TOK_FOR                               12
3694 #define DUK_TOK_FUNCTION                          13
3695 #define DUK_TOK_IF                                14
3696 #define DUK_TOK_IN                                15
3697 #define DUK_TOK_INSTANCEOF                        16
3698 #define DUK_TOK_NEW                               17
3699 #define DUK_TOK_RETURN                            18
3700 #define DUK_TOK_SWITCH                            19
3701 #define DUK_TOK_THIS                              20
3702 #define DUK_TOK_THROW                             21
3703 #define DUK_TOK_TRY                               22
3704 #define DUK_TOK_TYPEOF                            23
3705 #define DUK_TOK_VAR                               24
3706 #define DUK_TOK_CONST                             25
3707 #define DUK_TOK_VOID                              26
3708 #define DUK_TOK_WHILE                             27
3709 #define DUK_TOK_WITH                              28
3710 
3711 /* reserved words: future reserved words */
3712 #define DUK_TOK_CLASS                             29
3713 #define DUK_TOK_ENUM                              30
3714 #define DUK_TOK_EXPORT                            31
3715 #define DUK_TOK_EXTENDS                           32
3716 #define DUK_TOK_IMPORT                            33
3717 #define DUK_TOK_SUPER                             34
3718 
3719 /* "null", "true", and "false" are always reserved words.
3720  * Note that "get" and "set" are not!
3721  */
3722 #define DUK_TOK_NULL                              35
3723 #define DUK_TOK_TRUE                              36
3724 #define DUK_TOK_FALSE                             37
3725 
3726 /* reserved words: additional future reserved words in strict mode */
3727 #define DUK_TOK_START_STRICT_RESERVED             38  /* inclusive */
3728 #define DUK_TOK_IMPLEMENTS                        38
3729 #define DUK_TOK_INTERFACE                         39
3730 #define DUK_TOK_LET                               40
3731 #define DUK_TOK_PACKAGE                           41
3732 #define DUK_TOK_PRIVATE                           42
3733 #define DUK_TOK_PROTECTED                         43
3734 #define DUK_TOK_PUBLIC                            44
3735 #define DUK_TOK_STATIC                            45
3736 #define DUK_TOK_YIELD                             46
3737 
3738 #define DUK_TOK_END_RESERVED                      47  /* exclusive */
3739 
3740 /* "get" and "set" are tokens but NOT ReservedWords.  They are currently
3741  * parsed and identifiers and these defines are actually now unused.
3742  */
3743 #define DUK_TOK_GET                               47
3744 #define DUK_TOK_SET                               48
3745 
3746 /* punctuators (unlike the spec, also includes "/" and "/=") */
3747 #define DUK_TOK_LCURLY                            49
3748 #define DUK_TOK_RCURLY                            50
3749 #define DUK_TOK_LBRACKET                          51
3750 #define DUK_TOK_RBRACKET                          52
3751 #define DUK_TOK_LPAREN                            53
3752 #define DUK_TOK_RPAREN                            54
3753 #define DUK_TOK_PERIOD                            55
3754 #define DUK_TOK_SEMICOLON                         56
3755 #define DUK_TOK_COMMA                             57
3756 #define DUK_TOK_LT                                58
3757 #define DUK_TOK_GT                                59
3758 #define DUK_TOK_LE                                60
3759 #define DUK_TOK_GE                                61
3760 #define DUK_TOK_EQ                                62
3761 #define DUK_TOK_NEQ                               63
3762 #define DUK_TOK_SEQ                               64
3763 #define DUK_TOK_SNEQ                              65
3764 #define DUK_TOK_ADD                               66
3765 #define DUK_TOK_SUB                               67
3766 #define DUK_TOK_MUL                               68
3767 #define DUK_TOK_DIV                               69
3768 #define DUK_TOK_MOD                               70
3769 #define DUK_TOK_EXP                               71
3770 #define DUK_TOK_INCREMENT                         72
3771 #define DUK_TOK_DECREMENT                         73
3772 #define DUK_TOK_ALSHIFT                           74   /* named "arithmetic" because result is signed */
3773 #define DUK_TOK_ARSHIFT                           75
3774 #define DUK_TOK_RSHIFT                            76
3775 #define DUK_TOK_BAND                              77
3776 #define DUK_TOK_BOR                               78
3777 #define DUK_TOK_BXOR                              79
3778 #define DUK_TOK_LNOT                              80
3779 #define DUK_TOK_BNOT                              81
3780 #define DUK_TOK_LAND                              82
3781 #define DUK_TOK_LOR                               83
3782 #define DUK_TOK_QUESTION                          84
3783 #define DUK_TOK_COLON                             85
3784 #define DUK_TOK_EQUALSIGN                         86
3785 #define DUK_TOK_ADD_EQ                            87
3786 #define DUK_TOK_SUB_EQ                            88
3787 #define DUK_TOK_MUL_EQ                            89
3788 #define DUK_TOK_DIV_EQ                            90
3789 #define DUK_TOK_MOD_EQ                            91
3790 #define DUK_TOK_EXP_EQ                            92
3791 #define DUK_TOK_ALSHIFT_EQ                        93
3792 #define DUK_TOK_ARSHIFT_EQ                        94
3793 #define DUK_TOK_RSHIFT_EQ                         95
3794 #define DUK_TOK_BAND_EQ                           96
3795 #define DUK_TOK_BOR_EQ                            97
3796 #define DUK_TOK_BXOR_EQ                           98
3797 
3798 /* literals (E5 Section 7.8), except null, true, false, which are treated
3799  * like reserved words (above).
3800  */
3801 #define DUK_TOK_NUMBER                            99
3802 #define DUK_TOK_STRING                            100
3803 #define DUK_TOK_REGEXP                            101
3804 
3805 #define DUK_TOK_MAXVAL                            101  /* inclusive */
3806 
3807 #define DUK_TOK_INVALID                           DUK_SMALL_UINT_MAX
3808 
3809 /* Convert heap string index to a token (reserved words) */
3810 #define DUK_STRIDX_TO_TOK(x)                        ((x) - DUK_STRIDX_START_RESERVED + DUK_TOK_START_RESERVED)
3811 
3812 /* Sanity check */
3813 #if (DUK_TOK_MAXVAL > 255)
3814 #error DUK_TOK_MAXVAL too large, code assumes it fits into 8 bits
3815 #endif
3816 
3817 /* Sanity checks for string and token defines */
3818 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_BREAK) != DUK_TOK_BREAK)
3819 #error mismatch in token defines
3820 #endif
3821 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CASE) != DUK_TOK_CASE)
3822 #error mismatch in token defines
3823 #endif
3824 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CATCH) != DUK_TOK_CATCH)
3825 #error mismatch in token defines
3826 #endif
3827 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONTINUE) != DUK_TOK_CONTINUE)
3828 #error mismatch in token defines
3829 #endif
3830 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEBUGGER) != DUK_TOK_DEBUGGER)
3831 #error mismatch in token defines
3832 #endif
3833 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEFAULT) != DUK_TOK_DEFAULT)
3834 #error mismatch in token defines
3835 #endif
3836 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DELETE) != DUK_TOK_DELETE)
3837 #error mismatch in token defines
3838 #endif
3839 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DO) != DUK_TOK_DO)
3840 #error mismatch in token defines
3841 #endif
3842 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ELSE) != DUK_TOK_ELSE)
3843 #error mismatch in token defines
3844 #endif
3845 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FINALLY) != DUK_TOK_FINALLY)
3846 #error mismatch in token defines
3847 #endif
3848 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FOR) != DUK_TOK_FOR)
3849 #error mismatch in token defines
3850 #endif
3851 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_FUNCTION) != DUK_TOK_FUNCTION)
3852 #error mismatch in token defines
3853 #endif
3854 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IF) != DUK_TOK_IF)
3855 #error mismatch in token defines
3856 #endif
3857 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IN) != DUK_TOK_IN)
3858 #error mismatch in token defines
3859 #endif
3860 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INSTANCEOF) != DUK_TOK_INSTANCEOF)
3861 #error mismatch in token defines
3862 #endif
3863 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_NEW) != DUK_TOK_NEW)
3864 #error mismatch in token defines
3865 #endif
3866 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_RETURN) != DUK_TOK_RETURN)
3867 #error mismatch in token defines
3868 #endif
3869 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SWITCH) != DUK_TOK_SWITCH)
3870 #error mismatch in token defines
3871 #endif
3872 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THIS) != DUK_TOK_THIS)
3873 #error mismatch in token defines
3874 #endif
3875 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THROW) != DUK_TOK_THROW)
3876 #error mismatch in token defines
3877 #endif
3878 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRY) != DUK_TOK_TRY)
3879 #error mismatch in token defines
3880 #endif
3881 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TYPEOF) != DUK_TOK_TYPEOF)
3882 #error mismatch in token defines
3883 #endif
3884 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VAR) != DUK_TOK_VAR)
3885 #error mismatch in token defines
3886 #endif
3887 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VOID) != DUK_TOK_VOID)
3888 #error mismatch in token defines
3889 #endif
3890 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WHILE) != DUK_TOK_WHILE)
3891 #error mismatch in token defines
3892 #endif
3893 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WITH) != DUK_TOK_WITH)
3894 #error mismatch in token defines
3895 #endif
3896 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CLASS) != DUK_TOK_CLASS)
3897 #error mismatch in token defines
3898 #endif
3899 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONST) != DUK_TOK_CONST)
3900 #error mismatch in token defines
3901 #endif
3902 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ENUM) != DUK_TOK_ENUM)
3903 #error mismatch in token defines
3904 #endif
3905 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXPORT) != DUK_TOK_EXPORT)
3906 #error mismatch in token defines
3907 #endif
3908 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXTENDS) != DUK_TOK_EXTENDS)
3909 #error mismatch in token defines
3910 #endif
3911 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPORT) != DUK_TOK_IMPORT)
3912 #error mismatch in token defines
3913 #endif
3914 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SUPER) != DUK_TOK_SUPER)
3915 #error mismatch in token defines
3916 #endif
3917 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_NULL) != DUK_TOK_NULL)
3918 #error mismatch in token defines
3919 #endif
3920 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRUE) != DUK_TOK_TRUE)
3921 #error mismatch in token defines
3922 #endif
3923 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FALSE) != DUK_TOK_FALSE)
3924 #error mismatch in token defines
3925 #endif
3926 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPLEMENTS) != DUK_TOK_IMPLEMENTS)
3927 #error mismatch in token defines
3928 #endif
3929 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INTERFACE) != DUK_TOK_INTERFACE)
3930 #error mismatch in token defines
3931 #endif
3932 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LET) != DUK_TOK_LET)
3933 #error mismatch in token defines
3934 #endif
3935 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PACKAGE) != DUK_TOK_PACKAGE)
3936 #error mismatch in token defines
3937 #endif
3938 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PRIVATE) != DUK_TOK_PRIVATE)
3939 #error mismatch in token defines
3940 #endif
3941 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PROTECTED) != DUK_TOK_PROTECTED)
3942 #error mismatch in token defines
3943 #endif
3944 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PUBLIC) != DUK_TOK_PUBLIC)
3945 #error mismatch in token defines
3946 #endif
3947 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_STATIC) != DUK_TOK_STATIC)
3948 #error mismatch in token defines
3949 #endif
3950 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_YIELD) != DUK_TOK_YIELD)
3951 #error mismatch in token defines
3952 #endif
3953 
3954 /* Regexp tokens */
3955 #define DUK_RETOK_EOF                              0
3956 #define DUK_RETOK_DISJUNCTION                      1
3957 #define DUK_RETOK_QUANTIFIER                       2
3958 #define DUK_RETOK_ASSERT_START                     3
3959 #define DUK_RETOK_ASSERT_END                       4
3960 #define DUK_RETOK_ASSERT_WORD_BOUNDARY             5
3961 #define DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY         6
3962 #define DUK_RETOK_ASSERT_START_POS_LOOKAHEAD       7
3963 #define DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD       8
3964 #define DUK_RETOK_ATOM_PERIOD                      9
3965 #define DUK_RETOK_ATOM_CHAR                        10
3966 #define DUK_RETOK_ATOM_DIGIT                       11  /* assumptions in regexp compiler */
3967 #define DUK_RETOK_ATOM_NOT_DIGIT                   12  /* -""- */
3968 #define DUK_RETOK_ATOM_WHITE                       13  /* -""- */
3969 #define DUK_RETOK_ATOM_NOT_WHITE                   14  /* -""- */
3970 #define DUK_RETOK_ATOM_WORD_CHAR                   15  /* -""- */
3971 #define DUK_RETOK_ATOM_NOT_WORD_CHAR               16  /* -""- */
3972 #define DUK_RETOK_ATOM_BACKREFERENCE               17
3973 #define DUK_RETOK_ATOM_START_CAPTURE_GROUP         18
3974 #define DUK_RETOK_ATOM_START_NONCAPTURE_GROUP      19
3975 #define DUK_RETOK_ATOM_START_CHARCLASS             20
3976 #define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED    21
3977 #define DUK_RETOK_ATOM_END_GROUP                   22
3978 
3979 /* Constants for duk_lexer_ctx.buf. */
3980 #define DUK_LEXER_TEMP_BUF_LIMIT                   256
3981 
3982 /* A token value.  Can be memcpy()'d, but note that slot1/slot2 values are on the valstack.
3983  * Some fields (like num, str1, str2) are only valid for specific token types and may have
3984  * stale values otherwise.
3985  */
3986 struct duk_token {
3987 	duk_small_uint_t t;           /* token type (with reserved word identification) */
3988 	duk_small_uint_t t_nores;     /* token type (with reserved words as DUK_TOK_IDENTIFER) */
3989 	duk_double_t num;             /* numeric value of token */
3990 	duk_hstring *str1;            /* string 1 of token (borrowed, stored to ctx->slot1_idx) */
3991 	duk_hstring *str2;            /* string 2 of token (borrowed, stored to ctx->slot2_idx) */
3992 	duk_size_t start_offset;      /* start byte offset of token in lexer input */
3993 	duk_int_t start_line;         /* start line of token (first char) */
3994 	duk_int_t num_escapes;        /* number of escapes and line continuations (for directive prologue) */
3995 	duk_bool_t lineterm;          /* token was preceded by a lineterm */
3996 	duk_bool_t allow_auto_semi;   /* token allows automatic semicolon insertion (eof or preceded by newline) */
3997 };
3998 
3999 #define DUK_RE_QUANTIFIER_INFINITE         ((duk_uint32_t) 0xffffffffUL)
4000 
4001 /* A regexp token value. */
4002 struct duk_re_token {
4003 	duk_small_uint_t t;          /* token type */
4004 	duk_small_uint_t greedy;
4005 	duk_uint32_t num;            /* numeric value (character, count) */
4006 	duk_uint32_t qmin;
4007 	duk_uint32_t qmax;
4008 };
4009 
4010 /* A structure for 'snapshotting' a point for rewinding */
4011 struct duk_lexer_point {
4012 	duk_size_t offset;
4013 	duk_int_t line;
4014 };
4015 
4016 /* Lexer codepoint with additional info like offset/line number */
4017 struct duk_lexer_codepoint {
4018 	duk_codepoint_t codepoint;
4019 	duk_size_t offset;
4020 	duk_int_t line;
4021 };
4022 
4023 /* Lexer context.  Same context is used for ECMAScript and Regexp parsing. */
4024 struct duk_lexer_ctx {
4025 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
4026 	duk_lexer_codepoint *window; /* unicode code points, window[0] is always next, points to 'buffer' */
4027 	duk_lexer_codepoint buffer[DUK_LEXER_BUFFER_SIZE];
4028 #else
4029 	duk_lexer_codepoint window[DUK_LEXER_WINDOW_SIZE]; /* unicode code points, window[0] is always next */
4030 #endif
4031 
4032 	duk_hthread *thr;                              /* thread; minimizes argument passing */
4033 
4034 	const duk_uint8_t *input;                      /* input string (may be a user pointer) */
4035 	duk_size_t input_length;                       /* input byte length */
4036 	duk_size_t input_offset;                       /* input offset for window leading edge (not window[0]) */
4037 	duk_int_t input_line;                          /* input linenumber at input_offset (not window[0]), init to 1 */
4038 
4039 	duk_idx_t slot1_idx;                           /* valstack slot for 1st token value */
4040 	duk_idx_t slot2_idx;                           /* valstack slot for 2nd token value */
4041 	duk_idx_t buf_idx;                             /* valstack slot for temp buffer */
4042 	duk_hbuffer_dynamic *buf;                      /* temp accumulation buffer */
4043 	duk_bufwriter_ctx bw;                          /* bufwriter for temp accumulation */
4044 
4045 	duk_int_t token_count;                         /* number of tokens parsed */
4046 	duk_int_t token_limit;                         /* maximum token count before error (sanity backstop) */
4047 
4048 	duk_small_uint_t flags;                        /* lexer flags, use compiler flag defines for now */
4049 };
4050 
4051 /*
4052  *  Prototypes
4053  */
4054 
4055 DUK_INTERNAL_DECL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx);
4056 
4057 DUK_INTERNAL_DECL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);
4058 DUK_INTERNAL_DECL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);
4059 
4060 DUK_INTERNAL_DECL
4061 void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
4062                                       duk_token *out_token,
4063                                       duk_bool_t strict_mode,
4064                                       duk_bool_t regexp_mode);
4065 #if defined(DUK_USE_REGEXP_SUPPORT)
4066 DUK_INTERNAL_DECL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token);
4067 DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata);
4068 #endif  /* DUK_USE_REGEXP_SUPPORT */
4069 
4070 #endif  /* DUK_LEXER_H_INCLUDED */
4071 /* #include duk_js_compiler.h */
4072 /*
4073  *  ECMAScript compiler.
4074  */
4075 
4076 #if !defined(DUK_JS_COMPILER_H_INCLUDED)
4077 #define DUK_JS_COMPILER_H_INCLUDED
4078 
4079 /* ECMAScript compiler limits */
4080 #define DUK_COMPILER_TOKEN_LIMIT           100000000L  /* 1e8: protects against deeply nested inner functions */
4081 
4082 /* maximum loopcount for peephole optimization */
4083 #define DUK_COMPILER_PEEPHOLE_MAXITER      3
4084 
4085 /* maximum bytecode length in instructions */
4086 #define DUK_COMPILER_MAX_BYTECODE_LENGTH   (256L * 1024L * 1024L)  /* 1 GB */
4087 
4088 /*
4089  *  Compiler intermediate values
4090  *
4091  *  Intermediate values describe either plain values (e.g. strings or
4092  *  numbers) or binary operations which have not yet been coerced into
4093  *  either a left-hand-side or right-hand-side role (e.g. object property).
4094  */
4095 
4096 #define DUK_IVAL_NONE          0   /* no value */
4097 #define DUK_IVAL_PLAIN         1   /* register, constant, or value */
4098 #define DUK_IVAL_ARITH         2   /* binary arithmetic; DUK_OP_ADD, DUK_OP_EQ, other binary ops */
4099 #define DUK_IVAL_PROP          3   /* property access */
4100 #define DUK_IVAL_VAR           4   /* variable access */
4101 
4102 #define DUK_ISPEC_NONE         0   /* no value */
4103 #define DUK_ISPEC_VALUE        1   /* value resides in 'valstack_idx' */
4104 #define DUK_ISPEC_REGCONST     2   /* value resides in a register or constant */
4105 
4106 /* Bit mask which indicates that a regconst is a constant instead of a register.
4107  * Chosen so that when a regconst is cast to duk_int32_t, all consts are
4108  * negative values.
4109  */
4110 #define DUK_REGCONST_CONST_MARKER    DUK_INT32_MIN  /* = -0x80000000 */
4111 
4112 /* Type to represent a reg/const reference during compilation, with <0
4113  * indicating a constant.  Some call sites also use -1 to indicate 'none'.
4114  */
4115 typedef duk_int32_t duk_regconst_t;
4116 
4117 typedef struct {
4118 	duk_small_uint_t t;          /* DUK_ISPEC_XXX */
4119 	duk_regconst_t regconst;
4120 	duk_idx_t valstack_idx;      /* always set; points to a reserved valstack slot */
4121 } duk_ispec;
4122 
4123 typedef struct {
4124 	/*
4125 	 *  PLAIN: x1
4126 	 *  ARITH: x1 <op> x2
4127 	 *  PROP: x1.x2
4128 	 *  VAR: x1 (name)
4129 	 */
4130 
4131 	/* XXX: can be optimized for smaller footprint esp. on 32-bit environments */
4132 	duk_small_uint_t t;          /* DUK_IVAL_XXX */
4133 	duk_small_uint_t op;         /* bytecode opcode for binary ops */
4134 	duk_ispec x1;
4135 	duk_ispec x2;
4136 } duk_ivalue;
4137 
4138 /*
4139  *  Bytecode instruction representation during compilation
4140  *
4141  *  Contains the actual instruction and (optionally) debug info.
4142  */
4143 
4144 struct duk_compiler_instr {
4145 	duk_instr_t ins;
4146 #if defined(DUK_USE_PC2LINE)
4147 	duk_uint32_t line;
4148 #endif
4149 };
4150 
4151 /*
4152  *  Compiler state
4153  */
4154 
4155 #define DUK_LABEL_FLAG_ALLOW_BREAK       (1U << 0)
4156 #define DUK_LABEL_FLAG_ALLOW_CONTINUE    (1U << 1)
4157 
4158 #define DUK_DECL_TYPE_VAR                0
4159 #define DUK_DECL_TYPE_FUNC               1
4160 
4161 /* XXX: optimize to 16 bytes */
4162 typedef struct {
4163 	duk_small_uint_t flags;
4164 	duk_int_t label_id;          /* numeric label_id (-1 reserved as marker) */
4165 	duk_hstring *h_label;        /* borrowed label name */
4166 	duk_int_t catch_depth;       /* catch depth at point of definition */
4167 	duk_int_t pc_label;          /* pc of label statement:
4168 	                              * pc+1: break jump site
4169 	                              * pc+2: continue jump site
4170 	                              */
4171 
4172 	/* Fast jumps (which avoid longjmp) jump directly to the jump sites
4173 	 * which are always known even while the iteration/switch statement
4174 	 * is still being parsed.  A final peephole pass "straightens out"
4175 	 * the jumps.
4176 	 */
4177 } duk_labelinfo;
4178 
4179 /* Compiling state of one function, eventually converted to duk_hcompfunc */
4180 struct duk_compiler_func {
4181 	/* These pointers are at the start of the struct so that they pack
4182 	 * nicely.  Mixing pointers and integer values is bad on some
4183 	 * platforms (e.g. if int is 32 bits and pointers are 64 bits).
4184 	 */
4185 
4186 	duk_bufwriter_ctx bw_code;          /* bufwriter for code */
4187 
4188 	duk_hstring *h_name;                /* function name (borrowed reference), ends up in _name */
4189 	/* h_code: held in bw_code */
4190 	duk_hobject *h_consts;              /* array */
4191 	duk_hobject *h_funcs;               /* array of function templates: [func1, offset1, line1, func2, offset2, line2]
4192 	                                     * offset/line points to closing brace to allow skipping on pass 2
4193 	                                     */
4194 	duk_hobject *h_decls;               /* array of declarations: [ name1, val1, name2, val2, ... ]
4195 	                                     * valN = (typeN) | (fnum << 8), where fnum is inner func number (0 for vars)
4196 	                                     * record function and variable declarations in pass 1
4197 	                                     */
4198 	duk_hobject *h_labelnames;          /* array of active label names */
4199 	duk_hbuffer_dynamic *h_labelinfos;  /* C array of duk_labelinfo */
4200 	duk_hobject *h_argnames;            /* array of formal argument names (-> _Formals) */
4201 	duk_hobject *h_varmap;              /* variable map for pass 2 (identifier -> register number or null (unmapped)) */
4202 
4203 	/* Value stack indices for tracking objects. */
4204 	/* code_idx: not needed */
4205 	duk_idx_t consts_idx;
4206 	duk_idx_t funcs_idx;
4207 	duk_idx_t decls_idx;
4208 	duk_idx_t labelnames_idx;
4209 	duk_idx_t labelinfos_idx;
4210 	duk_idx_t argnames_idx;
4211 	duk_idx_t varmap_idx;
4212 
4213 	/* Temp reg handling. */
4214 	duk_regconst_t temp_first;           /* first register that is a temporary (below: variables) */
4215 	duk_regconst_t temp_next;            /* next temporary register to allocate */
4216 	duk_regconst_t temp_max;             /* highest value of temp_reg (temp_max - 1 is highest used reg) */
4217 
4218 	/* Shuffle registers if large number of regs/consts. */
4219 	duk_regconst_t shuffle1;
4220 	duk_regconst_t shuffle2;
4221 	duk_regconst_t shuffle3;
4222 
4223 	/* Stats for current expression being parsed. */
4224 	duk_int_t nud_count;
4225 	duk_int_t led_count;
4226 	duk_int_t paren_level;              /* parenthesis count, 0 = top level */
4227 	duk_bool_t expr_lhs;                /* expression is left-hand-side compatible */
4228 	duk_bool_t allow_in;                /* current paren level allows 'in' token */
4229 
4230 	/* Misc. */
4231 	duk_int_t stmt_next;                /* statement id allocation (running counter) */
4232 	duk_int_t label_next;               /* label id allocation (running counter) */
4233 	duk_int_t catch_depth;              /* catch stack depth */
4234 	duk_int_t with_depth;               /* with stack depth (affects identifier lookups) */
4235 	duk_int_t fnum_next;                /* inner function numbering */
4236 	duk_int_t num_formals;              /* number of formal arguments */
4237 	duk_regconst_t reg_stmt_value;      /* register for writing value of 'non-empty' statements (global or eval code), -1 is marker */
4238 #if defined(DUK_USE_DEBUGGER_SUPPORT)
4239 	duk_int_t min_line;                 /* XXX: typing (duk_hcompfunc has duk_uint32_t) */
4240 	duk_int_t max_line;
4241 #endif
4242 
4243 	/* Status booleans. */
4244 	duk_uint8_t is_function;             /* is an actual function (not global/eval code) */
4245 	duk_uint8_t is_eval;                 /* is eval code */
4246 	duk_uint8_t is_global;               /* is global code */
4247 	duk_uint8_t is_namebinding;          /* needs a name binding */
4248 	duk_uint8_t is_constructable;        /* result is constructable */
4249 	duk_uint8_t is_setget;               /* is a setter/getter */
4250 	duk_uint8_t is_strict;               /* function is strict */
4251 	duk_uint8_t is_notail;               /* function must not be tail called */
4252 	duk_uint8_t in_directive_prologue;   /* parsing in "directive prologue", recognize directives */
4253 	duk_uint8_t in_scanning;             /* parsing in "scanning" phase (first pass) */
4254 	duk_uint8_t may_direct_eval;         /* function may call direct eval */
4255 	duk_uint8_t id_access_arguments;     /* function refers to 'arguments' identifier */
4256 	duk_uint8_t id_access_slow;          /* function makes one or more slow path accesses that won't match own static variables */
4257 	duk_uint8_t id_access_slow_own;      /* function makes one or more slow path accesses that may match own static variables */
4258 	duk_uint8_t is_arguments_shadowed;   /* argument/function declaration shadows 'arguments' */
4259 	duk_uint8_t needs_shuffle;           /* function needs shuffle registers */
4260 	duk_uint8_t reject_regexp_in_adv;    /* reject RegExp literal on next advance() call; needed for handling IdentifierName productions */
4261 	duk_uint8_t allow_regexp_in_adv;     /* allow RegExp literal on next advance() call */
4262 };
4263 
4264 struct duk_compiler_ctx {
4265 	duk_hthread *thr;
4266 
4267 	/* filename being compiled (ends up in functions' '_filename' property) */
4268 	duk_hstring *h_filename;            /* borrowed reference */
4269 
4270 	/* lexing (tokenization) state (contains two valstack slot indices) */
4271 	duk_lexer_ctx lex;
4272 
4273 	/* current and previous token for parsing */
4274 	duk_token prev_token;
4275 	duk_token curr_token;
4276 	duk_idx_t tok11_idx;                /* curr_token slot1 (matches 'lex' slot1_idx) */
4277 	duk_idx_t tok12_idx;                /* curr_token slot2 (matches 'lex' slot2_idx) */
4278 	duk_idx_t tok21_idx;                /* prev_token slot1 */
4279 	duk_idx_t tok22_idx;                /* prev_token slot2 */
4280 
4281 	/* recursion limit */
4282 	duk_int_t recursion_depth;
4283 	duk_int_t recursion_limit;
4284 
4285 	/* code emission temporary */
4286 	duk_int_t emit_jumpslot_pc;
4287 
4288 	/* current function being compiled (embedded instead of pointer for more compact access) */
4289 	duk_compiler_func curr_func;
4290 };
4291 
4292 /*
4293  *  Prototypes
4294  */
4295 
4296 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);
4297 
4298 #endif  /* DUK_JS_COMPILER_H_INCLUDED */
4299 /* #include duk_regexp.h */
4300 /*
4301  *  Regular expression structs, constants, and bytecode defines.
4302  */
4303 
4304 #if !defined(DUK_REGEXP_H_INCLUDED)
4305 #define DUK_REGEXP_H_INCLUDED
4306 
4307 /* maximum bytecode copies for {n,m} quantifiers */
4308 #define DUK_RE_MAX_ATOM_COPIES             1000
4309 
4310 /* regexp compilation limits */
4311 #define DUK_RE_COMPILE_TOKEN_LIMIT         100000000L   /* 1e8 */
4312 
4313 /* regexp execution limits */
4314 #define DUK_RE_EXECUTE_STEPS_LIMIT         1000000000L  /* 1e9 */
4315 
4316 /* regexp opcodes */
4317 #define DUK_REOP_MATCH                     1
4318 #define DUK_REOP_CHAR                      2
4319 #define DUK_REOP_PERIOD                    3
4320 #define DUK_REOP_RANGES                    4
4321 #define DUK_REOP_INVRANGES                 5
4322 #define DUK_REOP_JUMP                      6
4323 #define DUK_REOP_SPLIT1                    7
4324 #define DUK_REOP_SPLIT2                    8
4325 #define DUK_REOP_SQMINIMAL                 9
4326 #define DUK_REOP_SQGREEDY                  10
4327 #define DUK_REOP_SAVE                      11
4328 #define DUK_REOP_WIPERANGE                 12
4329 #define DUK_REOP_LOOKPOS                   13
4330 #define DUK_REOP_LOOKNEG                   14
4331 #define DUK_REOP_BACKREFERENCE             15
4332 #define DUK_REOP_ASSERT_START              16
4333 #define DUK_REOP_ASSERT_END                17
4334 #define DUK_REOP_ASSERT_WORD_BOUNDARY      18
4335 #define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY  19
4336 
4337 /* flags */
4338 #define DUK_RE_FLAG_GLOBAL                 (1U << 0)
4339 #define DUK_RE_FLAG_IGNORE_CASE            (1U << 1)
4340 #define DUK_RE_FLAG_MULTILINE              (1U << 2)
4341 
4342 struct duk_re_matcher_ctx {
4343 	duk_hthread *thr;
4344 
4345 	duk_uint32_t re_flags;
4346 	const duk_uint8_t *input;
4347 	const duk_uint8_t *input_end;
4348 	const duk_uint8_t *bytecode;
4349 	const duk_uint8_t *bytecode_end;
4350 	const duk_uint8_t **saved;  /* allocated from valstack (fixed buffer) */
4351 	duk_uint32_t nsaved;
4352 	duk_uint32_t recursion_depth;
4353 	duk_uint32_t recursion_limit;
4354 	duk_uint32_t steps_count;
4355 	duk_uint32_t steps_limit;
4356 };
4357 
4358 struct duk_re_compiler_ctx {
4359 	duk_hthread *thr;
4360 
4361 	duk_uint32_t re_flags;
4362 	duk_lexer_ctx lex;
4363 	duk_re_token curr_token;
4364 	duk_bufwriter_ctx bw;
4365 	duk_uint32_t captures;  /* highest capture number emitted so far (used as: ++captures) */
4366 	duk_uint32_t highest_backref;
4367 	duk_uint32_t recursion_depth;
4368 	duk_uint32_t recursion_limit;
4369 	duk_uint32_t nranges;  /* internal temporary value, used for char classes */
4370 };
4371 
4372 /*
4373  *  Prototypes
4374  */
4375 
4376 #if defined(DUK_USE_REGEXP_SUPPORT)
4377 DUK_INTERNAL_DECL void duk_regexp_compile(duk_hthread *thr);
4378 DUK_INTERNAL_DECL void duk_regexp_create_instance(duk_hthread *thr);
4379 DUK_INTERNAL_DECL void duk_regexp_match(duk_hthread *thr);
4380 DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr);  /* hacky helper for String.prototype.split() */
4381 #endif
4382 
4383 #endif  /* DUK_REGEXP_H_INCLUDED */
4384 /* #include duk_heaphdr.h */
4385 /*
4386  *  Heap header definition and assorted macros, including ref counting.
4387  *  Access all fields through the accessor macros.
4388  */
4389 
4390 #if !defined(DUK_HEAPHDR_H_INCLUDED)
4391 #define DUK_HEAPHDR_H_INCLUDED
4392 
4393 /*
4394  *  Common heap header
4395  *
4396  *  All heap objects share the same flags and refcount fields.  Objects other
4397  *  than strings also need to have a single or double linked list pointers
4398  *  for insertion into the "heap allocated" list.  Strings have single linked
4399  *  list pointers for string table chaining.
4400  *
4401  *  Technically, 'h_refcount' must be wide enough to guarantee that it cannot
4402  *  wrap; otherwise objects might be freed incorrectly after wrapping.  The
4403  *  default refcount field is 32 bits even on 64-bit systems: while that's in
4404  *  theory incorrect, the Duktape heap needs to be larger than 64GB for the
4405  *  count to actually wrap (assuming 16-byte duk_tvals).  This is very unlikely
4406  *  to ever be an issue, but if it is, disabling DUK_USE_REFCOUNT32 causes
4407  *  Duktape to use size_t for refcounts which should always be safe.
4408  *
4409  *  Heap header size on 32-bit platforms: 8 bytes without reference counting,
4410  *  16 bytes with reference counting.
4411  *
4412  *  Note that 'raw' macros such as DUK_HEAPHDR_GET_REFCOUNT() are not
4413  *  defined without DUK_USE_REFERENCE_COUNTING, so caller must #if defined()
4414  *  around them.
4415  */
4416 
4417 /* XXX: macro for shared header fields (avoids some padding issues) */
4418 
4419 struct duk_heaphdr {
4420 	duk_uint32_t h_flags;
4421 
4422 #if defined(DUK_USE_REFERENCE_COUNTING)
4423 #if defined(DUK_USE_ASSERTIONS)
4424 	/* When assertions enabled, used by mark-and-sweep for refcount
4425 	 * validation.  Largest reasonable type; also detects overflows.
4426 	 */
4427 	duk_size_t h_assert_refcount;
4428 #endif
4429 #if defined(DUK_USE_REFCOUNT16)
4430 	duk_uint16_t h_refcount;
4431 #elif defined(DUK_USE_REFCOUNT32)
4432 	duk_uint32_t h_refcount;
4433 #else
4434 	duk_size_t h_refcount;
4435 #endif
4436 #endif  /* DUK_USE_REFERENCE_COUNTING */
4437 
4438 #if defined(DUK_USE_HEAPPTR16)
4439 	duk_uint16_t h_next16;
4440 #else
4441 	duk_heaphdr *h_next;
4442 #endif
4443 
4444 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
4445 	/* refcounting requires direct heap frees, which in turn requires a dual linked heap */
4446 #if defined(DUK_USE_HEAPPTR16)
4447 	duk_uint16_t h_prev16;
4448 #else
4449 	duk_heaphdr *h_prev;
4450 #endif
4451 #endif
4452 
4453 	/* When DUK_USE_HEAPPTR16 (and DUK_USE_REFCOUNT16) is in use, the
4454 	 * struct won't align nicely to 4 bytes.  This 16-bit extra field
4455 	 * is added to make the alignment clean; the field can be used by
4456 	 * heap objects when 16-bit packing is used.  This field is now
4457 	 * conditional to DUK_USE_HEAPPTR16 only, but it is intended to be
4458 	 * used with DUK_USE_REFCOUNT16 and DUK_USE_DOUBLE_LINKED_HEAP;
4459 	 * this only matter to low memory environments anyway.
4460 	 */
4461 #if defined(DUK_USE_HEAPPTR16)
4462 	duk_uint16_t h_extra16;
4463 #endif
4464 };
4465 
4466 struct duk_heaphdr_string {
4467 	/* 16 bits would be enough for shared heaphdr flags and duk_hstring
4468 	 * flags.  The initial parts of duk_heaphdr_string and duk_heaphdr
4469 	 * must match so changing the flags field size here would be quite
4470 	 * awkward.  However, to minimize struct size, we can pack at least
4471 	 * 16 bits of duk_hstring data into the flags field.
4472 	 */
4473 	duk_uint32_t h_flags;
4474 
4475 #if defined(DUK_USE_REFERENCE_COUNTING)
4476 #if defined(DUK_USE_ASSERTIONS)
4477 	/* When assertions enabled, used by mark-and-sweep for refcount
4478 	 * validation.  Largest reasonable type; also detects overflows.
4479 	 */
4480 	duk_size_t h_assert_refcount;
4481 #endif
4482 #if defined(DUK_USE_REFCOUNT16)
4483 	duk_uint16_t h_refcount;
4484 	duk_uint16_t h_strextra16;  /* round out to 8 bytes */
4485 #elif defined(DUK_USE_REFCOUNT32)
4486 	duk_uint32_t h_refcount;
4487 #else
4488 	duk_size_t h_refcount;
4489 #endif
4490 #else
4491 	duk_uint16_t h_strextra16;
4492 #endif  /* DUK_USE_REFERENCE_COUNTING */
4493 
4494 	duk_hstring *h_next;
4495 	/* No 'h_prev' pointer for strings. */
4496 };
4497 
4498 #define DUK_HEAPHDR_FLAGS_TYPE_MASK      0x00000003UL
4499 #define DUK_HEAPHDR_FLAGS_FLAG_MASK      (~DUK_HEAPHDR_FLAGS_TYPE_MASK)
4500 
4501                                              /* 2 bits for heap type */
4502 #define DUK_HEAPHDR_FLAGS_HEAP_START     2   /* 5 heap flags */
4503 #define DUK_HEAPHDR_FLAGS_USER_START     7   /* 25 user flags */
4504 
4505 #define DUK_HEAPHDR_HEAP_FLAG_NUMBER(n)  (DUK_HEAPHDR_FLAGS_HEAP_START + (n))
4506 #define DUK_HEAPHDR_USER_FLAG_NUMBER(n)  (DUK_HEAPHDR_FLAGS_USER_START + (n))
4507 #define DUK_HEAPHDR_HEAP_FLAG(n)         (1UL << (DUK_HEAPHDR_FLAGS_HEAP_START + (n)))
4508 #define DUK_HEAPHDR_USER_FLAG(n)         (1UL << (DUK_HEAPHDR_FLAGS_USER_START + (n)))
4509 
4510 #define DUK_HEAPHDR_FLAG_REACHABLE       DUK_HEAPHDR_HEAP_FLAG(0)  /* mark-and-sweep: reachable */
4511 #define DUK_HEAPHDR_FLAG_TEMPROOT        DUK_HEAPHDR_HEAP_FLAG(1)  /* mark-and-sweep: children not processed */
4512 #define DUK_HEAPHDR_FLAG_FINALIZABLE     DUK_HEAPHDR_HEAP_FLAG(2)  /* mark-and-sweep: finalizable (on current pass) */
4513 #define DUK_HEAPHDR_FLAG_FINALIZED       DUK_HEAPHDR_HEAP_FLAG(3)  /* mark-and-sweep: finalized (on previous pass) */
4514 #define DUK_HEAPHDR_FLAG_READONLY        DUK_HEAPHDR_HEAP_FLAG(4)  /* read-only object, in code section */
4515 
4516 #define DUK_HTYPE_MIN                    0
4517 #define DUK_HTYPE_STRING                 0
4518 #define DUK_HTYPE_OBJECT                 1
4519 #define DUK_HTYPE_BUFFER                 2
4520 #define DUK_HTYPE_MAX                    2
4521 
4522 #if defined(DUK_USE_HEAPPTR16)
4523 #define DUK_HEAPHDR_GET_NEXT(heap,h) \
4524 	((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_next16))
4525 #define DUK_HEAPHDR_SET_NEXT(heap,h,val)   do { \
4526 		(h)->h_next16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) val); \
4527 	} while (0)
4528 #else
4529 #define DUK_HEAPHDR_GET_NEXT(heap,h)  ((h)->h_next)
4530 #define DUK_HEAPHDR_SET_NEXT(heap,h,val)   do { \
4531 		(h)->h_next = (val); \
4532 	} while (0)
4533 #endif
4534 
4535 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
4536 #if defined(DUK_USE_HEAPPTR16)
4537 #define DUK_HEAPHDR_GET_PREV(heap,h) \
4538 	((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_prev16))
4539 #define DUK_HEAPHDR_SET_PREV(heap,h,val)   do { \
4540 		(h)->h_prev16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (val)); \
4541 	} while (0)
4542 #else
4543 #define DUK_HEAPHDR_GET_PREV(heap,h)       ((h)->h_prev)
4544 #define DUK_HEAPHDR_SET_PREV(heap,h,val)   do { \
4545 		(h)->h_prev = (val); \
4546 	} while (0)
4547 #endif
4548 #endif
4549 
4550 #if defined(DUK_USE_REFERENCE_COUNTING)
4551 #define DUK_HEAPHDR_GET_REFCOUNT(h)   ((h)->h_refcount)
4552 #define DUK_HEAPHDR_SET_REFCOUNT(h,val)  do { \
4553 		(h)->h_refcount = (val); \
4554 		DUK_ASSERT((h)->h_refcount == (val));  /* No truncation. */ \
4555 	} while (0)
4556 #define DUK_HEAPHDR_PREINC_REFCOUNT(h)  (++(h)->h_refcount)  /* result: updated refcount */
4557 #define DUK_HEAPHDR_PREDEC_REFCOUNT(h)  (--(h)->h_refcount)  /* result: updated refcount */
4558 #else
4559 /* refcount macros not defined without refcounting, caller must #if defined() now */
4560 #endif  /* DUK_USE_REFERENCE_COUNTING */
4561 
4562 /*
4563  *  Note: type is treated as a field separate from flags, so some masking is
4564  *  involved in the macros below.
4565  */
4566 
4567 #define DUK_HEAPHDR_GET_FLAGS_RAW(h)  ((h)->h_flags)
4568 #define DUK_HEAPHDR_SET_FLAGS_RAW(h,val)  do { \
4569 		(h)->h_flags = (val); } \
4570 	}
4571 #define DUK_HEAPHDR_GET_FLAGS(h)      ((h)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK)
4572 #define DUK_HEAPHDR_SET_FLAGS(h,val)  do { \
4573 		(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) | (val); \
4574 	} while (0)
4575 #define DUK_HEAPHDR_GET_TYPE(h)       ((h)->h_flags & DUK_HEAPHDR_FLAGS_TYPE_MASK)
4576 #define DUK_HEAPHDR_SET_TYPE(h,val)   do { \
4577 		(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_TYPE_MASK)) | (val); \
4578 	} while (0)
4579 
4580 /* Comparison for type >= DUK_HTYPE_MIN skipped; because DUK_HTYPE_MIN is zero
4581  * and the comparison is unsigned, it's always true and generates warnings.
4582  */
4583 #define DUK_HEAPHDR_HTYPE_VALID(h)    ( \
4584 	DUK_HEAPHDR_GET_TYPE((h)) <= DUK_HTYPE_MAX \
4585 	)
4586 
4587 #define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h,tval,fval)  do { \
4588 		(h)->h_flags = ((tval) & DUK_HEAPHDR_FLAGS_TYPE_MASK) | \
4589 		               ((fval) & DUK_HEAPHDR_FLAGS_FLAG_MASK); \
4590 	} while (0)
4591 
4592 #define DUK_HEAPHDR_SET_FLAG_BITS(h,bits)  do { \
4593 		DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
4594 		(h)->h_flags |= (bits); \
4595 	} while (0)
4596 
4597 #define DUK_HEAPHDR_CLEAR_FLAG_BITS(h,bits)  do { \
4598 		DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
4599 		(h)->h_flags &= ~((bits)); \
4600 	} while (0)
4601 
4602 #define DUK_HEAPHDR_CHECK_FLAG_BITS(h,bits)  (((h)->h_flags & (bits)) != 0)
4603 
4604 #define DUK_HEAPHDR_SET_REACHABLE(h)      DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
4605 #define DUK_HEAPHDR_CLEAR_REACHABLE(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
4606 #define DUK_HEAPHDR_HAS_REACHABLE(h)      DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
4607 
4608 #define DUK_HEAPHDR_SET_TEMPROOT(h)       DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
4609 #define DUK_HEAPHDR_CLEAR_TEMPROOT(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
4610 #define DUK_HEAPHDR_HAS_TEMPROOT(h)       DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
4611 
4612 #define DUK_HEAPHDR_SET_FINALIZABLE(h)    DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
4613 #define DUK_HEAPHDR_CLEAR_FINALIZABLE(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
4614 #define DUK_HEAPHDR_HAS_FINALIZABLE(h)    DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
4615 
4616 #define DUK_HEAPHDR_SET_FINALIZED(h)      DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
4617 #define DUK_HEAPHDR_CLEAR_FINALIZED(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
4618 #define DUK_HEAPHDR_HAS_FINALIZED(h)      DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
4619 
4620 #define DUK_HEAPHDR_SET_READONLY(h)       DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
4621 #define DUK_HEAPHDR_CLEAR_READONLY(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
4622 #define DUK_HEAPHDR_HAS_READONLY(h)       DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
4623 
4624 /* get or set a range of flags; m=first bit number, n=number of bits */
4625 #define DUK_HEAPHDR_GET_FLAG_RANGE(h,m,n)  (((h)->h_flags >> (m)) & ((1UL << (n)) - 1UL))
4626 
4627 #define DUK_HEAPHDR_SET_FLAG_RANGE(h,m,n,v)  do { \
4628 		(h)->h_flags = \
4629 			((h)->h_flags & (~(((1UL << (n)) - 1UL) << (m)))) \
4630 			| ((v) << (m)); \
4631 	} while (0)
4632 
4633 /* init pointer fields to null */
4634 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
4635 #define DUK_HEAPHDR_INIT_NULLS(h)       do { \
4636 		DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
4637 		DUK_HEAPHDR_SET_PREV((h), (void *) NULL); \
4638 	} while (0)
4639 #else
4640 #define DUK_HEAPHDR_INIT_NULLS(h)       do { \
4641 		DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
4642 	} while (0)
4643 #endif
4644 
4645 #define DUK_HEAPHDR_STRING_INIT_NULLS(h)  do { \
4646 		(h)->h_next = NULL; \
4647 	} while (0)
4648 
4649 /*
4650  *  Type tests
4651  */
4652 
4653 /* Take advantage of the fact that for DUK_HTYPE_xxx numbers the lowest bit
4654  * is only set for DUK_HTYPE_OBJECT (= 1).
4655  */
4656 #if 0
4657 #define DUK_HEAPHDR_IS_OBJECT(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_OBJECT)
4658 #endif
4659 #define DUK_HEAPHDR_IS_OBJECT(h) ((h)->h_flags & 0x01UL)
4660 #define DUK_HEAPHDR_IS_STRING(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_STRING)
4661 #define DUK_HEAPHDR_IS_BUFFER(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_BUFFER)
4662 
4663 /*
4664  *  Assert helpers
4665  */
4666 
4667 /* Check that prev/next links are consistent: if e.g. h->prev is != NULL,
4668  * h->prev->next should point back to h.
4669  */
4670 #if defined(DUK_USE_ASSERTIONS)
4671 DUK_INTERNAL_DECL void duk_heaphdr_assert_valid_subclassed(duk_heaphdr *h);
4672 DUK_INTERNAL_DECL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h);
4673 DUK_INTERNAL_DECL void duk_heaphdr_assert_valid(duk_heaphdr *h);
4674 #define DUK_HEAPHDR_ASSERT_LINKS(heap,h)  do { duk_heaphdr_assert_links((heap), (h)); } while (0)
4675 #define DUK_HEAPHDR_ASSERT_VALID(h)  do { duk_heaphdr_assert_valid((h)); } while (0)
4676 #else
4677 #define DUK_HEAPHDR_ASSERT_LINKS(heap,h)  do {} while (0)
4678 #define DUK_HEAPHDR_ASSERT_VALID(h)  do {} while (0)
4679 #endif
4680 
4681 #endif  /* DUK_HEAPHDR_H_INCLUDED */
4682 /* #include duk_refcount.h */
4683 /*
4684  *  Reference counting helper macros.  The macros take a thread argument
4685  *  and must thus always be executed in a specific thread context.  The
4686  *  thread argument is not really needed anymore: DECREF can operate with
4687  *  a heap pointer only, and INCREF needs neither.
4688  */
4689 
4690 #if !defined(DUK_REFCOUNT_H_INCLUDED)
4691 #define DUK_REFCOUNT_H_INCLUDED
4692 
4693 #if defined(DUK_USE_REFERENCE_COUNTING)
4694 
4695 #if defined(DUK_USE_ROM_OBJECTS)
4696 /* With ROM objects "needs refcount update" is true when the value is
4697  * heap allocated and is not a ROM object.
4698  */
4699 /* XXX: double evaluation for 'tv' argument. */
4700 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) \
4701 	(DUK_TVAL_IS_HEAP_ALLOCATED((tv)) && !DUK_HEAPHDR_HAS_READONLY(DUK_TVAL_GET_HEAPHDR((tv))))
4702 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)  (!DUK_HEAPHDR_HAS_READONLY((h)))
4703 #else  /* DUK_USE_ROM_OBJECTS */
4704 /* Without ROM objects "needs refcount update" == is heap allocated. */
4705 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)    DUK_TVAL_IS_HEAP_ALLOCATED((tv))
4706 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)  1
4707 #endif  /* DUK_USE_ROM_OBJECTS */
4708 
4709 /* Fast variants, inline refcount operations except for refzero handling.
4710  * Can be used explicitly when speed is always more important than size.
4711  * For a good compiler and a single file build, these are basically the
4712  * same as a forced inline.
4713  */
4714 #define DUK_TVAL_INCREF_FAST(thr,tv) do { \
4715 		duk_tval *duk__tv = (tv); \
4716 		DUK_ASSERT(duk__tv != NULL); \
4717 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4718 			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4719 			DUK_ASSERT(duk__h != NULL); \
4720 			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4721 			DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
4722 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0);  /* No wrapping. */ \
4723 		} \
4724 	} while (0)
4725 #define DUK_TVAL_DECREF_FAST(thr,tv) do { \
4726 		duk_tval *duk__tv = (tv); \
4727 		DUK_ASSERT(duk__tv != NULL); \
4728 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4729 			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4730 			DUK_ASSERT(duk__h != NULL); \
4731 			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4732 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4733 			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4734 				duk_heaphdr_refzero((thr), duk__h); \
4735 			} \
4736 		} \
4737 	} while (0)
4738 #define DUK_TVAL_DECREF_NORZ_FAST(thr,tv) do { \
4739 		duk_tval *duk__tv = (tv); \
4740 		DUK_ASSERT(duk__tv != NULL); \
4741 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4742 			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4743 			DUK_ASSERT(duk__h != NULL); \
4744 			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4745 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4746 			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4747 				duk_heaphdr_refzero_norz((thr), duk__h); \
4748 			} \
4749 		} \
4750 	} while (0)
4751 #define DUK_HEAPHDR_INCREF_FAST(thr,h) do { \
4752 		duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
4753 		DUK_ASSERT(duk__h != NULL); \
4754 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4755 		if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
4756 			DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
4757 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0);  /* No wrapping. */ \
4758 		} \
4759 	} while (0)
4760 #define DUK_HEAPHDR_DECREF_FAST_RAW(thr,h,rzcall,rzcast) do { \
4761 		duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
4762 		DUK_ASSERT(duk__h != NULL); \
4763 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4764 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4765 		if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
4766 			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4767 				(rzcall)((thr), (rzcast) duk__h); \
4768 			} \
4769 		} \
4770 	} while (0)
4771 #define DUK_HEAPHDR_DECREF_FAST(thr,h) \
4772 	DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *)
4773 #define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h) \
4774 	DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *)
4775 
4776 /* Slow variants, call to a helper to reduce code size.
4777  * Can be used explicitly when size is always more important than speed.
4778  */
4779 #define DUK_TVAL_INCREF_SLOW(thr,tv)         do { duk_tval_incref((tv)); } while (0)
4780 #define DUK_TVAL_DECREF_SLOW(thr,tv)         do { duk_tval_decref((thr), (tv)); } while (0)
4781 #define DUK_TVAL_DECREF_NORZ_SLOW(thr,tv)    do { duk_tval_decref_norz((thr), (tv)); } while (0)
4782 #define DUK_HEAPHDR_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4783 #define DUK_HEAPHDR_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4784 #define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4785 #define DUK_HSTRING_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4786 #define DUK_HSTRING_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4787 #define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4788 #define DUK_HBUFFER_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4789 #define DUK_HBUFFER_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4790 #define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4791 #define DUK_HOBJECT_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4792 #define DUK_HOBJECT_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4793 #define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4794 
4795 /* Default variants.  Selection depends on speed/size preference.
4796  * Concretely: with gcc 4.8.1 -Os x64 the difference in final binary
4797  * is about +1kB for _FAST variants.
4798  */
4799 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
4800 /* XXX: It would be nice to specialize for specific duk_hobject subtypes
4801  * but current refzero queue handling prevents that.
4802  */
4803 #define DUK_TVAL_INCREF(thr,tv)                DUK_TVAL_INCREF_FAST((thr),(tv))
4804 #define DUK_TVAL_DECREF(thr,tv)                DUK_TVAL_DECREF_FAST((thr),(tv))
4805 #define DUK_TVAL_DECREF_NORZ(thr,tv)           DUK_TVAL_DECREF_NORZ_FAST((thr),(tv))
4806 #define DUK_HEAPHDR_INCREF(thr,h)              DUK_HEAPHDR_INCREF_FAST((thr),(h))
4807 #define DUK_HEAPHDR_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *)
4808 #define DUK_HEAPHDR_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *)
4809 #define DUK_HSTRING_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4810 #define DUK_HSTRING_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *)
4811 #define DUK_HSTRING_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *)  /* no 'norz' variant */
4812 #define DUK_HOBJECT_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4813 #define DUK_HOBJECT_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4814 #define DUK_HOBJECT_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4815 #define DUK_HBUFFER_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4816 #define DUK_HBUFFER_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *)
4817 #define DUK_HBUFFER_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *)  /* no 'norz' variant */
4818 #define DUK_HCOMPFUNC_INCREF(thr,h)            DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4819 #define DUK_HCOMPFUNC_DECREF(thr,h)            DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4820 #define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4821 #define DUK_HNATFUNC_INCREF(thr,h)             DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4822 #define DUK_HNATFUNC_DECREF(thr,h)             DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4823 #define DUK_HNATFUNC_DECREF_NORZ(thr,h)        DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4824 #define DUK_HBUFOBJ_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4825 #define DUK_HBUFOBJ_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4826 #define DUK_HBUFOBJ_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4827 #define DUK_HTHREAD_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4828 #define DUK_HTHREAD_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4829 #define DUK_HTHREAD_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4830 #else
4831 #define DUK_TVAL_INCREF(thr,tv)                DUK_TVAL_INCREF_SLOW((thr),(tv))
4832 #define DUK_TVAL_DECREF(thr,tv)                DUK_TVAL_DECREF_SLOW((thr),(tv))
4833 #define DUK_TVAL_DECREF_NORZ(thr,tv)           DUK_TVAL_DECREF_NORZ_SLOW((thr),(tv))
4834 #define DUK_HEAPHDR_INCREF(thr,h)              DUK_HEAPHDR_INCREF_SLOW((thr),(h))
4835 #define DUK_HEAPHDR_DECREF(thr,h)              DUK_HEAPHDR_DECREF_SLOW((thr),(h))
4836 #define DUK_HEAPHDR_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_NORZ_SLOW((thr),(h))
4837 #define DUK_HSTRING_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4838 #define DUK_HSTRING_DECREF(thr,h)              DUK_HSTRING_DECREF_SLOW((thr),(h))
4839 #define DUK_HSTRING_DECREF_NORZ(thr,h)         DUK_HSTRING_DECREF_NORZ_SLOW((thr),(h))
4840 #define DUK_HOBJECT_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4841 #define DUK_HOBJECT_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(h))
4842 #define DUK_HOBJECT_DECREF_NORZ(thr,h)         DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(h))
4843 #define DUK_HBUFFER_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4844 #define DUK_HBUFFER_DECREF(thr,h)              DUK_HBUFFER_DECREF_SLOW((thr),(h))
4845 #define DUK_HBUFFER_DECREF_NORZ(thr,h)         DUK_HBUFFER_DECREF_NORZ_SLOW((thr),(h))
4846 #define DUK_HCOMPFUNC_INCREF(thr,h)            DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4847 #define DUK_HCOMPFUNC_DECREF(thr,h)            DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4848 #define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4849 #define DUK_HNATFUNC_INCREF(thr,h)             DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4850 #define DUK_HNATFUNC_DECREF(thr,h)             DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4851 #define DUK_HNATFUNC_DECREF_NORZ(thr,h)        DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4852 #define DUK_HBUFOBJ_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4853 #define DUK_HBUFOBJ_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4854 #define DUK_HBUFOB_DECREF_NORZ(thr,h)          DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4855 #define DUK_HTHREAD_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4856 #define DUK_HTHREAD_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4857 #define DUK_HTHREAD_DECREF_NORZ(thr,h)         DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4858 #endif
4859 
4860 /* Convenience for some situations; the above macros don't allow NULLs
4861  * for performance reasons.  Macros cover only actually needed cases.
4862  */
4863 #define DUK_HEAPHDR_INCREF_ALLOWNULL(thr,h) do { \
4864 		if ((h) != NULL) { \
4865 			DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h)); \
4866 		} \
4867 	} while (0)
4868 #define DUK_HEAPHDR_DECREF_ALLOWNULL(thr,h) do { \
4869 		if ((h) != NULL) { \
4870 			DUK_HEAPHDR_DECREF((thr), (duk_heaphdr *) (h)); \
4871 		} \
4872 	} while (0)
4873 #define DUK_HEAPHDR_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4874 		if ((h) != NULL) { \
4875 			DUK_HEAPHDR_DECREF_NORZ((thr), (duk_heaphdr *) (h)); \
4876 		} \
4877 	} while (0)
4878 #define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do { \
4879 		if ((h) != NULL) { \
4880 			DUK_HOBJECT_INCREF((thr), (h)); \
4881 		} \
4882 	} while (0)
4883 #define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do { \
4884 		if ((h) != NULL) { \
4885 			DUK_HOBJECT_DECREF((thr), (h)); \
4886 		} \
4887 	} while (0)
4888 #define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4889 		if ((h) != NULL) { \
4890 			DUK_HOBJECT_DECREF_NORZ((thr), (h)); \
4891 		} \
4892 	} while (0)
4893 #define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h) do { \
4894 		if ((h) != NULL) { \
4895 			DUK_HBUFFER_INCREF((thr), (h)); \
4896 		} \
4897 	} while (0)
4898 #define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h) do { \
4899 		if ((h) != NULL) { \
4900 			DUK_HBUFFER_DECREF((thr), (h)); \
4901 		} \
4902 	} while (0)
4903 #define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4904 		if ((h) != NULL) { \
4905 			DUK_HBUFFER_DECREF_NORZ((thr), (h)); \
4906 		} \
4907 	} while (0)
4908 #define DUK_HTHREAD_INCREF_ALLOWNULL(thr,h) do { \
4909 		if ((h) != NULL) { \
4910 			DUK_HTHREAD_INCREF((thr), (h)); \
4911 		} \
4912 	} while (0)
4913 #define DUK_HTHREAD_DECREF_ALLOWNULL(thr,h) do { \
4914 		if ((h) != NULL) { \
4915 			DUK_HTHREAD_DECREF((thr), (h)); \
4916 		} \
4917 	} while (0)
4918 #define DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4919 		if ((h) != NULL) { \
4920 			DUK_HTHREAD_DECREF_NORZ((thr), (h)); \
4921 		} \
4922 	} while (0)
4923 
4924 /* Called after one or more DECREF NORZ calls to handle pending side effects.
4925  * At present DECREF NORZ does freeing inline but doesn't execute finalizers,
4926  * so these macros check for pending finalizers and execute them.  The FAST
4927  * variant is performance critical.
4928  */
4929 #if defined(DUK_USE_FINALIZER_SUPPORT)
4930 #define DUK_REFZERO_CHECK_FAST(thr) do { \
4931 		duk_refzero_check_fast((thr)); \
4932 	} while (0)
4933 #define DUK_REFZERO_CHECK_SLOW(thr) do { \
4934 		duk_refzero_check_slow((thr)); \
4935 	} while (0)
4936 #else  /* DUK_USE_FINALIZER_SUPPORT */
4937 #define DUK_REFZERO_CHECK_FAST(thr) do { } while (0)
4938 #define DUK_REFZERO_CHECK_SLOW(thr) do { } while (0)
4939 #endif  /* DUK_USE_FINALIZER_SUPPORT */
4940 
4941 /*
4942  *  Macros to set a duk_tval and update refcount of the target (decref the
4943  *  old value and incref the new value if necessary).  This is both performance
4944  *  and footprint critical; any changes made should be measured for size/speed.
4945  */
4946 
4947 #define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
4948 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4949 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4950 		DUK_TVAL_SET_UNDEFINED(tv__dst); \
4951 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
4952 	} while (0)
4953 
4954 #define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0(thr,tvptr_dst) do { \
4955 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4956 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4957 		DUK_TVAL_SET_UNDEFINED(tv__dst); \
4958 		DUK_TVAL_DECREF_NORZ((thr), &tv__tmp); \
4959 	} while (0)
4960 
4961 #define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
4962 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4963 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4964 		DUK_TVAL_SET_UNUSED(tv__dst); \
4965 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
4966 	} while (0)
4967 
4968 #define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
4969 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4970 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4971 		DUK_TVAL_SET_NULL(tv__dst); \
4972 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
4973 	} while (0)
4974 
4975 #define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4976 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4977 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4978 		DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
4979 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
4980 	} while (0)
4981 
4982 #define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4983 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4984 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4985 		DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
4986 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
4987 	} while (0)
4988 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4989 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4990 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4991 		DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
4992 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
4993 	} while (0)
4994 #define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4995 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4996 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4997 		DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
4998 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
4999 	} while (0)
5000 #define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
5001 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5002 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5003 		DUK_TVAL_SET_NAN(tv__dst); \
5004 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5005 	} while (0)
5006 #if defined(DUK_USE_FASTINT)
5007 #define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5008 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5009 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5010 		DUK_TVAL_SET_I48(tv__dst, (newval)); \
5011 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5012 	} while (0)
5013 #define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5014 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5015 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5016 		DUK_TVAL_SET_I32(tv__dst, (newval)); \
5017 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5018 	} while (0)
5019 #define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) 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_U32(tv__dst, (newval)); \
5023 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5024 	} while (0)
5025 #else
5026 #define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
5027 	DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
5028 #endif  /* DUK_USE_FASTINT */
5029 
5030 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
5031 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5032 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5033 		DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
5034 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5035 	} while (0)
5036 
5037 #define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5038 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5039 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5040 		DUK_TVAL_SET_STRING(tv__dst, (newval)); \
5041 		DUK_HSTRING_INCREF((thr), (newval)); \
5042 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5043 	} while (0)
5044 
5045 #define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5046 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5047 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5048 		DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
5049 		DUK_HOBJECT_INCREF((thr), (newval)); \
5050 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5051 	} while (0)
5052 
5053 #define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5054 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5055 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5056 		DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
5057 		DUK_HBUFFER_INCREF((thr), (newval)); \
5058 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5059 	} while (0)
5060 
5061 #define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5062 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5063 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5064 		DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
5065 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5066 	} while (0)
5067 
5068 /* DUK_TVAL_SET_TVAL_UPDREF() is used a lot in executor, property lookups,
5069  * etc, so it's very important for performance.  Measure when changing.
5070  *
5071  * NOTE: the source and destination duk_tval pointers may be the same, and
5072  * the macros MUST deal with that correctly.
5073  */
5074 
5075 /* Original idiom used, minimal code size. */
5076 #define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
5077 		duk_tval *tv__dst, *tv__src; duk_tval tv__tmp; \
5078 		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
5079 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5080 		DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5081 		DUK_TVAL_INCREF((thr), tv__src); \
5082 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5083 	} while (0)
5084 
5085 /* Faster alternative: avoid making a temporary copy of tvptr_dst and use
5086  * fast incref/decref macros.
5087  */
5088 #define DUK_TVAL_SET_TVAL_UPDREF_ALT1(thr,tvptr_dst,tvptr_src) do { \
5089 		duk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \
5090 		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
5091 		DUK_TVAL_INCREF_FAST((thr), tv__src); \
5092 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv__dst)) { \
5093 			h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \
5094 			DUK_ASSERT(h__obj != NULL); \
5095 			DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5096 			DUK_HEAPHDR_DECREF_FAST((thr), h__obj);  /* side effects */ \
5097 		} else { \
5098 			DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5099 		} \
5100 	} while (0)
5101 
5102 /* XXX: no optimized variants yet */
5103 #define DUK_TVAL_SET_UNDEFINED_UPDREF         DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
5104 #define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ    DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0
5105 #define DUK_TVAL_SET_UNUSED_UPDREF            DUK_TVAL_SET_UNUSED_UPDREF_ALT0
5106 #define DUK_TVAL_SET_NULL_UPDREF              DUK_TVAL_SET_NULL_UPDREF_ALT0
5107 #define DUK_TVAL_SET_BOOLEAN_UPDREF           DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
5108 #define DUK_TVAL_SET_NUMBER_UPDREF            DUK_TVAL_SET_NUMBER_UPDREF_ALT0
5109 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF    DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
5110 #define DUK_TVAL_SET_DOUBLE_UPDREF            DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
5111 #define DUK_TVAL_SET_NAN_UPDREF               DUK_TVAL_SET_NAN_UPDREF_ALT0
5112 #if defined(DUK_USE_FASTINT)
5113 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_I48_UPDREF_ALT0
5114 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_I32_UPDREF_ALT0
5115 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_U32_UPDREF_ALT0
5116 #else
5117 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF  /* XXX: fast int-to-double */
5118 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5119 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5120 #endif  /* DUK_USE_FASTINT */
5121 #define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_I48_UPDREF  /* convenience */
5122 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF         DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
5123 #define DUK_TVAL_SET_STRING_UPDREF            DUK_TVAL_SET_STRING_UPDREF_ALT0
5124 #define DUK_TVAL_SET_OBJECT_UPDREF            DUK_TVAL_SET_OBJECT_UPDREF_ALT0
5125 #define DUK_TVAL_SET_BUFFER_UPDREF            DUK_TVAL_SET_BUFFER_UPDREF_ALT0
5126 #define DUK_TVAL_SET_POINTER_UPDREF           DUK_TVAL_SET_POINTER_UPDREF_ALT0
5127 
5128 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
5129 /* Optimized for speed. */
5130 #define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT1
5131 #define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT1
5132 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5133 #else
5134 /* Optimized for size. */
5135 #define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT0
5136 #define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5137 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5138 #endif
5139 
5140 #else  /* DUK_USE_REFERENCE_COUNTING */
5141 
5142 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)     0
5143 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)   0
5144 
5145 #define DUK_TVAL_INCREF_FAST(thr,v)            do {} while (0) /* nop */
5146 #define DUK_TVAL_DECREF_FAST(thr,v)            do {} while (0) /* nop */
5147 #define DUK_TVAL_DECREF_NORZ_FAST(thr,v)       do {} while (0) /* nop */
5148 #define DUK_TVAL_INCREF_SLOW(thr,v)            do {} while (0) /* nop */
5149 #define DUK_TVAL_DECREF_SLOW(thr,v)            do {} while (0) /* nop */
5150 #define DUK_TVAL_DECREF_NORZ_SLOW(thr,v)       do {} while (0) /* nop */
5151 #define DUK_TVAL_INCREF(thr,v)                 do {} while (0) /* nop */
5152 #define DUK_TVAL_DECREF(thr,v)                 do {} while (0) /* nop */
5153 #define DUK_TVAL_DECREF_NORZ(thr,v)            do {} while (0) /* nop */
5154 #define DUK_HEAPHDR_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5155 #define DUK_HEAPHDR_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5156 #define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5157 #define DUK_HEAPHDR_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5158 #define DUK_HEAPHDR_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5159 #define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5160 #define DUK_HEAPHDR_INCREF(thr,h)              do {} while (0) /* nop */
5161 #define DUK_HEAPHDR_DECREF(thr,h)              do {} while (0) /* nop */
5162 #define DUK_HEAPHDR_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5163 #define DUK_HSTRING_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5164 #define DUK_HSTRING_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5165 #define DUK_HSTRING_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5166 #define DUK_HSTRING_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5167 #define DUK_HSTRING_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5168 #define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5169 #define DUK_HSTRING_INCREF(thr,h)              do {} while (0) /* nop */
5170 #define DUK_HSTRING_DECREF(thr,h)              do {} while (0) /* nop */
5171 #define DUK_HSTRING_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5172 #define DUK_HOBJECT_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5173 #define DUK_HOBJECT_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5174 #define DUK_HOBJECT_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5175 #define DUK_HOBJECT_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5176 #define DUK_HOBJECT_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5177 #define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5178 #define DUK_HOBJECT_INCREF(thr,h)              do {} while (0) /* nop */
5179 #define DUK_HOBJECT_DECREF(thr,h)              do {} while (0) /* nop */
5180 #define DUK_HOBJECT_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5181 #define DUK_HBUFFER_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5182 #define DUK_HBUFFER_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5183 #define DUK_HBUFFER_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5184 #define DUK_HBUFFER_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5185 #define DUK_HBUFFER_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5186 #define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5187 #define DUK_HBUFFER_INCREF(thr,h)              do {} while (0) /* nop */
5188 #define DUK_HBUFFER_DECREF(thr,h)              do {} while (0) /* nop */
5189 #define DUK_HBUFFER_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5190 
5191 #define DUK_HCOMPFUNC_INCREF(thr,h)            do {} while (0) /* nop */
5192 #define DUK_HCOMPFUNC_DECREF(thr,h)            do {} while (0) /* nop */
5193 #define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       do {} while (0) /* nop */
5194 #define DUK_HNATFUNC_INCREF(thr,h)             do {} while (0) /* nop */
5195 #define DUK_HNATFUNC_DECREF(thr,h)             do {} while (0) /* nop */
5196 #define DUK_HNATFUNC_DECREF_NORZ(thr,h)        do {} while (0) /* nop */
5197 #define DUK_HBUFOBJ_INCREF(thr,h)              do {} while (0) /* nop */
5198 #define DUK_HBUFOBJ_DECREF(thr,h)              do {} while (0) /* nop */
5199 #define DUK_HBUFOBJ_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5200 #define DUK_HTHREAD_INCREF(thr,h)              do {} while (0) /* nop */
5201 #define DUK_HTHREAD_DECREF(thr,h)              do {} while (0) /* nop */
5202 #define DUK_HTHREAD_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5203 #define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5204 #define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5205 #define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h)  do {} while (0) /* nop */
5206 #define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5207 #define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5208 #define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h)  do {} while (0) /* nop */
5209 
5210 #define DUK_REFZERO_CHECK_FAST(thr)            do {} while (0) /* nop */
5211 #define DUK_REFZERO_CHECK_SLOW(thr)            do {} while (0) /* nop */
5212 
5213 #define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
5214 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5215 		DUK_TVAL_SET_UNDEFINED(tv__dst); \
5216 		DUK_UNREF((thr)); \
5217 	} while (0)
5218 
5219 #define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
5220 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5221 		DUK_TVAL_SET_UNUSED(tv__dst); \
5222 		DUK_UNREF((thr)); \
5223 	} while (0)
5224 
5225 #define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
5226 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5227 		DUK_TVAL_SET_NULL(tv__dst); \
5228 		DUK_UNREF((thr)); \
5229 	} while (0)
5230 
5231 #define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5232 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5233 		DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
5234 		DUK_UNREF((thr)); \
5235 	} while (0)
5236 
5237 #define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5238 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5239 		DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
5240 		DUK_UNREF((thr)); \
5241 	} while (0)
5242 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5243 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5244 		DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
5245 		DUK_UNREF((thr)); \
5246 	} while (0)
5247 #define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5248 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5249 		DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
5250 		DUK_UNREF((thr)); \
5251 	} while (0)
5252 #define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
5253 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5254 		DUK_TVAL_SET_NAN(tv__dst); \
5255 		DUK_UNREF((thr)); \
5256 	} while (0)
5257 #if defined(DUK_USE_FASTINT)
5258 #define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5259 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5260 		DUK_TVAL_SET_I48(tv__dst, (newval)); \
5261 		DUK_UNREF((thr)); \
5262 	} while (0)
5263 #define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5264 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5265 		DUK_TVAL_SET_I32(tv__dst, (newval)); \
5266 		DUK_UNREF((thr)); \
5267 	} while (0)
5268 #define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5269 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5270 		DUK_TVAL_SET_U32(tv__dst, (newval)); \
5271 		DUK_UNREF((thr)); \
5272 	} while (0)
5273 #else
5274 #define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
5275 	DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
5276 #endif  /* DUK_USE_FASTINT */
5277 
5278 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
5279 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5280 		DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
5281 		DUK_UNREF((thr)); \
5282 	} while (0)
5283 
5284 #define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5285 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5286 		DUK_TVAL_SET_STRING(tv__dst, (newval)); \
5287 		DUK_UNREF((thr)); \
5288 	} while (0)
5289 
5290 #define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5291 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5292 		DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
5293 		DUK_UNREF((thr)); \
5294 	} while (0)
5295 
5296 #define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5297 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5298 		DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
5299 		DUK_UNREF((thr)); \
5300 	} while (0)
5301 
5302 #define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5303 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5304 		DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
5305 		DUK_UNREF((thr)); \
5306 	} while (0)
5307 
5308 #define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
5309 		duk_tval *tv__dst, *tv__src; \
5310 		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
5311 		DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5312 		DUK_UNREF((thr)); \
5313 	} while (0)
5314 
5315 #define DUK_TVAL_SET_UNDEFINED_UPDREF         DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
5316 #define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ    DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
5317 #define DUK_TVAL_SET_UNUSED_UPDREF            DUK_TVAL_SET_UNUSED_UPDREF_ALT0
5318 #define DUK_TVAL_SET_NULL_UPDREF              DUK_TVAL_SET_NULL_UPDREF_ALT0
5319 #define DUK_TVAL_SET_BOOLEAN_UPDREF           DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
5320 #define DUK_TVAL_SET_NUMBER_UPDREF            DUK_TVAL_SET_NUMBER_UPDREF_ALT0
5321 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF    DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
5322 #define DUK_TVAL_SET_DOUBLE_UPDREF            DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
5323 #define DUK_TVAL_SET_NAN_UPDREF               DUK_TVAL_SET_NAN_UPDREF_ALT0
5324 #if defined(DUK_USE_FASTINT)
5325 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_I48_UPDREF_ALT0
5326 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_I32_UPDREF_ALT0
5327 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_U32_UPDREF_ALT0
5328 #else
5329 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF  /* XXX: fast-int-to-double */
5330 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5331 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5332 #endif  /* DUK_USE_FASTINT */
5333 #define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_I48_UPDREF  /* convenience */
5334 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF         DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
5335 #define DUK_TVAL_SET_STRING_UPDREF            DUK_TVAL_SET_STRING_UPDREF_ALT0
5336 #define DUK_TVAL_SET_OBJECT_UPDREF            DUK_TVAL_SET_OBJECT_UPDREF_ALT0
5337 #define DUK_TVAL_SET_BUFFER_UPDREF            DUK_TVAL_SET_BUFFER_UPDREF_ALT0
5338 #define DUK_TVAL_SET_POINTER_UPDREF           DUK_TVAL_SET_POINTER_UPDREF_ALT0
5339 
5340 #define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT0
5341 #define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5342 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5343 
5344 #endif  /* DUK_USE_REFERENCE_COUNTING */
5345 
5346 /*
5347  *  Some convenience macros that don't have optimized implementations now.
5348  */
5349 
5350 #define DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr,tv_dst,tv_src) do { \
5351 		duk_hthread *duk__thr = (thr); \
5352 		duk_tval *duk__dst = (tv_dst); \
5353 		duk_tval *duk__src = (tv_src); \
5354 		DUK_UNREF(duk__thr); \
5355 		DUK_TVAL_DECREF_NORZ(thr, duk__dst); \
5356 		DUK_TVAL_SET_TVAL(duk__dst, duk__src); \
5357 		DUK_TVAL_INCREF(thr, duk__dst); \
5358 	} while (0)
5359 
5360 #define DUK_TVAL_SET_U32_UPDREF_NORZ(thr,tv_dst,val) do { \
5361 		duk_hthread *duk__thr = (thr); \
5362 		duk_tval *duk__dst = (tv_dst); \
5363 		duk_uint32_t duk__val = (duk_uint32_t) (val); \
5364 		DUK_UNREF(duk__thr); \
5365 		DUK_TVAL_DECREF_NORZ(thr, duk__dst); \
5366 		DUK_TVAL_SET_U32(duk__dst, duk__val); \
5367 	} while (0)
5368 
5369 /*
5370  *  Prototypes
5371  */
5372 
5373 #if defined(DUK_USE_REFERENCE_COUNTING)
5374 #if defined(DUK_USE_FINALIZER_SUPPORT)
5375 DUK_INTERNAL_DECL void duk_refzero_check_slow(duk_hthread *thr);
5376 DUK_INTERNAL_DECL DUK_INLINE void duk_refzero_check_fast(duk_hthread *thr);
5377 #endif
5378 DUK_INTERNAL_DECL void duk_heaphdr_refcount_finalize_norz(duk_heap *heap, duk_heaphdr *hdr);
5379 DUK_INTERNAL_DECL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject *h);
5380 #if 0  /* Not needed: fast path handles inline; slow path uses duk_heaphdr_decref() which is needed anyway. */
5381 DUK_INTERNAL_DECL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h);
5382 DUK_INTERNAL_DECL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h);
5383 DUK_INTERNAL_DECL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h);
5384 DUK_INTERNAL_DECL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h);
5385 DUK_INTERNAL_DECL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h);
5386 DUK_INTERNAL_DECL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h);
5387 #endif
5388 DUK_INTERNAL_DECL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h);
5389 DUK_INTERNAL_DECL void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h);
5390 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
5391 DUK_INTERNAL_DECL void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h);  /* no 'norz' variant */
5392 DUK_INTERNAL_DECL void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h);  /* no 'norz' variant */
5393 DUK_INTERNAL_DECL void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h);
5394 DUK_INTERNAL_DECL void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h);
5395 #else
5396 DUK_INTERNAL_DECL void duk_tval_incref(duk_tval *tv);
5397 DUK_INTERNAL_DECL void duk_tval_decref(duk_hthread *thr, duk_tval *tv);
5398 DUK_INTERNAL_DECL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv);
5399 DUK_INTERNAL_DECL void duk_heaphdr_incref(duk_heaphdr *h);
5400 DUK_INTERNAL_DECL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h);
5401 DUK_INTERNAL_DECL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h);
5402 #endif
5403 #else  /* DUK_USE_REFERENCE_COUNTING */
5404 /* no refcounting */
5405 #endif  /* DUK_USE_REFERENCE_COUNTING */
5406 
5407 #endif  /* DUK_REFCOUNT_H_INCLUDED */
5408 /* #include duk_api_internal.h */
5409 /*
5410  *  Internal API calls which have (stack and other) semantics similar
5411  *  to the public API.
5412  */
5413 
5414 #if !defined(DUK_API_INTERNAL_H_INCLUDED)
5415 #define DUK_API_INTERNAL_H_INCLUDED
5416 
5417 /* duk_push_sprintf constants */
5418 #define DUK_PUSH_SPRINTF_INITIAL_SIZE  256L
5419 #define DUK_PUSH_SPRINTF_SANITY_LIMIT  (1L * 1024L * 1024L * 1024L)
5420 
5421 /* Flag ORed to err_code to indicate __FILE__ / __LINE__ is not
5422  * blamed as source of error for error fileName / lineNumber.
5423  */
5424 #define DUK_ERRCODE_FLAG_NOBLAME_FILELINE  (1L << 24)
5425 
5426 /* Current convention is to use duk_size_t for value stack sizes and global indices,
5427  * and duk_idx_t for local frame indices.
5428  */
5429 DUK_INTERNAL_DECL DUK_INLINE void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes);
5430 DUK_INTERNAL_DECL DUK_INLINE duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes);
5431 DUK_INTERNAL_DECL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t snug);
5432 
5433 DUK_INTERNAL_DECL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_size_t count);
5434 
5435 DUK_INTERNAL_DECL duk_tval *duk_reserve_gap(duk_hthread *thr, duk_idx_t idx_base, duk_idx_t count);
5436 
5437 DUK_INTERNAL_DECL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx);
5438 DUK_INTERNAL_DECL void duk_set_top_and_wipe(duk_hthread *thr, duk_idx_t top, duk_idx_t idx_wipe_start);
5439 
5440 DUK_INTERNAL_DECL void duk_dup_0(duk_hthread *thr);
5441 DUK_INTERNAL_DECL void duk_dup_1(duk_hthread *thr);
5442 DUK_INTERNAL_DECL void duk_dup_2(duk_hthread *thr);
5443 /* duk_dup_m1() would be same as duk_dup_top() */
5444 DUK_INTERNAL_DECL void duk_dup_m2(duk_hthread *thr);
5445 DUK_INTERNAL_DECL void duk_dup_m3(duk_hthread *thr);
5446 DUK_INTERNAL_DECL void duk_dup_m4(duk_hthread *thr);
5447 
5448 DUK_INTERNAL_DECL void duk_remove_unsafe(duk_hthread *thr, duk_idx_t idx);
5449 DUK_INTERNAL_DECL void duk_remove_m2(duk_hthread *thr);
5450 DUK_INTERNAL_DECL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);
5451 DUK_INTERNAL_DECL void duk_remove_n_unsafe(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);
5452 
5453 DUK_INTERNAL_DECL duk_int_t duk_get_type_tval(duk_tval *tv);
5454 DUK_INTERNAL_DECL duk_uint_t duk_get_type_mask_tval(duk_tval *tv);
5455 
5456 #if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
5457 DUK_INTERNAL_DECL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx);
5458 #endif
5459 DUK_INTERNAL_DECL duk_small_uint_t duk_get_class_number(duk_hthread *thr, duk_idx_t idx);
5460 
5461 DUK_INTERNAL_DECL duk_tval *duk_get_tval(duk_hthread *thr, duk_idx_t idx);
5462 DUK_INTERNAL_DECL duk_tval *duk_get_tval_or_unused(duk_hthread *thr, duk_idx_t idx);
5463 DUK_INTERNAL_DECL duk_tval *duk_require_tval(duk_hthread *thr, duk_idx_t idx);
5464 DUK_INTERNAL_DECL void duk_push_tval(duk_hthread *thr, duk_tval *tv);
5465 
5466 /* Push the current 'this' binding; throw TypeError if binding is not object
5467  * coercible (CheckObjectCoercible).
5468  */
5469 DUK_INTERNAL_DECL void duk_push_this_check_object_coercible(duk_hthread *thr);
5470 
5471 /* duk_push_this() + CheckObjectCoercible() + duk_to_object() */
5472 DUK_INTERNAL_DECL duk_hobject *duk_push_this_coercible_to_object(duk_hthread *thr);
5473 
5474 /* duk_push_this() + CheckObjectCoercible() + duk_to_string() */
5475 DUK_INTERNAL_DECL duk_hstring *duk_push_this_coercible_to_string(duk_hthread *thr);
5476 
5477 DUK_INTERNAL_DECL duk_hstring *duk_push_uint_to_hstring(duk_hthread *thr, duk_uint_t i);
5478 
5479 /* Get a borrowed duk_tval pointer to the current 'this' binding.  Caller must
5480  * make sure there's an active callstack entry.  Note that the returned pointer
5481  * is unstable with regards to side effects.
5482  */
5483 DUK_INTERNAL_DECL duk_tval *duk_get_borrowed_this_tval(duk_hthread *thr);
5484 
5485 /* XXX: add fastint support? */
5486 #define duk_push_u64(thr,val) \
5487 	duk_push_number((thr), (duk_double_t) (val))
5488 #define duk_push_i64(thr,val) \
5489 	duk_push_number((thr), (duk_double_t) (val))
5490 
5491 /* duk_push_(u)int() is guaranteed to support at least (un)signed 32-bit range */
5492 #define duk_push_u32(thr,val) \
5493 	duk_push_uint((thr), (duk_uint_t) (val))
5494 #define duk_push_i32(thr,val) \
5495 	duk_push_int((thr), (duk_int_t) (val))
5496 
5497 /* sometimes stack and array indices need to go on the stack */
5498 #define duk_push_idx(thr,val) \
5499 	duk_push_int((thr), (duk_int_t) (val))
5500 #define duk_push_uarridx(thr,val) \
5501 	duk_push_uint((thr), (duk_uint_t) (val))
5502 #define duk_push_size_t(thr,val) \
5503 	duk_push_uint((thr), (duk_uint_t) (val))  /* XXX: assumed to fit for now */
5504 
5505 DUK_INTERNAL_DECL duk_bool_t duk_is_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
5506 
5507 DUK_INTERNAL_DECL duk_bool_t duk_is_callable_tval(duk_hthread *thr, duk_tval *tv);
5508 
5509 DUK_INTERNAL_DECL duk_bool_t duk_is_bare_object(duk_hthread *thr, duk_idx_t idx);
5510 
5511 DUK_INTERNAL_DECL duk_hstring *duk_get_hstring(duk_hthread *thr, duk_idx_t idx);
5512 DUK_INTERNAL_DECL duk_hstring *duk_get_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx);
5513 DUK_INTERNAL_DECL const char *duk_get_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
5514 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject(duk_hthread *thr, duk_idx_t idx);
5515 DUK_INTERNAL_DECL duk_hbuffer *duk_get_hbuffer(duk_hthread *thr, duk_idx_t idx);
5516 DUK_INTERNAL_DECL duk_hthread *duk_get_hthread(duk_hthread *thr, duk_idx_t idx);
5517 DUK_INTERNAL_DECL duk_hcompfunc *duk_get_hcompfunc(duk_hthread *thr, duk_idx_t idx);
5518 DUK_INTERNAL_DECL duk_hnatfunc *duk_get_hnatfunc(duk_hthread *thr, duk_idx_t idx);
5519 
5520 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);
5521 
5522 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum);
5523 
5524 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
5525 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
5526 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_accept_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
5527 #define duk_require_hobject_promote_lfunc(thr,idx) \
5528 	duk_require_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)
5529 #define duk_get_hobject_promote_lfunc(thr,idx) \
5530 	duk_get_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)
5531 
5532 #if 0  /*unused*/
5533 DUK_INTERNAL_DECL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx);
5534 #endif
5535 
5536 DUK_INTERNAL_DECL duk_hstring *duk_known_hstring(duk_hthread *thr, duk_idx_t idx);
5537 DUK_INTERNAL_DECL duk_hobject *duk_known_hobject(duk_hthread *thr, duk_idx_t idx);
5538 DUK_INTERNAL_DECL duk_hbuffer *duk_known_hbuffer(duk_hthread *thr, duk_idx_t idx);
5539 DUK_INTERNAL_DECL duk_hcompfunc *duk_known_hcompfunc(duk_hthread *thr, duk_idx_t idx);
5540 DUK_INTERNAL_DECL duk_hnatfunc *duk_known_hnatfunc(duk_hthread *thr, duk_idx_t idx);
5541 
5542 DUK_INTERNAL_DECL duk_double_t duk_to_number_tval(duk_hthread *thr, duk_tval *tv);
5543 
5544 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring(duk_hthread *thr, duk_idx_t idx);
5545 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring_m1(duk_hthread *thr);
5546 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring_acceptsymbol(duk_hthread *thr, duk_idx_t idx);
5547 
5548 DUK_INTERNAL_DECL duk_hobject *duk_to_hobject(duk_hthread *thr, duk_idx_t idx);
5549 
5550 DUK_INTERNAL_DECL duk_double_t duk_to_number_m1(duk_hthread *thr);
5551 DUK_INTERNAL_DECL duk_double_t duk_to_number_m2(duk_hthread *thr);
5552 
5553 DUK_INTERNAL_DECL duk_bool_t duk_to_boolean_top_pop(duk_hthread *thr);
5554 
5555 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* only needed by debugger for now */
5556 DUK_INTERNAL_DECL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx);
5557 #endif
5558 DUK_INTERNAL_DECL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects);
5559 
5560 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 */
5561 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);
5562 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);
5563 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
5564 DUK_INTERNAL_DECL duk_uint8_t duk_to_uint8clamped(duk_hthread *thr, duk_idx_t idx);
5565 #endif
5566 DUK_INTERNAL_DECL duk_hstring *duk_to_property_key_hstring(duk_hthread *thr, duk_idx_t idx);
5567 
5568 DUK_INTERNAL_DECL duk_hstring *duk_require_hstring(duk_hthread *thr, duk_idx_t idx);
5569 DUK_INTERNAL_DECL duk_hstring *duk_require_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx);
5570 DUK_INTERNAL_DECL const char *duk_require_lstring_notsymbol(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len);
5571 DUK_INTERNAL_DECL const char *duk_require_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
5572 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject(duk_hthread *thr, duk_idx_t idx);
5573 DUK_INTERNAL_DECL duk_hbuffer *duk_require_hbuffer(duk_hthread *thr, duk_idx_t idx);
5574 DUK_INTERNAL_DECL duk_hthread *duk_require_hthread(duk_hthread *thr, duk_idx_t idx);
5575 DUK_INTERNAL_DECL duk_hcompfunc *duk_require_hcompfunc(duk_hthread *thr, duk_idx_t idx);
5576 DUK_INTERNAL_DECL duk_hnatfunc *duk_require_hnatfunc(duk_hthread *thr, duk_idx_t idx);
5577 
5578 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum);
5579 
5580 DUK_INTERNAL_DECL void duk_push_hstring(duk_hthread *thr, duk_hstring *h);
5581 DUK_INTERNAL_DECL void duk_push_hstring_stridx(duk_hthread *thr, duk_small_uint_t stridx);
5582 DUK_INTERNAL_DECL void duk_push_hstring_empty(duk_hthread *thr);
5583 DUK_INTERNAL_DECL void duk_push_hobject(duk_hthread *thr, duk_hobject *h);
5584 DUK_INTERNAL_DECL void duk_push_hbuffer(duk_hthread *thr, duk_hbuffer *h);
5585 #define duk_push_hthread(thr,h) \
5586 	duk_push_hobject((thr), (duk_hobject *) (h))
5587 #define duk_push_hnatfunc(thr,h) \
5588 	duk_push_hobject((thr), (duk_hobject *) (h))
5589 DUK_INTERNAL_DECL void duk_push_hobject_bidx(duk_hthread *thr, duk_small_int_t builtin_idx);
5590 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);
5591 DUK_INTERNAL_DECL duk_hobject *duk_push_object_helper_proto(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_hobject *proto);
5592 DUK_INTERNAL_DECL duk_hcompfunc *duk_push_hcompfunc(duk_hthread *thr);
5593 DUK_INTERNAL_DECL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr);
5594 DUK_INTERNAL_DECL void duk_push_c_function_builtin(duk_hthread *thr, duk_c_function func, duk_int_t nargs);
5595 DUK_INTERNAL_DECL void duk_push_c_function_builtin_noconstruct(duk_hthread *thr, duk_c_function func, duk_int_t nargs);
5596 
5597 /* XXX: duk_push_harray() and duk_push_hcompfunc() are inconsistent with
5598  * duk_push_hobject() etc which don't create a new value.
5599  */
5600 DUK_INTERNAL_DECL duk_harray *duk_push_harray(duk_hthread *thr);
5601 DUK_INTERNAL_DECL duk_harray *duk_push_harray_with_size(duk_hthread *thr, duk_uint32_t size);
5602 DUK_INTERNAL_DECL duk_tval *duk_push_harray_with_size_outptr(duk_hthread *thr, duk_uint32_t size);
5603 
5604 DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, duk_size_t sz);
5605 DUK_INTERNAL_DECL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags);
5606 DUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_hthread *thr, duk_tval *tv);
5607 DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv);
5608 #if 0  /* not used yet */
5609 DUK_INTERNAL_DECL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h);
5610 #endif
5611 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
5612 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);
5613 #endif
5614 
5615 DUK_INTERNAL_DECL void *duk_push_fixed_buffer_nozero(duk_hthread *thr, duk_size_t len);
5616 DUK_INTERNAL_DECL void *duk_push_fixed_buffer_zero(duk_hthread *thr, duk_size_t len);
5617 
5618 DUK_INTERNAL_DECL const char *duk_push_string_readable(duk_hthread *thr, duk_idx_t idx);
5619 DUK_INTERNAL_DECL const char *duk_push_string_tval_readable(duk_hthread *thr, duk_tval *tv);
5620 DUK_INTERNAL_DECL const char *duk_push_string_tval_readable_error(duk_hthread *thr, duk_tval *tv);
5621 
5622 /* The duk_xxx_prop_stridx_short() variants expect their arguments to be short
5623  * enough to be packed into a single 32-bit integer argument.  Argument limits
5624  * vary per call; typically 16 bits are assigned to the signed value stack index
5625  * and the stridx.  In practice these work well for footprint with constant
5626  * arguments and such call sites are also easiest to verify to be correct.
5627  */
5628 
5629 DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [val] */
5630 DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5631 #define duk_get_prop_stridx_short(thr,obj_idx,stridx) \
5632 	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
5633 	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
5634 	 duk_get_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5635 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);  /* [] -> [] */
5636 
5637 DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop(duk_hthread *thr, duk_idx_t obj_idx);
5638 DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);
5639 DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5640 #define duk_xget_owndataprop_stridx_short(thr,obj_idx,stridx) \
5641 	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
5642 	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
5643 	 duk_xget_owndataprop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5644 
5645 DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [val] -> [] */
5646 DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5647 #define duk_put_prop_stridx_short(thr,obj_idx,stridx) \
5648 	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
5649 	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
5650 	 duk_put_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5651 
5652 DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [] */
5653 #if 0  /* Too few call sites to be useful. */
5654 DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5655 #define duk_del_prop_stridx_short(thr,obj_idx,stridx) \
5656 	(DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \
5657 	 DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \
5658 	 duk_del_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5659 #endif
5660 #define duk_del_prop_stridx_short(thr,obj_idx,stridx) \
5661 	duk_del_prop_stridx((thr), (obj_idx), (stridx))
5662 
5663 DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [] */
5664 #if 0  /* Too few call sites to be useful. */
5665 DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5666 #define duk_has_prop_stridx_short(thr,obj_idx,stridx) \
5667 	(DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \
5668 	 DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \
5669 	 duk_has_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5670 #endif
5671 #define duk_has_prop_stridx_short(thr,obj_idx,stridx) \
5672 	duk_has_prop_stridx((thr), (obj_idx), (stridx))
5673 
5674 DUK_INTERNAL_DECL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags);  /* [key val] -> [] */
5675 
5676 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] -> [] */
5677 
5678 /* XXX: Because stridx and desc_flags have a limited range, this call could
5679  * always pack stridx and desc_flags into a single argument.
5680  */
5681 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] -> [] */
5682 DUK_INTERNAL_DECL void duk_xdef_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5683 #define duk_xdef_prop_stridx_short(thr,obj_idx,stridx,desc_flags) \
5684 	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x80L && (duk_int_t) (obj_idx) <= 0x7fL), \
5685 	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
5686 	 DUK_ASSERT_EXPR((duk_int_t) (desc_flags) >= 0 && (duk_int_t) (desc_flags) <= 0xffL), \
5687 	 duk_xdef_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 24) + (((duk_uint_t) (stridx)) << 8) + (duk_uint_t) (desc_flags)))
5688 
5689 #define duk_xdef_prop_wec(thr,obj_idx) \
5690 	duk_xdef_prop((thr), (obj_idx), DUK_PROPDESC_FLAGS_WEC)
5691 #define duk_xdef_prop_index_wec(thr,obj_idx,arr_idx) \
5692 	duk_xdef_prop_index((thr), (obj_idx), (arr_idx), DUK_PROPDESC_FLAGS_WEC)
5693 #define duk_xdef_prop_stridx_wec(thr,obj_idx,stridx) \
5694 	duk_xdef_prop_stridx((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)
5695 #define duk_xdef_prop_stridx_short_wec(thr,obj_idx,stridx) \
5696 	duk_xdef_prop_stridx_short((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)
5697 
5698 #if 0  /*unused*/
5699 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);  /* [] -> [] */
5700 #endif
5701 
5702 DUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);  /* [] -> [] */
5703 
5704 DUK_INTERNAL_DECL duk_bool_t duk_get_method_stridx(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t stridx);
5705 
5706 DUK_INTERNAL_DECL void duk_pack(duk_hthread *thr, duk_idx_t count);
5707 DUK_INTERNAL_DECL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx);
5708 #if 0
5709 DUK_INTERNAL_DECL void duk_unpack(duk_hthread *thr);
5710 #endif
5711 
5712 DUK_INTERNAL_DECL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstring *h);
5713 
5714 DUK_INTERNAL_DECL void duk_resolve_nonbound_function(duk_hthread *thr);
5715 
5716 DUK_INTERNAL_DECL duk_idx_t duk_get_top_require_min(duk_hthread *thr, duk_idx_t min_top);
5717 DUK_INTERNAL_DECL duk_idx_t duk_get_top_index_unsafe(duk_hthread *thr);
5718 
5719 DUK_INTERNAL_DECL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count);
5720 DUK_INTERNAL_DECL void duk_pop_unsafe(duk_hthread *thr);
5721 DUK_INTERNAL_DECL void duk_pop_2_unsafe(duk_hthread *thr);
5722 DUK_INTERNAL_DECL void duk_pop_3_unsafe(duk_hthread *thr);
5723 DUK_INTERNAL_DECL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count);
5724 DUK_INTERNAL_DECL void duk_pop_nodecref_unsafe(duk_hthread *thr);
5725 DUK_INTERNAL_DECL void duk_pop_2_nodecref_unsafe(duk_hthread *thr);
5726 DUK_INTERNAL_DECL void duk_pop_3_nodecref_unsafe(duk_hthread *thr);
5727 DUK_INTERNAL_DECL void duk_pop_undefined(duk_hthread *thr);
5728 
5729 DUK_INTERNAL_DECL void duk_compact_m1(duk_hthread *thr);
5730 
5731 DUK_INTERNAL_DECL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_bool_t is_freeze);
5732 
5733 DUK_INTERNAL_DECL void duk_insert_undefined(duk_hthread *thr, duk_idx_t idx);
5734 DUK_INTERNAL_DECL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);
5735 
5736 DUK_INTERNAL_DECL void duk_concat_2(duk_hthread *thr);
5737 
5738 DUK_INTERNAL_DECL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags);
5739 
5740 #if defined(DUK_USE_SYMBOL_BUILTIN)
5741 DUK_INTERNAL_DECL void duk_to_primitive_ordinary(duk_hthread *thr, duk_idx_t idx, duk_int_t hint);
5742 #endif
5743 
5744 DUK_INTERNAL_DECL void duk_clear_prototype(duk_hthread *thr, duk_idx_t idx);
5745 
5746 /* Raw internal valstack access macros: access is unsafe so call site
5747  * must have a guarantee that the index is valid.  When that is the case,
5748  * using these macro results in faster and smaller code than duk_get_tval().
5749  * Both 'ctx' and 'idx' are evaluted multiple times, but only for asserts.
5750  */
5751 #define DUK_ASSERT_VALID_NEGIDX(thr,idx) \
5752 	(DUK_ASSERT_EXPR((duk_int_t) (idx) < 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx))))
5753 #define DUK_ASSERT_VALID_POSIDX(thr,idx) \
5754 	(DUK_ASSERT_EXPR((duk_int_t) (idx) >= 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx))))
5755 #define DUK_GET_TVAL_NEGIDX(thr,idx) \
5756 	(DUK_ASSERT_VALID_NEGIDX((thr),(idx)), ((duk_hthread *) (thr))->valstack_top + (idx))
5757 #define DUK_GET_TVAL_POSIDX(thr,idx) \
5758 	(DUK_ASSERT_VALID_POSIDX((thr),(idx)), ((duk_hthread *) (thr))->valstack_bottom + (idx))
5759 #define DUK_GET_HOBJECT_NEGIDX(thr,idx) \
5760 	(DUK_ASSERT_VALID_NEGIDX((thr),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_top + (idx)))
5761 #define DUK_GET_HOBJECT_POSIDX(thr,idx) \
5762 	(DUK_ASSERT_VALID_POSIDX((thr),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_bottom + (idx)))
5763 
5764 #define DUK_GET_THIS_TVAL_PTR(thr) \
5765 	(DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \
5766 	 (thr)->valstack_bottom - 1)
5767 
5768 DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr);
5769 DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr);
5770 DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr);
5771 
5772 #endif  /* DUK_API_INTERNAL_H_INCLUDED */
5773 /* #include duk_hstring.h */
5774 /*
5775  *  Heap string representation.
5776  *
5777  *  Strings are byte sequences ordinarily stored in extended UTF-8 format,
5778  *  allowing values larger than the official UTF-8 range (used internally)
5779  *  and also allowing UTF-8 encoding of surrogate pairs (CESU-8 format).
5780  *  Strings may also be invalid UTF-8 altogether which is the case e.g. with
5781  *  strings used as internal property names and raw buffers converted to
5782  *  strings.  In such cases the 'clen' field contains an inaccurate value.
5783  *
5784  *  ECMAScript requires support for 32-bit long strings.  However, since each
5785  *  16-bit codepoint can take 3 bytes in CESU-8, this representation can only
5786  *  support about 1.4G codepoint long strings in extreme cases.  This is not
5787  *  really a practical issue.
5788  */
5789 
5790 #if !defined(DUK_HSTRING_H_INCLUDED)
5791 #define DUK_HSTRING_H_INCLUDED
5792 
5793 /* Impose a maximum string length for now.  Restricted artificially to
5794  * ensure adding a heap header length won't overflow size_t.  The limit
5795  * should be synchronized with DUK_HBUFFER_MAX_BYTELEN.
5796  *
5797  * E5.1 makes provisions to support strings longer than 4G characters.
5798  * This limit should be eliminated on 64-bit platforms (and increased
5799  * closer to maximum support on 32-bit platforms).
5800  */
5801 
5802 #if defined(DUK_USE_STRLEN16)
5803 #define DUK_HSTRING_MAX_BYTELEN                     (0x0000ffffUL)
5804 #else
5805 #define DUK_HSTRING_MAX_BYTELEN                     (0x7fffffffUL)
5806 #endif
5807 
5808 /* XXX: could add flags for "is valid CESU-8" (ECMAScript compatible strings),
5809  * "is valid UTF-8", "is valid extended UTF-8" (internal strings are not,
5810  * regexp bytecode is), and "contains non-BMP characters".  These are not
5811  * needed right now.
5812  */
5813 
5814 /* With lowmem builds the high 16 bits of duk_heaphdr are used for other
5815  * purposes, so this leaves 7 duk_heaphdr flags and 9 duk_hstring flags.
5816  */
5817 #define DUK_HSTRING_FLAG_ASCII                      DUK_HEAPHDR_USER_FLAG(0)  /* string is ASCII, clen == blen */
5818 #define DUK_HSTRING_FLAG_ARRIDX                     DUK_HEAPHDR_USER_FLAG(1)  /* string is a valid array index */
5819 #define DUK_HSTRING_FLAG_SYMBOL                     DUK_HEAPHDR_USER_FLAG(2)  /* string is a symbol (invalid utf-8) */
5820 #define DUK_HSTRING_FLAG_HIDDEN                     DUK_HEAPHDR_USER_FLAG(3)  /* string is a hidden symbol (implies symbol, Duktape 1.x internal string) */
5821 #define DUK_HSTRING_FLAG_RESERVED_WORD              DUK_HEAPHDR_USER_FLAG(4)  /* string is a reserved word (non-strict) */
5822 #define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD       DUK_HEAPHDR_USER_FLAG(5)  /* string is a reserved word (strict) */
5823 #define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS          DUK_HEAPHDR_USER_FLAG(6)  /* string is 'eval' or 'arguments' */
5824 #define DUK_HSTRING_FLAG_EXTDATA                    DUK_HEAPHDR_USER_FLAG(7)  /* string data is external (duk_hstring_external) */
5825 #define DUK_HSTRING_FLAG_PINNED_LITERAL             DUK_HEAPHDR_USER_FLAG(8)  /* string is a literal, and pinned */
5826 
5827 #define DUK_HSTRING_HAS_ASCII(x)                    DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
5828 #define DUK_HSTRING_HAS_ARRIDX(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
5829 #define DUK_HSTRING_HAS_SYMBOL(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
5830 #define DUK_HSTRING_HAS_HIDDEN(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
5831 #define DUK_HSTRING_HAS_RESERVED_WORD(x)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
5832 #define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
5833 #define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
5834 #define DUK_HSTRING_HAS_EXTDATA(x)                  DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
5835 #define DUK_HSTRING_HAS_PINNED_LITERAL(x)           DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
5836 
5837 #define DUK_HSTRING_SET_ASCII(x)                    DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
5838 #define DUK_HSTRING_SET_ARRIDX(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
5839 #define DUK_HSTRING_SET_SYMBOL(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
5840 #define DUK_HSTRING_SET_HIDDEN(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
5841 #define DUK_HSTRING_SET_RESERVED_WORD(x)            DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
5842 #define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x)     DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
5843 #define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x)        DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
5844 #define DUK_HSTRING_SET_EXTDATA(x)                  DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
5845 #define DUK_HSTRING_SET_PINNED_LITERAL(x)           DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
5846 
5847 #define DUK_HSTRING_CLEAR_ASCII(x)                  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
5848 #define DUK_HSTRING_CLEAR_ARRIDX(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
5849 #define DUK_HSTRING_CLEAR_SYMBOL(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
5850 #define DUK_HSTRING_CLEAR_HIDDEN(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
5851 #define DUK_HSTRING_CLEAR_RESERVED_WORD(x)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
5852 #define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
5853 #define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
5854 #define DUK_HSTRING_CLEAR_EXTDATA(x)                DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
5855 #define DUK_HSTRING_CLEAR_PINNED_LITERAL(x)         DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
5856 
5857 #if 0  /* Slightly smaller code without explicit flag, but explicit flag
5858         * is very useful when 'clen' is dropped.
5859         */
5860 #define DUK_HSTRING_IS_ASCII(x)                     (DUK_HSTRING_GET_BYTELEN((x)) == DUK_HSTRING_GET_CHARLEN((x)))
5861 #endif
5862 #define DUK_HSTRING_IS_ASCII(x)                     DUK_HSTRING_HAS_ASCII((x))  /* lazily set! */
5863 #define DUK_HSTRING_IS_EMPTY(x)                     (DUK_HSTRING_GET_BYTELEN((x)) == 0)
5864 
5865 #if defined(DUK_USE_STRHASH16)
5866 #define DUK_HSTRING_GET_HASH(x)                     ((x)->hdr.h_flags >> 16)
5867 #define DUK_HSTRING_SET_HASH(x,v) do { \
5868 		(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | ((v) << 16); \
5869 	} while (0)
5870 #else
5871 #define DUK_HSTRING_GET_HASH(x)                     ((x)->hash)
5872 #define DUK_HSTRING_SET_HASH(x,v) do { \
5873 		(x)->hash = (v); \
5874 	} while (0)
5875 #endif
5876 
5877 #if defined(DUK_USE_STRLEN16)
5878 #define DUK_HSTRING_GET_BYTELEN(x)                  ((x)->hdr.h_strextra16)
5879 #define DUK_HSTRING_SET_BYTELEN(x,v) do { \
5880 		(x)->hdr.h_strextra16 = (v); \
5881 	} while (0)
5882 #if defined(DUK_USE_HSTRING_CLEN)
5883 #define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
5884 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
5885 		(x)->clen16 = (v); \
5886 	} while (0)
5887 #else
5888 #define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
5889 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
5890 		DUK_ASSERT(0);  /* should never be called */ \
5891 	} while (0)
5892 #endif
5893 #else
5894 #define DUK_HSTRING_GET_BYTELEN(x)                  ((x)->blen)
5895 #define DUK_HSTRING_SET_BYTELEN(x,v) do { \
5896 		(x)->blen = (v); \
5897 	} while (0)
5898 #define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
5899 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
5900 		(x)->clen = (v); \
5901 	} while (0)
5902 #endif
5903 
5904 #if defined(DUK_USE_HSTRING_EXTDATA)
5905 #define DUK_HSTRING_GET_EXTDATA(x) \
5906 	((x)->extdata)
5907 #define DUK_HSTRING_GET_DATA(x) \
5908 	(DUK_HSTRING_HAS_EXTDATA((x)) ? \
5909 		DUK_HSTRING_GET_EXTDATA((const duk_hstring_external *) (x)) : ((const duk_uint8_t *) ((x) + 1)))
5910 #else
5911 #define DUK_HSTRING_GET_DATA(x) \
5912 	((const duk_uint8_t *) ((x) + 1))
5913 #endif
5914 
5915 #define DUK_HSTRING_GET_DATA_END(x) \
5916 	(DUK_HSTRING_GET_DATA((x)) + (x)->blen)
5917 
5918 /* Marker value; in E5 2^32-1 is not a valid array index (2^32-2 is highest
5919  * valid).
5920  */
5921 #define DUK_HSTRING_NO_ARRAY_INDEX  (0xffffffffUL)
5922 
5923 #if defined(DUK_USE_HSTRING_ARRIDX)
5924 #define DUK_HSTRING_GET_ARRIDX_FAST(h)  ((h)->arridx)
5925 #define DUK_HSTRING_GET_ARRIDX_SLOW(h)  ((h)->arridx)
5926 #else
5927 /* Get array index related to string (or return DUK_HSTRING_NO_ARRAY_INDEX);
5928  * avoids helper call if string has no array index value.
5929  */
5930 #define DUK_HSTRING_GET_ARRIDX_FAST(h)  \
5931 	(DUK_HSTRING_HAS_ARRIDX((h)) ? duk_js_to_arrayindex_hstring_fast_known((h)) : DUK_HSTRING_NO_ARRAY_INDEX)
5932 
5933 /* Slower but more compact variant. */
5934 #define DUK_HSTRING_GET_ARRIDX_SLOW(h)  \
5935 	(duk_js_to_arrayindex_hstring_fast((h)))
5936 #endif
5937 
5938 /* XXX: these actually fit into duk_hstring */
5939 #define DUK_SYMBOL_TYPE_HIDDEN 0
5940 #define DUK_SYMBOL_TYPE_GLOBAL 1
5941 #define DUK_SYMBOL_TYPE_LOCAL 2
5942 #define DUK_SYMBOL_TYPE_WELLKNOWN 3
5943 
5944 /* Assertion for duk_hstring validity. */
5945 #if defined(DUK_USE_ASSERTIONS)
5946 DUK_INTERNAL_DECL void duk_hstring_assert_valid(duk_hstring *h);
5947 #define DUK_HSTRING_ASSERT_VALID(h)  do { duk_hstring_assert_valid((h)); } while (0)
5948 #else
5949 #define DUK_HSTRING_ASSERT_VALID(h)  do {} while (0)
5950 #endif
5951 
5952 /*
5953  *  Misc
5954  */
5955 
5956 struct duk_hstring {
5957 	/* Smaller heaphdr than for other objects, because strings are held
5958 	 * in string intern table which requires no link pointers.  Much of
5959 	 * the 32-bit flags field is unused by flags, so we can stuff a 16-bit
5960 	 * field in there.
5961 	 */
5962 	duk_heaphdr_string hdr;
5963 
5964 	/* String hash. */
5965 #if defined(DUK_USE_STRHASH16)
5966 	/* If 16-bit hash is in use, stuff it into duk_heaphdr_string flags. */
5967 #else
5968 	duk_uint32_t hash;
5969 #endif
5970 
5971 	/* Precomputed array index (or DUK_HSTRING_NO_ARRAY_INDEX). */
5972 #if defined(DUK_USE_HSTRING_ARRIDX)
5973 	duk_uarridx_t arridx;
5974 #endif
5975 
5976 	/* Length in bytes (not counting NUL term). */
5977 #if defined(DUK_USE_STRLEN16)
5978 	/* placed in duk_heaphdr_string */
5979 #else
5980 	duk_uint32_t blen;
5981 #endif
5982 
5983 	/* Length in codepoints (must be E5 compatible). */
5984 #if defined(DUK_USE_STRLEN16)
5985 #if defined(DUK_USE_HSTRING_CLEN)
5986 	duk_uint16_t clen16;
5987 #else
5988 	/* computed live */
5989 #endif
5990 #else
5991 	duk_uint32_t clen;
5992 #endif
5993 
5994 	/*
5995 	 *  String data of 'blen+1' bytes follows (+1 for NUL termination
5996 	 *  convenience for C API).  No alignment needs to be guaranteed
5997 	 *  for strings, but fields above should guarantee alignment-by-4
5998 	 *  (but not alignment-by-8).
5999 	 */
6000 };
6001 
6002 /* The external string struct is defined even when the feature is inactive. */
6003 struct duk_hstring_external {
6004 	duk_hstring str;
6005 
6006 	/*
6007 	 *  For an external string, the NUL-terminated string data is stored
6008 	 *  externally.  The user must guarantee that data behind this pointer
6009 	 *  doesn't change while it's used.
6010 	 */
6011 
6012 	const duk_uint8_t *extdata;
6013 };
6014 
6015 /*
6016  *  Prototypes
6017  */
6018 
6019 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);
6020 DUK_INTERNAL_DECL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const char *cstr);
6021 DUK_INTERNAL_DECL duk_size_t duk_hstring_get_charlen(duk_hstring *h);
6022 #if !defined(DUK_USE_HSTRING_LAZY_CLEN)
6023 DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);
6024 #endif
6025 
6026 #endif  /* DUK_HSTRING_H_INCLUDED */
6027 /* #include duk_hobject.h */
6028 /*
6029  *  Heap object representation.
6030  *
6031  *  Heap objects are used for ECMAScript objects, arrays, and functions,
6032  *  but also for internal control like declarative and object environment
6033  *  records.  Compiled functions, native functions, and threads are also
6034  *  objects but with an extended C struct.
6035  *
6036  *  Objects provide the required ECMAScript semantics and exotic behaviors
6037  *  especially for property access.
6038  *
6039  *  Properties are stored in three conceptual parts:
6040  *
6041  *    1. A linear 'entry part' contains ordered key-value-attributes triples
6042  *       and is the main method of string properties.
6043  *
6044  *    2. An optional linear 'array part' is used for array objects to store a
6045  *       (dense) range of [0,N[ array indexed entries with default attributes
6046  *       (writable, enumerable, configurable).  If the array part would become
6047  *       sparse or non-default attributes are required, the array part is
6048  *       abandoned and moved to the 'entry part'.
6049  *
6050  *    3. An optional 'hash part' is used to optimize lookups of the entry
6051  *       part; it is used only for objects with sufficiently many properties
6052  *       and can be abandoned without loss of information.
6053  *
6054  *  These three conceptual parts are stored in a single memory allocated area.
6055  *  This minimizes memory allocation overhead but also means that all three
6056  *  parts are resized together, and makes property access a bit complicated.
6057  */
6058 
6059 #if !defined(DUK_HOBJECT_H_INCLUDED)
6060 #define DUK_HOBJECT_H_INCLUDED
6061 
6062 /* Object flags.  Make sure this stays in sync with debugger object
6063  * inspection code.
6064  */
6065 
6066 /* XXX: some flags are object subtype specific (e.g. common to all function
6067  * subtypes, duk_harray, etc) and could be reused for different subtypes.
6068  */
6069 #define DUK_HOBJECT_FLAG_EXTENSIBLE            DUK_HEAPHDR_USER_FLAG(0)   /* object is extensible */
6070 #define DUK_HOBJECT_FLAG_CONSTRUCTABLE         DUK_HEAPHDR_USER_FLAG(1)   /* object is constructable */
6071 #define DUK_HOBJECT_FLAG_CALLABLE              DUK_HEAPHDR_USER_FLAG(2)   /* object is callable */
6072 #define DUK_HOBJECT_FLAG_BOUNDFUNC             DUK_HEAPHDR_USER_FLAG(3)   /* object established using Function.prototype.bind() */
6073 #define DUK_HOBJECT_FLAG_COMPFUNC              DUK_HEAPHDR_USER_FLAG(4)   /* object is a compiled function (duk_hcompfunc) */
6074 #define DUK_HOBJECT_FLAG_NATFUNC               DUK_HEAPHDR_USER_FLAG(5)   /* object is a native function (duk_hnatfunc) */
6075 #define DUK_HOBJECT_FLAG_BUFOBJ                DUK_HEAPHDR_USER_FLAG(6)   /* object is a buffer object (duk_hbufobj) (always exotic) */
6076 #define DUK_HOBJECT_FLAG_FASTREFS              DUK_HEAPHDR_USER_FLAG(7)   /* object has no fields needing DECREF/marking beyond base duk_hobject header */
6077 #define DUK_HOBJECT_FLAG_ARRAY_PART            DUK_HEAPHDR_USER_FLAG(8)   /* object has an array part (a_size may still be 0) */
6078 #define DUK_HOBJECT_FLAG_STRICT                DUK_HEAPHDR_USER_FLAG(9)   /* function: function object is strict */
6079 #define DUK_HOBJECT_FLAG_NOTAIL                DUK_HEAPHDR_USER_FLAG(10)  /* function: function must not be tail called */
6080 #define DUK_HOBJECT_FLAG_NEWENV                DUK_HEAPHDR_USER_FLAG(11)  /* function: create new environment when called (see duk_hcompfunc) */
6081 #define DUK_HOBJECT_FLAG_NAMEBINDING           DUK_HEAPHDR_USER_FLAG(12)  /* function: create binding for func name (function templates only, used for named function expressions) */
6082 #define DUK_HOBJECT_FLAG_CREATEARGS            DUK_HEAPHDR_USER_FLAG(13)  /* function: create an arguments object on function call */
6083 #define DUK_HOBJECT_FLAG_HAVE_FINALIZER        DUK_HEAPHDR_USER_FLAG(14)  /* object has a callable (own) finalizer property */
6084 #define DUK_HOBJECT_FLAG_EXOTIC_ARRAY          DUK_HEAPHDR_USER_FLAG(15)  /* 'Array' object, array length and index exotic behavior */
6085 #define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ      DUK_HEAPHDR_USER_FLAG(16)  /* 'String' object, array index exotic behavior */
6086 #define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS      DUK_HEAPHDR_USER_FLAG(17)  /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */
6087 #define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ       DUK_HEAPHDR_USER_FLAG(18)  /* 'Proxy' object */
6088 #define DUK_HOBJECT_FLAG_SPECIAL_CALL          DUK_HEAPHDR_USER_FLAG(19)  /* special casing in call behavior, for .call(), .apply(), etc. */
6089 
6090 #define DUK_HOBJECT_FLAG_CLASS_BASE            DUK_HEAPHDR_USER_FLAG_NUMBER(20)
6091 #define DUK_HOBJECT_FLAG_CLASS_BITS            5
6092 
6093 #define DUK_HOBJECT_GET_CLASS_NUMBER(h)        \
6094 	DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS)
6095 #define DUK_HOBJECT_SET_CLASS_NUMBER(h,v)      \
6096 	DUK_HEAPHDR_SET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS, (v))
6097 
6098 #define DUK_HOBJECT_GET_CLASS_MASK(h)          \
6099 	(1UL << DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS))
6100 
6101 /* Macro for creating flag initializer from a class number.
6102  * Unsigned type cast is needed to avoid warnings about coercing
6103  * a signed integer to an unsigned one; the largest class values
6104  * have the highest bit (bit 31) set which causes this.
6105  */
6106 #define DUK_HOBJECT_CLASS_AS_FLAGS(v)          (((duk_uint_t) (v)) << DUK_HOBJECT_FLAG_CLASS_BASE)
6107 
6108 /* E5 Section 8.6.2 + custom classes */
6109 #define DUK_HOBJECT_CLASS_NONE                 0
6110 #define DUK_HOBJECT_CLASS_OBJECT               1
6111 #define DUK_HOBJECT_CLASS_ARRAY                2
6112 #define DUK_HOBJECT_CLASS_FUNCTION             3
6113 #define DUK_HOBJECT_CLASS_ARGUMENTS            4
6114 #define DUK_HOBJECT_CLASS_BOOLEAN              5
6115 #define DUK_HOBJECT_CLASS_DATE                 6
6116 #define DUK_HOBJECT_CLASS_ERROR                7
6117 #define DUK_HOBJECT_CLASS_JSON                 8
6118 #define DUK_HOBJECT_CLASS_MATH                 9
6119 #define DUK_HOBJECT_CLASS_NUMBER               10
6120 #define DUK_HOBJECT_CLASS_REGEXP               11
6121 #define DUK_HOBJECT_CLASS_STRING               12
6122 #define DUK_HOBJECT_CLASS_GLOBAL               13
6123 #define DUK_HOBJECT_CLASS_SYMBOL               14
6124 #define DUK_HOBJECT_CLASS_OBJENV               15  /* custom */
6125 #define DUK_HOBJECT_CLASS_DECENV               16  /* custom */
6126 #define DUK_HOBJECT_CLASS_POINTER              17  /* custom */
6127 #define DUK_HOBJECT_CLASS_THREAD               18  /* custom; implies DUK_HOBJECT_IS_THREAD */
6128 #define DUK_HOBJECT_CLASS_BUFOBJ_MIN           19
6129 #define DUK_HOBJECT_CLASS_ARRAYBUFFER          19  /* implies DUK_HOBJECT_IS_BUFOBJ */
6130 #define DUK_HOBJECT_CLASS_DATAVIEW             20
6131 #define DUK_HOBJECT_CLASS_INT8ARRAY            21
6132 #define DUK_HOBJECT_CLASS_UINT8ARRAY           22
6133 #define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY    23
6134 #define DUK_HOBJECT_CLASS_INT16ARRAY           24
6135 #define DUK_HOBJECT_CLASS_UINT16ARRAY          25
6136 #define DUK_HOBJECT_CLASS_INT32ARRAY           26
6137 #define DUK_HOBJECT_CLASS_UINT32ARRAY          27
6138 #define DUK_HOBJECT_CLASS_FLOAT32ARRAY         28
6139 #define DUK_HOBJECT_CLASS_FLOAT64ARRAY         29
6140 #define DUK_HOBJECT_CLASS_BUFOBJ_MAX           29
6141 #define DUK_HOBJECT_CLASS_MAX                  29
6142 
6143 /* Class masks. */
6144 #define DUK_HOBJECT_CMASK_ALL                  ((1UL << (DUK_HOBJECT_CLASS_MAX + 1)) - 1UL)
6145 #define DUK_HOBJECT_CMASK_NONE                 (1UL << DUK_HOBJECT_CLASS_NONE)
6146 #define DUK_HOBJECT_CMASK_ARGUMENTS            (1UL << DUK_HOBJECT_CLASS_ARGUMENTS)
6147 #define DUK_HOBJECT_CMASK_ARRAY                (1UL << DUK_HOBJECT_CLASS_ARRAY)
6148 #define DUK_HOBJECT_CMASK_BOOLEAN              (1UL << DUK_HOBJECT_CLASS_BOOLEAN)
6149 #define DUK_HOBJECT_CMASK_DATE                 (1UL << DUK_HOBJECT_CLASS_DATE)
6150 #define DUK_HOBJECT_CMASK_ERROR                (1UL << DUK_HOBJECT_CLASS_ERROR)
6151 #define DUK_HOBJECT_CMASK_FUNCTION             (1UL << DUK_HOBJECT_CLASS_FUNCTION)
6152 #define DUK_HOBJECT_CMASK_JSON                 (1UL << DUK_HOBJECT_CLASS_JSON)
6153 #define DUK_HOBJECT_CMASK_MATH                 (1UL << DUK_HOBJECT_CLASS_MATH)
6154 #define DUK_HOBJECT_CMASK_NUMBER               (1UL << DUK_HOBJECT_CLASS_NUMBER)
6155 #define DUK_HOBJECT_CMASK_OBJECT               (1UL << DUK_HOBJECT_CLASS_OBJECT)
6156 #define DUK_HOBJECT_CMASK_REGEXP               (1UL << DUK_HOBJECT_CLASS_REGEXP)
6157 #define DUK_HOBJECT_CMASK_STRING               (1UL << DUK_HOBJECT_CLASS_STRING)
6158 #define DUK_HOBJECT_CMASK_GLOBAL               (1UL << DUK_HOBJECT_CLASS_GLOBAL)
6159 #define DUK_HOBJECT_CMASK_SYMBOL               (1UL << DUK_HOBJECT_CLASS_SYMBOL)
6160 #define DUK_HOBJECT_CMASK_OBJENV               (1UL << DUK_HOBJECT_CLASS_OBJENV)
6161 #define DUK_HOBJECT_CMASK_DECENV               (1UL << DUK_HOBJECT_CLASS_DECENV)
6162 #define DUK_HOBJECT_CMASK_POINTER              (1UL << DUK_HOBJECT_CLASS_POINTER)
6163 #define DUK_HOBJECT_CMASK_ARRAYBUFFER          (1UL << DUK_HOBJECT_CLASS_ARRAYBUFFER)
6164 #define DUK_HOBJECT_CMASK_DATAVIEW             (1UL << DUK_HOBJECT_CLASS_DATAVIEW)
6165 #define DUK_HOBJECT_CMASK_INT8ARRAY            (1UL << DUK_HOBJECT_CLASS_INT8ARRAY)
6166 #define DUK_HOBJECT_CMASK_UINT8ARRAY           (1UL << DUK_HOBJECT_CLASS_UINT8ARRAY)
6167 #define DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY    (1UL << DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY)
6168 #define DUK_HOBJECT_CMASK_INT16ARRAY           (1UL << DUK_HOBJECT_CLASS_INT16ARRAY)
6169 #define DUK_HOBJECT_CMASK_UINT16ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT16ARRAY)
6170 #define DUK_HOBJECT_CMASK_INT32ARRAY           (1UL << DUK_HOBJECT_CLASS_INT32ARRAY)
6171 #define DUK_HOBJECT_CMASK_UINT32ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT32ARRAY)
6172 #define DUK_HOBJECT_CMASK_FLOAT32ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT32ARRAY)
6173 #define DUK_HOBJECT_CMASK_FLOAT64ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT64ARRAY)
6174 
6175 #define DUK_HOBJECT_CMASK_ALL_BUFOBJS \
6176 	(DUK_HOBJECT_CMASK_ARRAYBUFFER | \
6177 	 DUK_HOBJECT_CMASK_DATAVIEW | \
6178 	 DUK_HOBJECT_CMASK_INT8ARRAY | \
6179 	 DUK_HOBJECT_CMASK_UINT8ARRAY | \
6180 	 DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY | \
6181 	 DUK_HOBJECT_CMASK_INT16ARRAY | \
6182 	 DUK_HOBJECT_CMASK_UINT16ARRAY | \
6183 	 DUK_HOBJECT_CMASK_INT32ARRAY | \
6184 	 DUK_HOBJECT_CMASK_UINT32ARRAY | \
6185 	 DUK_HOBJECT_CMASK_FLOAT32ARRAY | \
6186 	 DUK_HOBJECT_CMASK_FLOAT64ARRAY)
6187 
6188 #define DUK_HOBJECT_IS_OBJENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_OBJENV)
6189 #define DUK_HOBJECT_IS_DECENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DECENV)
6190 #define DUK_HOBJECT_IS_ENV(h)                  (DUK_HOBJECT_IS_OBJENV((h)) || DUK_HOBJECT_IS_DECENV((h)))
6191 #define DUK_HOBJECT_IS_ARRAY(h)                DUK_HOBJECT_HAS_EXOTIC_ARRAY((h))  /* Rely on class Array <=> exotic Array */
6192 #define DUK_HOBJECT_IS_BOUNDFUNC(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6193 #define DUK_HOBJECT_IS_COMPFUNC(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6194 #define DUK_HOBJECT_IS_NATFUNC(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6195 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6196 #define DUK_HOBJECT_IS_BUFOBJ(h)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6197 #else
6198 #define DUK_HOBJECT_IS_BUFOBJ(h)               0
6199 #endif
6200 #define DUK_HOBJECT_IS_THREAD(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_THREAD)
6201 #if defined(DUK_USE_ES6_PROXY)
6202 #define DUK_HOBJECT_IS_PROXY(h)                DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((h))
6203 #else
6204 #define DUK_HOBJECT_IS_PROXY(h)                0
6205 #endif
6206 
6207 #define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
6208                                                         DUK_HOBJECT_FLAG_COMPFUNC | \
6209                                                         DUK_HOBJECT_FLAG_NATFUNC)
6210 
6211 #define DUK_HOBJECT_IS_FUNCTION(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
6212                                                         DUK_HOBJECT_FLAG_BOUNDFUNC | \
6213                                                         DUK_HOBJECT_FLAG_COMPFUNC | \
6214                                                         DUK_HOBJECT_FLAG_NATFUNC)
6215 
6216 #define DUK_HOBJECT_IS_CALLABLE(h)             DUK_HOBJECT_HAS_CALLABLE((h))
6217 
6218 /* Object has any exotic behavior(s). */
6219 #define DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS      (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
6220                                                 DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS | \
6221                                                 DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
6222                                                 DUK_HOBJECT_FLAG_BUFOBJ | \
6223                                                 DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6224 #define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS)
6225 
6226 /* Object has any virtual properties (not counting Proxy behavior). */
6227 #define DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS     (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
6228                                                 DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
6229                                                 DUK_HOBJECT_FLAG_BUFOBJ)
6230 #define DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(h)  DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS)
6231 
6232 #define DUK_HOBJECT_HAS_EXTENSIBLE(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
6233 #define DUK_HOBJECT_HAS_CONSTRUCTABLE(h)       DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
6234 #define DUK_HOBJECT_HAS_CALLABLE(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
6235 #define DUK_HOBJECT_HAS_BOUNDFUNC(h)           DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6236 #define DUK_HOBJECT_HAS_COMPFUNC(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6237 #define DUK_HOBJECT_HAS_NATFUNC(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6238 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6239 #define DUK_HOBJECT_HAS_BUFOBJ(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6240 #else
6241 #define DUK_HOBJECT_HAS_BUFOBJ(h)              0
6242 #endif
6243 #define DUK_HOBJECT_HAS_FASTREFS(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
6244 #define DUK_HOBJECT_HAS_ARRAY_PART(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
6245 #define DUK_HOBJECT_HAS_STRICT(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
6246 #define DUK_HOBJECT_HAS_NOTAIL(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
6247 #define DUK_HOBJECT_HAS_NEWENV(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
6248 #define DUK_HOBJECT_HAS_NAMEBINDING(h)         DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
6249 #define DUK_HOBJECT_HAS_CREATEARGS(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
6250 #define DUK_HOBJECT_HAS_HAVE_FINALIZER(h)      DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
6251 #define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
6252 #define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
6253 #define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
6254 #if defined(DUK_USE_ES6_PROXY)
6255 #define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6256 #else
6257 #define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)     0
6258 #endif
6259 #define DUK_HOBJECT_HAS_SPECIAL_CALL(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
6260 
6261 #define DUK_HOBJECT_SET_EXTENSIBLE(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
6262 #define DUK_HOBJECT_SET_CONSTRUCTABLE(h)       DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
6263 #define DUK_HOBJECT_SET_CALLABLE(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
6264 #define DUK_HOBJECT_SET_BOUNDFUNC(h)           DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6265 #define DUK_HOBJECT_SET_COMPFUNC(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6266 #define DUK_HOBJECT_SET_NATFUNC(h)             DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6267 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6268 #define DUK_HOBJECT_SET_BUFOBJ(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6269 #endif
6270 #define DUK_HOBJECT_SET_FASTREFS(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
6271 #define DUK_HOBJECT_SET_ARRAY_PART(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
6272 #define DUK_HOBJECT_SET_STRICT(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
6273 #define DUK_HOBJECT_SET_NOTAIL(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
6274 #define DUK_HOBJECT_SET_NEWENV(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
6275 #define DUK_HOBJECT_SET_NAMEBINDING(h)         DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
6276 #define DUK_HOBJECT_SET_CREATEARGS(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
6277 #define DUK_HOBJECT_SET_HAVE_FINALIZER(h)      DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
6278 #define DUK_HOBJECT_SET_EXOTIC_ARRAY(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
6279 #define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
6280 #define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
6281 #if defined(DUK_USE_ES6_PROXY)
6282 #define DUK_HOBJECT_SET_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6283 #endif
6284 #define DUK_HOBJECT_SET_SPECIAL_CALL(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
6285 
6286 #define DUK_HOBJECT_CLEAR_EXTENSIBLE(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
6287 #define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
6288 #define DUK_HOBJECT_CLEAR_CALLABLE(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
6289 #define DUK_HOBJECT_CLEAR_BOUNDFUNC(h)         DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6290 #define DUK_HOBJECT_CLEAR_COMPFUNC(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6291 #define DUK_HOBJECT_CLEAR_NATFUNC(h)           DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6292 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6293 #define DUK_HOBJECT_CLEAR_BUFOBJ(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6294 #endif
6295 #define DUK_HOBJECT_CLEAR_FASTREFS(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
6296 #define DUK_HOBJECT_CLEAR_ARRAY_PART(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
6297 #define DUK_HOBJECT_CLEAR_STRICT(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
6298 #define DUK_HOBJECT_CLEAR_NOTAIL(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
6299 #define DUK_HOBJECT_CLEAR_NEWENV(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
6300 #define DUK_HOBJECT_CLEAR_NAMEBINDING(h)       DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
6301 #define DUK_HOBJECT_CLEAR_CREATEARGS(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
6302 #define DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
6303 #define DUK_HOBJECT_CLEAR_EXOTIC_ARRAY(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
6304 #define DUK_HOBJECT_CLEAR_EXOTIC_STRINGOBJ(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
6305 #define DUK_HOBJECT_CLEAR_EXOTIC_ARGUMENTS(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
6306 #if defined(DUK_USE_ES6_PROXY)
6307 #define DUK_HOBJECT_CLEAR_EXOTIC_PROXYOBJ(h)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6308 #endif
6309 #define DUK_HOBJECT_CLEAR_SPECIAL_CALL(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
6310 
6311 /* Object can/cannot use FASTREFS, i.e. has no strong reference fields beyond
6312  * duk_hobject base header.  This is used just for asserts so doesn't need to
6313  * be optimized.
6314  */
6315 #define DUK_HOBJECT_PROHIBITS_FASTREFS(h) \
6316 	(DUK_HOBJECT_IS_COMPFUNC((h)) || DUK_HOBJECT_IS_DECENV((h)) || DUK_HOBJECT_IS_OBJENV((h)) || \
6317 	 DUK_HOBJECT_IS_BUFOBJ((h)) || DUK_HOBJECT_IS_THREAD((h)) || DUK_HOBJECT_IS_PROXY((h)) || \
6318 	 DUK_HOBJECT_IS_BOUNDFUNC((h)))
6319 #define DUK_HOBJECT_ALLOWS_FASTREFS(h) (!DUK_HOBJECT_PROHIBITS_FASTREFS((h)))
6320 
6321 /* Flags used for property attributes in duk_propdesc and packed flags.
6322  * Must fit into 8 bits.
6323  */
6324 #define DUK_PROPDESC_FLAG_WRITABLE              (1U << 0)    /* E5 Section 8.6.1 */
6325 #define DUK_PROPDESC_FLAG_ENUMERABLE            (1U << 1)    /* E5 Section 8.6.1 */
6326 #define DUK_PROPDESC_FLAG_CONFIGURABLE          (1U << 2)    /* E5 Section 8.6.1 */
6327 #define DUK_PROPDESC_FLAG_ACCESSOR              (1U << 3)    /* accessor */
6328 #define DUK_PROPDESC_FLAG_VIRTUAL               (1U << 4)    /* property is virtual: used in duk_propdesc, never stored
6329                                                              * (used by e.g. buffer virtual properties)
6330                                                              */
6331 #define DUK_PROPDESC_FLAGS_MASK                 (DUK_PROPDESC_FLAG_WRITABLE | \
6332                                                  DUK_PROPDESC_FLAG_ENUMERABLE | \
6333                                                  DUK_PROPDESC_FLAG_CONFIGURABLE | \
6334                                                  DUK_PROPDESC_FLAG_ACCESSOR)
6335 
6336 /* Additional flags which are passed in the same flags argument as property
6337  * flags but are not stored in object properties.
6338  */
6339 #define DUK_PROPDESC_FLAG_NO_OVERWRITE          (1U << 4)    /* internal define property: skip write silently if exists */
6340 
6341 /* Convenience defines for property attributes. */
6342 #define DUK_PROPDESC_FLAGS_NONE                 0
6343 #define DUK_PROPDESC_FLAGS_W                    (DUK_PROPDESC_FLAG_WRITABLE)
6344 #define DUK_PROPDESC_FLAGS_E                    (DUK_PROPDESC_FLAG_ENUMERABLE)
6345 #define DUK_PROPDESC_FLAGS_C                    (DUK_PROPDESC_FLAG_CONFIGURABLE)
6346 #define DUK_PROPDESC_FLAGS_WE                   (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE)
6347 #define DUK_PROPDESC_FLAGS_WC                   (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
6348 #define DUK_PROPDESC_FLAGS_EC                   (DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
6349 #define DUK_PROPDESC_FLAGS_WEC                  (DUK_PROPDESC_FLAG_WRITABLE | \
6350                                                  DUK_PROPDESC_FLAG_ENUMERABLE | \
6351                                                  DUK_PROPDESC_FLAG_CONFIGURABLE)
6352 
6353 /* Flags for duk_hobject_get_own_propdesc() and variants. */
6354 #define DUK_GETDESC_FLAG_PUSH_VALUE          (1U << 0)  /* push value to stack */
6355 #define DUK_GETDESC_FLAG_IGNORE_PROTOLOOP    (1U << 1)  /* don't throw for prototype loop */
6356 
6357 /*
6358  *  Macro for object validity check
6359  *
6360  *  Assert for currently guaranteed relations between flags, for instance.
6361  */
6362 
6363 #if defined(DUK_USE_ASSERTIONS)
6364 DUK_INTERNAL_DECL void duk_hobject_assert_valid(duk_hobject *h);
6365 #define DUK_HOBJECT_ASSERT_VALID(h)  do { duk_hobject_assert_valid((h)); } while (0)
6366 #else
6367 #define DUK_HOBJECT_ASSERT_VALID(h)  do {} while (0)
6368 #endif
6369 
6370 /*
6371  *  Macros to access the 'props' allocation.
6372  */
6373 
6374 #if defined(DUK_USE_HEAPPTR16)
6375 #define DUK_HOBJECT_GET_PROPS(heap,h) \
6376 	((duk_uint8_t *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (h))->h_extra16))
6377 #define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
6378 		((duk_heaphdr *) (h))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
6379 	} while (0)
6380 #else
6381 #define DUK_HOBJECT_GET_PROPS(heap,h) \
6382 	((h)->props)
6383 #define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
6384 		(h)->props = (duk_uint8_t *) (x); \
6385 	} while (0)
6386 #endif
6387 
6388 #if defined(DUK_USE_HOBJECT_LAYOUT_1)
6389 /* LAYOUT 1 */
6390 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
6391 	((duk_hstring **) (void *) ( \
6392 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
6393 	))
6394 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
6395 	((duk_propvalue *) (void *) ( \
6396 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6397 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_hstring *) \
6398 	))
6399 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
6400 	((duk_uint8_t *) (void *) ( \
6401 		DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
6402 	))
6403 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
6404 	((duk_tval *) (void *) ( \
6405 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6406 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) \
6407 	))
6408 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
6409 	((duk_uint32_t *) (void *) ( \
6410 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6411 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6412 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6413 	))
6414 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
6415 	( \
6416 		(n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6417 		(n_arr) * sizeof(duk_tval) + \
6418 		(n_hash) * sizeof(duk_uint32_t) \
6419 	)
6420 #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 { \
6421 		(set_e_k) = (duk_hstring **) (void *) (p_base); \
6422 		(set_e_pv) = (duk_propvalue *) (void *) ((set_e_k) + (n_ent)); \
6423 		(set_e_f) = (duk_uint8_t *) (void *) ((set_e_pv) + (n_ent)); \
6424 		(set_a) = (duk_tval *) (void *) ((set_e_f) + (n_ent)); \
6425 		(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
6426 	} while (0)
6427 #elif defined(DUK_USE_HOBJECT_LAYOUT_2)
6428 /* LAYOUT 2 */
6429 #if (DUK_USE_ALIGN_BY == 4)
6430 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((4 - (e_sz)) & 0x03)
6431 #elif (DUK_USE_ALIGN_BY == 8)
6432 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((8 - (e_sz)) & 0x07)
6433 #elif (DUK_USE_ALIGN_BY == 1)
6434 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) 0
6435 #else
6436 #error invalid DUK_USE_ALIGN_BY
6437 #endif
6438 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
6439 	((duk_hstring **) (void *) ( \
6440 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6441 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
6442 	))
6443 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
6444 	((duk_propvalue *) (void *) ( \
6445 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
6446 	))
6447 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
6448 	((duk_uint8_t *) (void *) ( \
6449 		DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
6450 	))
6451 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
6452 	((duk_tval *) (void *) ( \
6453 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6454 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6455 			DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) \
6456 	))
6457 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
6458 	((duk_uint32_t *) (void *) ( \
6459 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6460 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6461 			DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) + \
6462 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6463 	))
6464 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
6465 	( \
6466 		(n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6467 		DUK_HOBJECT_E_FLAG_PADDING((n_ent)) + \
6468 		(n_arr) * sizeof(duk_tval) + \
6469 		(n_hash) * sizeof(duk_uint32_t) \
6470 	)
6471 #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 { \
6472 		(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
6473 		(set_e_k) = (duk_hstring **) (void *) ((set_e_pv) + (n_ent)); \
6474 		(set_e_f) = (duk_uint8_t *) (void *) ((set_e_k) + (n_ent)); \
6475 		(set_a) = (duk_tval *) (void *) (((duk_uint8_t *) (set_e_f)) + \
6476 		                                 sizeof(duk_uint8_t) * (n_ent) + \
6477 		                                 DUK_HOBJECT_E_FLAG_PADDING((n_ent))); \
6478 		(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
6479 	} while (0)
6480 #elif defined(DUK_USE_HOBJECT_LAYOUT_3)
6481 /* LAYOUT 3 */
6482 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
6483 	((duk_hstring **) (void *) ( \
6484 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6485 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) + \
6486 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6487 	))
6488 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
6489 	((duk_propvalue *) (void *) ( \
6490 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
6491 	))
6492 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
6493 	((duk_uint8_t *) (void *) ( \
6494 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6495 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
6496 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) + \
6497 			DUK_HOBJECT_GET_HSIZE((h)) * sizeof(duk_uint32_t) \
6498 	))
6499 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
6500 	((duk_tval *) (void *) ( \
6501 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6502 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
6503 	))
6504 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
6505 	((duk_uint32_t *) (void *) ( \
6506 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6507 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
6508 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6509 	))
6510 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
6511 	( \
6512 		(n_ent) * (sizeof(duk_propvalue) + sizeof(duk_hstring *) + sizeof(duk_uint8_t)) + \
6513 		(n_arr) * sizeof(duk_tval) + \
6514 		(n_hash) * sizeof(duk_uint32_t) \
6515 	)
6516 #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 { \
6517 		(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
6518 		(set_a) = (duk_tval *) (void *) ((set_e_pv) + (n_ent)); \
6519 		(set_e_k) = (duk_hstring **) (void *) ((set_a) + (n_arr)); \
6520 		(set_h) = (duk_uint32_t *) (void *) ((set_e_k) + (n_ent)); \
6521 		(set_e_f) = (duk_uint8_t *) (void *) ((set_h) + (n_hash)); \
6522 	} while (0)
6523 #else
6524 #error invalid hobject layout defines
6525 #endif  /* hobject property layout */
6526 
6527 #define DUK_HOBJECT_P_ALLOC_SIZE(h) \
6528 	DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE((h)), DUK_HOBJECT_GET_ASIZE((h)), DUK_HOBJECT_GET_HSIZE((h)))
6529 
6530 #define DUK_HOBJECT_E_GET_KEY(heap,h,i)              (DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
6531 #define DUK_HOBJECT_E_GET_KEY_PTR(heap,h,i)          (&DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
6532 #define DUK_HOBJECT_E_GET_VALUE(heap,h,i)            (DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
6533 #define DUK_HOBJECT_E_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
6534 #define DUK_HOBJECT_E_GET_VALUE_TVAL(heap,h,i)       (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
6535 #define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap,h,i)   (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
6536 #define DUK_HOBJECT_E_GET_VALUE_GETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
6537 #define DUK_HOBJECT_E_GET_VALUE_GETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
6538 #define DUK_HOBJECT_E_GET_VALUE_SETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
6539 #define DUK_HOBJECT_E_GET_VALUE_SETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
6540 #define DUK_HOBJECT_E_GET_FLAGS(heap,h,i)            (DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
6541 #define DUK_HOBJECT_E_GET_FLAGS_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
6542 #define DUK_HOBJECT_A_GET_VALUE(heap,h,i)            (DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
6543 #define DUK_HOBJECT_A_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
6544 #define DUK_HOBJECT_H_GET_INDEX(heap,h,i)            (DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
6545 #define DUK_HOBJECT_H_GET_INDEX_PTR(heap,h,i)        (&DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
6546 
6547 #define DUK_HOBJECT_E_SET_KEY(heap,h,i,k)  do { \
6548 		DUK_HOBJECT_E_GET_KEY((heap), (h), (i)) = (k); \
6549 	} while (0)
6550 #define DUK_HOBJECT_E_SET_VALUE(heap,h,i,v)  do { \
6551 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)) = (v); \
6552 	} while (0)
6553 #define DUK_HOBJECT_E_SET_VALUE_TVAL(heap,h,i,v)  do { \
6554 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v = (v); \
6555 	} while (0)
6556 #define DUK_HOBJECT_E_SET_VALUE_GETTER(heap,h,i,v)  do { \
6557 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get = (v); \
6558 	} while (0)
6559 #define DUK_HOBJECT_E_SET_VALUE_SETTER(heap,h,i,v)  do { \
6560 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set = (v); \
6561 	} while (0)
6562 #define DUK_HOBJECT_E_SET_FLAGS(heap,h,i,f)  do { \
6563 		DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) = (duk_uint8_t) (f); \
6564 	} while (0)
6565 #define DUK_HOBJECT_A_SET_VALUE(heap,h,i,v)  do { \
6566 		DUK_HOBJECT_A_GET_VALUE((heap), (h), (i)) = (v); \
6567 	} while (0)
6568 #define DUK_HOBJECT_A_SET_VALUE_TVAL(heap,h,i,v) \
6569 	DUK_HOBJECT_A_SET_VALUE((heap), (h), (i), (v))  /* alias for above */
6570 #define DUK_HOBJECT_H_SET_INDEX(heap,h,i,v)  do { \
6571 		DUK_HOBJECT_H_GET_INDEX((heap), (h), (i)) = (v); \
6572 	} while (0)
6573 
6574 #define DUK_HOBJECT_E_SET_FLAG_BITS(heap,h,i,mask)  do { \
6575 		DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] |= (mask); \
6576 	} while (0)
6577 
6578 #define DUK_HOBJECT_E_CLEAR_FLAG_BITS(heap,h,i,mask)  do { \
6579 		DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] &= ~(mask); \
6580 	} while (0)
6581 
6582 #define DUK_HOBJECT_E_SLOT_IS_WRITABLE(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_WRITABLE) != 0)
6583 #define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap,h,i)   ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
6584 #define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
6585 #define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
6586 
6587 #define DUK_HOBJECT_E_SLOT_SET_WRITABLE(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
6588 #define DUK_HOBJECT_E_SLOT_SET_ENUMERABLE(heap,h,i)      DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
6589 #define DUK_HOBJECT_E_SLOT_SET_CONFIGURABLE(heap,h,i)    DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
6590 #define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
6591 
6592 #define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
6593 #define DUK_HOBJECT_E_SLOT_CLEAR_ENUMERABLE(heap,h,i)    DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
6594 #define DUK_HOBJECT_E_SLOT_CLEAR_CONFIGURABLE(heap,h,i)  DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
6595 #define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
6596 
6597 #define DUK_PROPDESC_IS_WRITABLE(p)             (((p)->flags & DUK_PROPDESC_FLAG_WRITABLE) != 0)
6598 #define DUK_PROPDESC_IS_ENUMERABLE(p)           (((p)->flags & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
6599 #define DUK_PROPDESC_IS_CONFIGURABLE(p)         (((p)->flags & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
6600 #define DUK_PROPDESC_IS_ACCESSOR(p)             (((p)->flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
6601 
6602 #define DUK_HOBJECT_HASHIDX_UNUSED              0xffffffffUL
6603 #define DUK_HOBJECT_HASHIDX_DELETED             0xfffffffeUL
6604 
6605 /*
6606  *  Macros for accessing size fields
6607  */
6608 
6609 #if defined(DUK_USE_OBJSIZES16)
6610 #define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size16)
6611 #define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size16 = (v); } while (0)
6612 #define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next16)
6613 #define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next16 = (v); } while (0)
6614 #define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next16++)
6615 #define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size16)
6616 #define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size16 = (v); } while (0)
6617 #if defined(DUK_USE_HOBJECT_HASH_PART)
6618 #define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size16)
6619 #define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size16 = (v); } while (0)
6620 #else
6621 #define DUK_HOBJECT_GET_HSIZE(h) 0
6622 #define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
6623 #endif
6624 #else
6625 #define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size)
6626 #define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size = (v); } while (0)
6627 #define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next)
6628 #define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next = (v); } while (0)
6629 #define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next++)
6630 #define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size)
6631 #define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size = (v); } while (0)
6632 #if defined(DUK_USE_HOBJECT_HASH_PART)
6633 #define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size)
6634 #define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size = (v); } while (0)
6635 #else
6636 #define DUK_HOBJECT_GET_HSIZE(h) 0
6637 #define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
6638 #endif
6639 #endif
6640 
6641 /*
6642  *  Misc
6643  */
6644 
6645 /* Maximum prototype traversal depth.  Sanity limit which handles e.g.
6646  * prototype loops (even complex ones like 1->2->3->4->2->3->4->2->3->4).
6647  */
6648 #define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY      10000L
6649 
6650 /*
6651  *  ECMAScript [[Class]]
6652  */
6653 
6654 /* range check not necessary because all 4-bit values are mapped */
6655 #define DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(n)  duk_class_number_to_stridx[(n)]
6656 
6657 #define DUK_HOBJECT_GET_CLASS_STRING(heap,h)          \
6658 	DUK_HEAP_GET_STRING( \
6659 		(heap), \
6660 		DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(DUK_HOBJECT_GET_CLASS_NUMBER((h))) \
6661 	)
6662 
6663 /*
6664  *  Macros for property handling
6665  */
6666 
6667 #if defined(DUK_USE_HEAPPTR16)
6668 #define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
6669 	((duk_hobject *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->prototype16))
6670 #define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
6671 		(h)->prototype16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
6672 	} while (0)
6673 #else
6674 #define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
6675 	((h)->prototype)
6676 #define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
6677 		(h)->prototype = (x); \
6678 	} while (0)
6679 #endif
6680 
6681 /* Set prototype, DECREF earlier value, INCREF new value (tolerating NULLs). */
6682 #define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr,h,p)       duk_hobject_set_prototype_updref((thr), (h), (p))
6683 
6684 /* Set initial prototype, assume NULL previous prototype, INCREF new value,
6685  * tolerate NULL.
6686  */
6687 #define DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr,h,proto) do { \
6688 		duk_hthread *duk__thr = (thr); \
6689 		duk_hobject *duk__obj = (h); \
6690 		duk_hobject *duk__proto = (proto); \
6691 		DUK_UNREF(duk__thr); \
6692 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(duk__thr->heap, duk__obj) == NULL); \
6693 		DUK_HOBJECT_SET_PROTOTYPE(duk__thr->heap, duk__obj, duk__proto); \
6694 		DUK_HOBJECT_INCREF_ALLOWNULL(duk__thr, duk__proto); \
6695 	} while (0)
6696 
6697 /*
6698  *  Finalizer check
6699  */
6700 
6701 #if defined(DUK_USE_HEAPPTR16)
6702 #define DUK_HOBJECT_HAS_FINALIZER_FAST(heap,h) duk_hobject_has_finalizer_fast_raw((heap), (h))
6703 #else
6704 #define DUK_HOBJECT_HAS_FINALIZER_FAST(heap,h) duk_hobject_has_finalizer_fast_raw((h))
6705 #endif
6706 
6707 /*
6708  *  Resizing and hash behavior
6709  */
6710 
6711 /* Sanity limit on max number of properties (allocated, not necessarily used).
6712  * This is somewhat arbitrary, but if we're close to 2**32 properties some
6713  * algorithms will fail (e.g. hash size selection, next prime selection).
6714  * Also, we use negative array/entry table indices to indicate 'not found',
6715  * so anything above 0x80000000 will cause trouble now.
6716  */
6717 #if defined(DUK_USE_OBJSIZES16)
6718 #define DUK_HOBJECT_MAX_PROPERTIES       0x0000ffffUL
6719 #else
6720 #define DUK_HOBJECT_MAX_PROPERTIES       0x3fffffffUL   /* 2**30-1 ~= 1G properties */
6721 #endif
6722 
6723 /* internal align target for props allocation, must be 2*n for some n */
6724 #if (DUK_USE_ALIGN_BY == 4)
6725 #define DUK_HOBJECT_ALIGN_TARGET         4
6726 #elif (DUK_USE_ALIGN_BY == 8)
6727 #define DUK_HOBJECT_ALIGN_TARGET         8
6728 #elif (DUK_USE_ALIGN_BY == 1)
6729 #define DUK_HOBJECT_ALIGN_TARGET         1
6730 #else
6731 #error invalid DUK_USE_ALIGN_BY
6732 #endif
6733 
6734 /*
6735  *  PC-to-line constants
6736  */
6737 
6738 #define DUK_PC2LINE_SKIP    64
6739 
6740 /* maximum length for a SKIP-1 diffstream: 35 bits per entry, rounded up to bytes */
6741 #define DUK_PC2LINE_MAX_DIFF_LENGTH    (((DUK_PC2LINE_SKIP - 1) * 35 + 7) / 8)
6742 
6743 /*
6744  *  Struct defs
6745  */
6746 
6747 struct duk_propaccessor {
6748 	duk_hobject *get;
6749 	duk_hobject *set;
6750 };
6751 
6752 union duk_propvalue {
6753 	/* The get/set pointers could be 16-bit pointer compressed but it
6754 	 * would make no difference on 32-bit platforms because duk_tval is
6755 	 * 8 bytes or more anyway.
6756 	 */
6757 	duk_tval v;
6758 	duk_propaccessor a;
6759 };
6760 
6761 struct duk_propdesc {
6762 	/* read-only values 'lifted' for ease of use */
6763 	duk_small_uint_t flags;
6764 	duk_hobject *get;
6765 	duk_hobject *set;
6766 
6767 	/* for updating (all are set to < 0 for virtual properties) */
6768 	duk_int_t e_idx;  /* prop index in 'entry part', < 0 if not there */
6769 	duk_int_t h_idx;  /* prop index in 'hash part', < 0 if not there */
6770 	duk_int_t a_idx;  /* prop index in 'array part', < 0 if not there */
6771 };
6772 
6773 struct duk_hobject {
6774 	duk_heaphdr hdr;
6775 
6776 	/*
6777 	 *  'props' contains {key,value,flags} entries, optional array entries, and
6778 	 *  an optional hash lookup table for non-array entries in a single 'sliced'
6779 	 *  allocation.  There are several layout options, which differ slightly in
6780 	 *  generated code size/speed and alignment/padding; duk_features.h selects
6781 	 *  the layout used.
6782 	 *
6783 	 *  Layout 1 (DUK_USE_HOBJECT_LAYOUT_1):
6784 	 *
6785 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
6786 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
6787 	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)
6788 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
6789 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
6790 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
6791 	 *
6792 	 *  Layout 2 (DUK_USE_HOBJECT_LAYOUT_2):
6793 	 *
6794 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
6795 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
6796 	 *    e_size * sizeof(duk_uint8_t) + pad     bytes of   entry flags (e_next gc reachable)
6797 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
6798 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
6799 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
6800 	 *
6801 	 *  Layout 3 (DUK_USE_HOBJECT_LAYOUT_3):
6802 	 *
6803 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
6804 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
6805 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
6806 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
6807 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
6808 	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)
6809 	 *
6810 	 *  In layout 1, the 'e_next' count is rounded to 4 or 8 on platforms
6811 	 *  requiring 4 or 8 byte alignment.  This ensures proper alignment
6812 	 *  for the entries, at the cost of memory footprint.  However, it's
6813 	 *  probably preferable to use another layout on such platforms instead.
6814 	 *
6815 	 *  In layout 2, the key and value parts are swapped to avoid padding
6816 	 *  the key array on platforms requiring alignment by 8.  The flags part
6817 	 *  is padded to get alignment for array entries.  The 'e_next' count does
6818 	 *  not need to be rounded as in layout 1.
6819 	 *
6820 	 *  In layout 3, entry values and array values are always aligned properly,
6821 	 *  and assuming pointers are at most 8 bytes, so are the entry keys.  Hash
6822 	 *  indices will be properly aligned (assuming pointers are at least 4 bytes).
6823 	 *  Finally, flags don't need additional alignment.  This layout provides
6824 	 *  compact allocations without padding (even on platforms with alignment
6825 	 *  requirements) at the cost of a bit slower lookups.
6826 	 *
6827 	 *  Objects with few keys don't have a hash index; keys are looked up linearly,
6828 	 *  which is cache efficient because the keys are consecutive.  Larger objects
6829 	 *  have a hash index part which contains integer indexes to the entries part.
6830 	 *
6831 	 *  A single allocation reduces memory allocation overhead but requires more
6832 	 *  work when any part needs to be resized.  A sliced allocation for entries
6833 	 *  makes linear key matching faster on most platforms (more locality) and
6834 	 *  skimps on flags size (which would be followed by 3 bytes of padding in
6835 	 *  most architectures if entries were placed in a struct).
6836 	 *
6837 	 *  'props' also contains internal properties distinguished with a non-BMP
6838 	 *  prefix.  Often used properties should be placed early in 'props' whenever
6839 	 *  possible to make accessing them as fast a possible.
6840 	 */
6841 
6842 #if defined(DUK_USE_HEAPPTR16)
6843 	/* Located in duk_heaphdr h_extra16.  Subclasses of duk_hobject (like
6844 	 * duk_hcompfunc) are not free to use h_extra16 for this reason.
6845 	 */
6846 #else
6847 	duk_uint8_t *props;
6848 #endif
6849 
6850 	/* prototype: the only internal property lifted outside 'e' as it is so central */
6851 #if defined(DUK_USE_HEAPPTR16)
6852 	duk_uint16_t prototype16;
6853 #else
6854 	duk_hobject *prototype;
6855 #endif
6856 
6857 #if defined(DUK_USE_OBJSIZES16)
6858 	duk_uint16_t e_size16;
6859 	duk_uint16_t e_next16;
6860 	duk_uint16_t a_size16;
6861 #if defined(DUK_USE_HOBJECT_HASH_PART)
6862 	duk_uint16_t h_size16;
6863 #endif
6864 #else
6865 	duk_uint32_t e_size;  /* entry part size */
6866 	duk_uint32_t e_next;  /* index for next new key ([0,e_next[ are gc reachable) */
6867 	duk_uint32_t a_size;  /* array part size (entirely gc reachable) */
6868 #if defined(DUK_USE_HOBJECT_HASH_PART)
6869 	duk_uint32_t h_size;  /* hash part size or 0 if unused */
6870 #endif
6871 #endif
6872 };
6873 
6874 /*
6875  *  Exposed data
6876  */
6877 
6878 #if !defined(DUK_SINGLE_FILE)
6879 DUK_INTERNAL_DECL duk_uint8_t duk_class_number_to_stridx[32];
6880 #endif  /* !DUK_SINGLE_FILE */
6881 
6882 /*
6883  *  Prototypes
6884  */
6885 
6886 /* alloc and init */
6887 DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags);
6888 DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6889 DUK_INTERNAL_DECL duk_harray *duk_harray_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6890 DUK_INTERNAL_DECL duk_hcompfunc *duk_hcompfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6891 DUK_INTERNAL_DECL duk_hnatfunc *duk_hnatfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6892 DUK_INTERNAL_DECL duk_hboundfunc *duk_hboundfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags);
6893 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6894 DUK_INTERNAL_DECL duk_hbufobj *duk_hbufobj_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6895 #endif
6896 DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags);
6897 DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6898 DUK_INTERNAL_DECL duk_hdecenv *duk_hdecenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6899 DUK_INTERNAL_DECL duk_hobjenv *duk_hobjenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6900 DUK_INTERNAL_DECL duk_hproxy *duk_hproxy_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6901 
6902 /* resize */
6903 DUK_INTERNAL_DECL void duk_hobject_realloc_props(duk_hthread *thr,
6904                                                  duk_hobject *obj,
6905                                                  duk_uint32_t new_e_size,
6906                                                  duk_uint32_t new_a_size,
6907                                                  duk_uint32_t new_h_size,
6908                                                  duk_bool_t abandon_array);
6909 DUK_INTERNAL_DECL void duk_hobject_resize_entrypart(duk_hthread *thr,
6910                                                     duk_hobject *obj,
6911                                                     duk_uint32_t new_e_size);
6912 #if 0  /*unused*/
6913 DUK_INTERNAL_DECL void duk_hobject_resize_arraypart(duk_hthread *thr,
6914                                                     duk_hobject *obj,
6915                                                     duk_uint32_t new_a_size);
6916 #endif
6917 
6918 /* low-level property functions */
6919 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);
6920 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key);
6921 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_entry_tval_ptr_stridx(duk_heap *heap, duk_hobject *obj, duk_small_uint_t stridx);
6922 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);
6923 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i);
6924 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);
6925 
6926 /* core property functions */
6927 DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
6928 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);
6929 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);
6930 DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
6931 
6932 /* internal property functions */
6933 #define DUK_DELPROP_FLAG_THROW  (1U << 0)
6934 #define DUK_DELPROP_FLAG_FORCE  (1U << 1)
6935 DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
6936 DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key);
6937 DUK_INTERNAL_DECL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
6938 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);
6939 DUK_INTERNAL_DECL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj);
6940 #if defined(DUK_USE_HEAPPTR16)
6941 DUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_heap *heap, duk_hobject *obj);
6942 #else
6943 DUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_hobject *obj);
6944 #endif
6945 
6946 /* helpers for defineProperty() and defineProperties() */
6947 DUK_INTERNAL_DECL void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
6948                                                                duk_idx_t idx_in,
6949                                                                duk_uint_t *out_defprop_flags,
6950                                                                duk_idx_t *out_idx_value,
6951                                                                duk_hobject **out_getter,
6952                                                                duk_hobject **out_setter);
6953 DUK_INTERNAL_DECL duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
6954                                                                 duk_uint_t defprop_flags,
6955                                                                 duk_hobject *obj,
6956                                                                 duk_hstring *key,
6957                                                                 duk_idx_t idx_value,
6958                                                                 duk_hobject *get,
6959                                                                 duk_hobject *set,
6960                                                                 duk_bool_t throw_flag);
6961 
6962 /* Object built-in methods */
6963 DUK_INTERNAL_DECL void duk_hobject_object_get_own_property_descriptor(duk_hthread *thr, duk_idx_t obj_idx);
6964 DUK_INTERNAL_DECL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze);
6965 DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen);
6966 DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_small_uint_t required_desc_flags);
6967 
6968 /* internal properties */
6969 DUK_INTERNAL_DECL duk_tval *duk_hobject_get_internal_value_tval_ptr(duk_heap *heap, duk_hobject *obj);
6970 DUK_INTERNAL_DECL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj);
6971 DUK_INTERNAL_DECL duk_harray *duk_hobject_get_formals(duk_hthread *thr, duk_hobject *obj);
6972 DUK_INTERNAL_DECL duk_hobject *duk_hobject_get_varmap(duk_hthread *thr, duk_hobject *obj);
6973 
6974 /* hobject management functions */
6975 DUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj);
6976 
6977 /* ES2015 proxy */
6978 #if defined(DUK_USE_ES6_PROXY)
6979 DUK_INTERNAL_DECL duk_bool_t duk_hobject_proxy_check(duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler);
6980 DUK_INTERNAL_DECL duk_hobject *duk_hobject_resolve_proxy_target(duk_hobject *obj);
6981 #endif
6982 
6983 /* enumeration */
6984 DUK_INTERNAL_DECL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint_t enum_flags);
6985 DUK_INTERNAL_DECL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_small_uint_t enum_flags);
6986 DUK_INTERNAL_DECL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t get_value);
6987 
6988 /* macros */
6989 DUK_INTERNAL_DECL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p);
6990 
6991 /* pc2line */
6992 #if defined(DUK_USE_PC2LINE)
6993 DUK_INTERNAL_DECL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length);
6994 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_idx_t idx_func, duk_uint_fast32_t pc);
6995 #endif
6996 
6997 /* misc */
6998 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);
6999 
7000 #if !defined(DUK_USE_OBJECT_BUILTIN)
7001 /* These declarations are needed when related built-in is disabled and
7002  * genbuiltins.py won't automatically emit the declerations.
7003  */
7004 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_hthread *thr);
7005 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_hthread *thr);
7006 #endif
7007 
7008 #endif  /* DUK_HOBJECT_H_INCLUDED */
7009 /* #include duk_hcompfunc.h */
7010 /*
7011  *  Heap compiled function (ECMAScript function) representation.
7012  *
7013  *  There is a single data buffer containing the ECMAScript function's
7014  *  bytecode, constants, and inner functions.
7015  */
7016 
7017 #if !defined(DUK_HCOMPFUNC_H_INCLUDED)
7018 #define DUK_HCOMPFUNC_H_INCLUDED
7019 
7020 /*
7021  *  Field accessor macros
7022  */
7023 
7024 /* XXX: casts could be improved, especially for GET/SET DATA */
7025 
7026 #if defined(DUK_USE_HEAPPTR16)
7027 #define DUK_HCOMPFUNC_GET_DATA(heap,h) \
7028 	((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16))
7029 #define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \
7030 		(h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7031 	} while (0)
7032 #define DUK_HCOMPFUNC_GET_FUNCS(heap,h)  \
7033 	((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16)))
7034 #define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v)  do { \
7035 		(h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7036 	} while (0)
7037 #define DUK_HCOMPFUNC_GET_BYTECODE(heap,h)  \
7038 	((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16)))
7039 #define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v)  do { \
7040 		(h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7041 	} while (0)
7042 #define DUK_HCOMPFUNC_GET_LEXENV(heap,h)  \
7043 	((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->lex_env16)))
7044 #define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v)  do { \
7045 		(h)->lex_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7046 	} while (0)
7047 #define DUK_HCOMPFUNC_GET_VARENV(heap,h)  \
7048 	((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->var_env16)))
7049 #define DUK_HCOMPFUNC_SET_VARENV(heap,h,v)  do { \
7050 		(h)->var_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7051 	} while (0)
7052 #else
7053 #define DUK_HCOMPFUNC_GET_DATA(heap,h)  ((duk_hbuffer_fixed *) (void *) (h)->data)
7054 #define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \
7055 		(h)->data = (duk_hbuffer *) (v); \
7056 	} while (0)
7057 #define DUK_HCOMPFUNC_GET_FUNCS(heap,h)  ((h)->funcs)
7058 #define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v)  do { \
7059 		(h)->funcs = (v); \
7060 	} while (0)
7061 #define DUK_HCOMPFUNC_GET_BYTECODE(heap,h)  ((h)->bytecode)
7062 #define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v)  do { \
7063 		(h)->bytecode = (v); \
7064 	} while (0)
7065 #define DUK_HCOMPFUNC_GET_LEXENV(heap,h)  ((h)->lex_env)
7066 #define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v)  do { \
7067 		(h)->lex_env = (v); \
7068 	} while (0)
7069 #define DUK_HCOMPFUNC_GET_VARENV(heap,h)  ((h)->var_env)
7070 #define DUK_HCOMPFUNC_SET_VARENV(heap,h,v)  do { \
7071 		(h)->var_env = (v); \
7072 	} while (0)
7073 #endif
7074 
7075 /*
7076  *  Accessor macros for function specific data areas
7077  */
7078 
7079 /* Note: assumes 'data' is always a fixed buffer */
7080 #define DUK_HCOMPFUNC_GET_BUFFER_BASE(heap,h)  \
7081 	DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h)))
7082 
7083 #define DUK_HCOMPFUNC_GET_CONSTS_BASE(heap,h)  \
7084 	((duk_tval *) (void *) DUK_HCOMPFUNC_GET_BUFFER_BASE((heap), (h)))
7085 
7086 #define DUK_HCOMPFUNC_GET_FUNCS_BASE(heap,h)  \
7087 	DUK_HCOMPFUNC_GET_FUNCS((heap), (h))
7088 
7089 #define DUK_HCOMPFUNC_GET_CODE_BASE(heap,h)  \
7090 	DUK_HCOMPFUNC_GET_BYTECODE((heap), (h))
7091 
7092 #define DUK_HCOMPFUNC_GET_CONSTS_END(heap,h)  \
7093 	((duk_tval *) (void *) DUK_HCOMPFUNC_GET_FUNCS((heap), (h)))
7094 
7095 #define DUK_HCOMPFUNC_GET_FUNCS_END(heap,h)  \
7096 	((duk_hobject **) (void *) DUK_HCOMPFUNC_GET_BYTECODE((heap), (h)))
7097 
7098 /* XXX: double evaluation of DUK_HCOMPFUNC_GET_DATA() */
7099 #define DUK_HCOMPFUNC_GET_CODE_END(heap,h)  \
7100 	((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h))) + \
7101 	                DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA((heap), h))))
7102 
7103 #define DUK_HCOMPFUNC_GET_CONSTS_SIZE(heap,h)  \
7104 	( \
7105 	 (duk_size_t) \
7106 	 ( \
7107 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_END((heap), (h))) - \
7108 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_BASE((heap), (h))) \
7109 	 ) \
7110 	)
7111 
7112 #define DUK_HCOMPFUNC_GET_FUNCS_SIZE(heap,h)  \
7113 	( \
7114 	 (duk_size_t) \
7115 	 ( \
7116 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_END((heap), (h))) - \
7117 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_BASE((heap), (h))) \
7118 	 ) \
7119 	)
7120 
7121 #define DUK_HCOMPFUNC_GET_CODE_SIZE(heap,h)  \
7122 	( \
7123 	 (duk_size_t) \
7124 	 ( \
7125 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_END((heap),(h))) - \
7126 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_BASE((heap),(h))) \
7127 	 ) \
7128 	)
7129 
7130 #define DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap,h)  \
7131 	((duk_size_t) (DUK_HCOMPFUNC_GET_CONSTS_SIZE((heap), (h)) / sizeof(duk_tval)))
7132 
7133 #define DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap,h)  \
7134 	((duk_size_t) (DUK_HCOMPFUNC_GET_FUNCS_SIZE((heap), (h)) / sizeof(duk_hobject *)))
7135 
7136 #define DUK_HCOMPFUNC_GET_CODE_COUNT(heap,h)  \
7137 	((duk_size_t) (DUK_HCOMPFUNC_GET_CODE_SIZE((heap), (h)) / sizeof(duk_instr_t)))
7138 
7139 /*
7140  *  Validity assert
7141  */
7142 
7143 #if defined(DUK_USE_ASSERTIONS)
7144 DUK_INTERNAL_DECL void duk_hcompfunc_assert_valid(duk_hcompfunc *h);
7145 #define DUK_HCOMPFUNC_ASSERT_VALID(h)  do { duk_hcompfunc_assert_valid((h)); } while (0)
7146 #else
7147 #define DUK_HCOMPFUNC_ASSERT_VALID(h)  do {} while (0)
7148 #endif
7149 
7150 /*
7151  *  Main struct
7152  */
7153 
7154 struct duk_hcompfunc {
7155 	/* shared object part */
7156 	duk_hobject obj;
7157 
7158 	/*
7159 	 *  Pointers to function data area for faster access.  Function
7160 	 *  data is a buffer shared between all closures of the same
7161 	 *  "template" function.  The data buffer is always fixed (non-
7162 	 *  dynamic, hence stable), with a layout as follows:
7163 	 *
7164 	 *    constants (duk_tval)
7165 	 *    inner functions (duk_hobject *)
7166 	 *    bytecode (duk_instr_t)
7167 	 *
7168 	 *  Note: bytecode end address can be computed from 'data' buffer
7169 	 *  size.  It is not strictly necessary functionally, assuming
7170 	 *  bytecode never jumps outside its allocated area.  However,
7171 	 *  it's a safety/robustness feature for avoiding the chance of
7172 	 *  executing random data as bytecode due to a compiler error.
7173 	 *
7174 	 *  Note: values in the data buffer must be incref'd (they will
7175 	 *  be decref'd on release) for every compiledfunction referring
7176 	 *  to the 'data' element.
7177 	 */
7178 
7179 	/* Data area, fixed allocation, stable data ptrs. */
7180 #if defined(DUK_USE_HEAPPTR16)
7181 	duk_uint16_t data16;
7182 #else
7183 	duk_hbuffer *data;
7184 #endif
7185 
7186 	/* No need for constants pointer (= same as data).
7187 	 *
7188 	 * When using 16-bit packing alignment to 4 is nice.  'funcs' will be
7189 	 * 4-byte aligned because 'constants' are duk_tvals.  For now the
7190 	 * inner function pointers are not compressed, so that 'bytecode' will
7191 	 * also be 4-byte aligned.
7192 	 */
7193 #if defined(DUK_USE_HEAPPTR16)
7194 	duk_uint16_t funcs16;
7195 	duk_uint16_t bytecode16;
7196 #else
7197 	duk_hobject **funcs;
7198 	duk_instr_t *bytecode;
7199 #endif
7200 
7201 	/* Lexenv: lexical environment of closure, NULL for templates.
7202 	 * Varenv: variable environment of closure, NULL for templates.
7203 	 */
7204 #if defined(DUK_USE_HEAPPTR16)
7205 	duk_uint16_t lex_env16;
7206 	duk_uint16_t var_env16;
7207 #else
7208 	duk_hobject *lex_env;
7209 	duk_hobject *var_env;
7210 #endif
7211 
7212 	/*
7213 	 *  'nregs' registers are allocated on function entry, at most 'nargs'
7214 	 *  are initialized to arguments, and the rest to undefined.  Arguments
7215 	 *  above 'nregs' are not mapped to registers.  All registers in the
7216 	 *  active stack range must be initialized because they are GC reachable.
7217 	 *  'nargs' is needed so that if the function is given more than 'nargs'
7218 	 *  arguments, the additional arguments do not 'clobber' registers
7219 	 *  beyond 'nregs' which must be consistently initialized to undefined.
7220 	 *
7221 	 *  Usually there is no need to know which registers are mapped to
7222 	 *  local variables.  Registers may be allocated to variable in any
7223 	 *  way (even including gaps).  However, a register-variable mapping
7224 	 *  must be the same for the duration of the function execution and
7225 	 *  the register cannot be used for anything else.
7226 	 *
7227 	 *  When looking up variables by name, the '_Varmap' map is used.
7228 	 *  When an activation closes, registers mapped to arguments are
7229 	 *  copied into the environment record based on the same map.  The
7230 	 *  reverse map (from register to variable) is not currently needed
7231 	 *  at run time, except for debugging, so it is not maintained.
7232 	 */
7233 
7234 	duk_uint16_t nregs;                /* regs to allocate */
7235 	duk_uint16_t nargs;                /* number of arguments allocated to regs */
7236 
7237 	/*
7238 	 *  Additional control information is placed into the object itself
7239 	 *  as internal properties to avoid unnecessary fields for the
7240 	 *  majority of functions.  The compiler tries to omit internal
7241 	 *  control fields when possible.
7242 	 *
7243 	 *  Function templates:
7244 	 *
7245 	 *    {
7246 	 *      name: "func",    // declaration, named function expressions
7247 	 *      fileName: <debug info for creating nice errors>
7248 	 *      _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
7249 	 *      _Formals: [ "arg1", "arg2" ],
7250 	 *      _Source: "function func(arg1, arg2) { ... }",
7251 	 *      _Pc2line: <debug info for pc-to-line mapping>,
7252 	 *    }
7253 	 *
7254 	 *  Function instances:
7255 	 *
7256 	 *    {
7257 	 *      length: 2,
7258 	 *      prototype: { constructor: <func> },
7259 	 *      caller: <thrower>,
7260 	 *      arguments: <thrower>,
7261 	 *      name: "func",    // declaration, named function expressions
7262 	 *      fileName: <debug info for creating nice errors>
7263 	 *      _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
7264 	 *      _Formals: [ "arg1", "arg2" ],
7265 	 *      _Source: "function func(arg1, arg2) { ... }",
7266 	 *      _Pc2line: <debug info for pc-to-line mapping>,
7267 	 *    }
7268 	 *
7269 	 *  More detailed description of these properties can be found
7270 	 *  in the documentation.
7271 	 */
7272 
7273 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7274 	/* Line number range for function.  Needed during debugging to
7275 	 * determine active breakpoints.
7276 	 */
7277 	duk_uint32_t start_line;
7278 	duk_uint32_t end_line;
7279 #endif
7280 };
7281 
7282 #endif  /* DUK_HCOMPFUNC_H_INCLUDED */
7283 /* #include duk_hnatfunc.h */
7284 /*
7285  *  Heap native function representation.
7286  */
7287 
7288 #if !defined(DUK_HNATFUNC_H_INCLUDED)
7289 #define DUK_HNATFUNC_H_INCLUDED
7290 
7291 #if defined(DUK_USE_ASSERTIONS)
7292 DUK_INTERNAL_DECL void duk_hnatfunc_assert_valid(duk_hnatfunc *h);
7293 #define DUK_HNATFUNC_ASSERT_VALID(h)  do { duk_hnatfunc_assert_valid((h)); } while (0)
7294 #else
7295 #define DUK_HNATFUNC_ASSERT_VALID(h)  do {} while (0)
7296 #endif
7297 
7298 #define DUK_HNATFUNC_NARGS_VARARGS  ((duk_int16_t) -1)
7299 #define DUK_HNATFUNC_NARGS_MAX      ((duk_int16_t) 0x7fff)
7300 
7301 struct duk_hnatfunc {
7302 	/* shared object part */
7303 	duk_hobject obj;
7304 
7305 	duk_c_function func;
7306 	duk_int16_t nargs;
7307 	duk_int16_t magic;
7308 
7309 	/* The 'magic' field allows an opaque 16-bit field to be accessed by the
7310 	 * Duktape/C function.  This allows, for instance, the same native function
7311 	 * to be used for a set of very similar functions, with the 'magic' field
7312 	 * providing the necessary non-argument flags / values to guide the behavior
7313 	 * of the native function.  The value is signed on purpose: it is easier to
7314 	 * convert a signed value to unsigned (simply AND with 0xffff) than vice
7315 	 * versa.
7316 	 *
7317 	 * Note: cannot place nargs/magic into the heaphdr flags, because
7318 	 * duk_hobject takes almost all flags already.
7319 	 */
7320 };
7321 
7322 #endif  /* DUK_HNATFUNC_H_INCLUDED */
7323 /* #include duk_hboundfunc.h */
7324 /*
7325  *  Bound function representation.
7326  */
7327 
7328 #if !defined(DUK_HBOUNDFUNC_H_INCLUDED)
7329 #define DUK_HBOUNDFUNC_H_INCLUDED
7330 
7331 /* Artificial limit for args length.  Ensures arithmetic won't overflow
7332  * 32 bits when combining bound functions.
7333  */
7334 #define DUK_HBOUNDFUNC_MAX_ARGS 0x20000000UL
7335 
7336 #if defined(DUK_USE_ASSERTIONS)
7337 DUK_INTERNAL_DECL void duk_hboundfunc_assert_valid(duk_hboundfunc *h);
7338 #define DUK_HBOUNDFUNC_ASSERT_VALID(h)  do { duk_hboundfunc_assert_valid((h)); } while (0)
7339 #else
7340 #define DUK_HBOUNDFUNC_ASSERT_VALID(h)  do {} while (0)
7341 #endif
7342 
7343 struct duk_hboundfunc {
7344 	/* Shared object part. */
7345 	duk_hobject obj;
7346 
7347 	/* Final target function, stored as duk_tval so that lightfunc can be
7348 	 * represented too.
7349 	 */
7350 	duk_tval target;
7351 
7352 	/* This binding. */
7353 	duk_tval this_binding;
7354 
7355 	/* Arguments to prepend. */
7356 	duk_tval *args;  /* Separate allocation. */
7357 	duk_idx_t nargs;
7358 };
7359 
7360 #endif  /* DUK_HBOUNDFUNC_H_INCLUDED */
7361 /* #include duk_hbufobj.h */
7362 /*
7363  *  Heap Buffer object representation.  Used for all Buffer variants.
7364  */
7365 
7366 #if !defined(DUK_HBUFOBJ_H_INCLUDED)
7367 #define DUK_HBUFOBJ_H_INCLUDED
7368 
7369 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
7370 
7371 /* All element accessors are host endian now (driven by TypedArray spec). */
7372 #define DUK_HBUFOBJ_ELEM_UINT8           0
7373 #define DUK_HBUFOBJ_ELEM_UINT8CLAMPED    1
7374 #define DUK_HBUFOBJ_ELEM_INT8            2
7375 #define DUK_HBUFOBJ_ELEM_UINT16          3
7376 #define DUK_HBUFOBJ_ELEM_INT16           4
7377 #define DUK_HBUFOBJ_ELEM_UINT32          5
7378 #define DUK_HBUFOBJ_ELEM_INT32           6
7379 #define DUK_HBUFOBJ_ELEM_FLOAT32         7
7380 #define DUK_HBUFOBJ_ELEM_FLOAT64         8
7381 #define DUK_HBUFOBJ_ELEM_MAX             8
7382 
7383 #if defined(DUK_USE_ASSERTIONS)
7384 DUK_INTERNAL_DECL void duk_hbufobj_assert_valid(duk_hbufobj *h);
7385 #define DUK_HBUFOBJ_ASSERT_VALID(h)  do { duk_hbufobj_assert_valid((h)); } while (0)
7386 #else
7387 #define DUK_HBUFOBJ_ASSERT_VALID(h)  do {} while (0)
7388 #endif
7389 
7390 /* Get the current data pointer (caller must ensure buf != NULL) as a
7391  * duk_uint8_t ptr.  Note that the result may be NULL if the underlying
7392  * buffer has zero size and is not a fixed buffer.
7393  */
7394 #define DUK_HBUFOBJ_GET_SLICE_BASE(heap,h) \
7395 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7396 	(((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + (h)->offset))
7397 
7398 /* True if slice is full, i.e. offset is zero and length covers the entire
7399  * buffer.  This status may change independently of the duk_hbufobj if
7400  * the underlying buffer is dynamic and changes without the hbufobj
7401  * being changed.
7402  */
7403 #define DUK_HBUFOBJ_FULL_SLICE(h) \
7404 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7405 	((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf)))
7406 
7407 /* Validate that the whole slice [0,length[ is contained in the underlying
7408  * buffer.  Caller must ensure 'buf' != NULL.
7409  */
7410 #define DUK_HBUFOBJ_VALID_SLICE(h) \
7411 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7412 	((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf)))
7413 
7414 /* Validate byte read/write for virtual 'offset', i.e. check that the
7415  * offset, taking into account h->offset, is within the underlying
7416  * buffer size.  This is a safety check which is needed to ensure
7417  * that even a misconfigured duk_hbufobj never causes memory unsafe
7418  * behavior (e.g. if an underlying dynamic buffer changes after being
7419  * setup).  Caller must ensure 'buf' != NULL.
7420  */
7421 #define DUK_HBUFOBJ_VALID_BYTEOFFSET_INCL(h,off) \
7422 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7423 	((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf)))
7424 
7425 #define DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h,off) \
7426 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7427 	((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf)))
7428 
7429 /* Clamp an input byte length (already assumed to be within the nominal
7430  * duk_hbufobj 'length') to the current dynamic buffer limits to yield
7431  * a byte length limit that's safe for memory accesses.  This value can
7432  * be invalidated by any side effect because it may trigger a user
7433  * callback that resizes the underlying buffer.
7434  */
7435 #define DUK_HBUFOBJ_CLAMP_BYTELENGTH(h,len) \
7436 	(DUK_ASSERT_EXPR((h) != NULL), \
7437 	duk_hbufobj_clamp_bytelength((h), (len)))
7438 
7439 /* Typed arrays have virtual indices, ArrayBuffer and DataView do not. */
7440 #define DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h)  ((h)->is_typedarray)
7441 
7442 struct duk_hbufobj {
7443 	/* Shared object part. */
7444 	duk_hobject obj;
7445 
7446 	/* Underlying buffer (refcounted), may be NULL. */
7447 	duk_hbuffer *buf;
7448 
7449 	/* .buffer reference to an ArrayBuffer, may be NULL. */
7450 	duk_hobject *buf_prop;
7451 
7452 	/* Slice and accessor information.
7453 	 *
7454 	 * Because the underlying buffer may be dynamic, these may be
7455 	 * invalidated by the buffer being modified so that both offset
7456 	 * and length should be validated before every access.  Behavior
7457 	 * when the underlying buffer has changed doesn't need to be clean:
7458 	 * virtual 'length' doesn't need to be affected, reads can return
7459 	 * zero/NaN, and writes can be ignored.
7460 	 *
7461 	 * Note that a data pointer cannot be precomputed because 'buf' may
7462 	 * be dynamic and its pointer unstable.
7463 	 */
7464 
7465 	duk_uint_t offset;       /* byte offset to buf */
7466 	duk_uint_t length;       /* byte index limit for element access, exclusive */
7467 	duk_uint8_t shift;       /* element size shift:
7468 	                          *   0 = u8/i8
7469 	                          *   1 = u16/i16
7470 	                          *   2 = u32/i32/float
7471 	                          *   3 = double
7472 	                          */
7473 	duk_uint8_t elem_type;   /* element type */
7474 	duk_uint8_t is_typedarray;
7475 };
7476 
7477 DUK_INTERNAL_DECL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len);
7478 DUK_INTERNAL_DECL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf);
7479 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);
7480 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);
7481 DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx);
7482 
7483 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
7484 
7485 /* nothing */
7486 
7487 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
7488 #endif  /* DUK_HBUFOBJ_H_INCLUDED */
7489 /* #include duk_hthread.h */
7490 /*
7491  *  Heap thread object representation.
7492  *
7493  *  duk_hthread is also the 'context' for public API functions via a
7494  *  different typedef.  Most API calls operate on the topmost frame
7495  *  of the value stack only.
7496  */
7497 
7498 #if !defined(DUK_HTHREAD_H_INCLUDED)
7499 #define DUK_HTHREAD_H_INCLUDED
7500 
7501 /*
7502  *  Stack constants
7503  */
7504 
7505 /* Initial valstack size, roughly 0.7kiB. */
7506 #define DUK_VALSTACK_INITIAL_SIZE       96U
7507 
7508 /* Internal extra elements assumed on function entry, always added to
7509  * user-defined 'extra' for e.g. the duk_check_stack() call.
7510  */
7511 #define DUK_VALSTACK_INTERNAL_EXTRA     32U
7512 
7513 /* Number of elements guaranteed to be user accessible (in addition to call
7514  * arguments) on Duktape/C function entry.  This is the major public API
7515  * commitment.
7516  */
7517 #define DUK_VALSTACK_API_ENTRY_MINIMUM  DUK_API_ENTRY_STACK
7518 
7519 /*
7520  *  Activation defines
7521  */
7522 
7523 #define DUK_ACT_FLAG_STRICT             (1U << 0)  /* function executes in strict mode */
7524 #define DUK_ACT_FLAG_TAILCALLED         (1U << 1)  /* activation has tail called one or more times */
7525 #define DUK_ACT_FLAG_CONSTRUCT          (1U << 2)  /* function executes as a constructor (called via "new") */
7526 #define DUK_ACT_FLAG_PREVENT_YIELD      (1U << 3)  /* activation prevents yield (native call or "new") */
7527 #define DUK_ACT_FLAG_DIRECT_EVAL        (1U << 4)  /* activation is a direct eval call */
7528 #define DUK_ACT_FLAG_CONSTRUCT_PROXY    (1U << 5)  /* activation is for Proxy 'construct' call, special return value handling */
7529 #define DUK_ACT_FLAG_BREAKPOINT_ACTIVE  (1U << 6)  /* activation has active breakpoint(s) */
7530 
7531 #define DUK_ACT_GET_FUNC(act)           ((act)->func)
7532 
7533 /*
7534  *  Flags for __FILE__ / __LINE__ registered into tracedata
7535  */
7536 
7537 #define DUK_TB_FLAG_NOBLAME_FILELINE    (1U << 0)  /* don't report __FILE__ / __LINE__ as fileName/lineNumber */
7538 
7539 /*
7540  *  Catcher defines
7541  */
7542 
7543 /* XXX: remove catcher type entirely */
7544 
7545 /* flags field: LLLLLLFT, L = label (24 bits), F = flags (4 bits), T = type (4 bits) */
7546 #define DUK_CAT_TYPE_MASK            0x0000000fUL
7547 #define DUK_CAT_TYPE_BITS            4
7548 #define DUK_CAT_LABEL_MASK           0xffffff00UL
7549 #define DUK_CAT_LABEL_BITS           24
7550 #define DUK_CAT_LABEL_SHIFT          8
7551 
7552 #define DUK_CAT_FLAG_CATCH_ENABLED          (1U << 4)   /* catch part will catch */
7553 #define DUK_CAT_FLAG_FINALLY_ENABLED        (1U << 5)   /* finally part will catch */
7554 #define DUK_CAT_FLAG_CATCH_BINDING_ENABLED  (1U << 6)   /* request to create catch binding */
7555 #define DUK_CAT_FLAG_LEXENV_ACTIVE          (1U << 7)   /* catch or with binding is currently active */
7556 
7557 #define DUK_CAT_TYPE_UNKNOWN         0
7558 #define DUK_CAT_TYPE_TCF             1
7559 #define DUK_CAT_TYPE_LABEL           2
7560 
7561 #define DUK_CAT_GET_TYPE(c)          ((c)->flags & DUK_CAT_TYPE_MASK)
7562 #define DUK_CAT_GET_LABEL(c)         (((c)->flags & DUK_CAT_LABEL_MASK) >> DUK_CAT_LABEL_SHIFT)
7563 
7564 #define DUK_CAT_HAS_CATCH_ENABLED(c)           ((c)->flags & DUK_CAT_FLAG_CATCH_ENABLED)
7565 #define DUK_CAT_HAS_FINALLY_ENABLED(c)         ((c)->flags & DUK_CAT_FLAG_FINALLY_ENABLED)
7566 #define DUK_CAT_HAS_CATCH_BINDING_ENABLED(c)   ((c)->flags & DUK_CAT_FLAG_CATCH_BINDING_ENABLED)
7567 #define DUK_CAT_HAS_LEXENV_ACTIVE(c)           ((c)->flags & DUK_CAT_FLAG_LEXENV_ACTIVE)
7568 
7569 #define DUK_CAT_SET_CATCH_ENABLED(c)    do { \
7570 		(c)->flags |= DUK_CAT_FLAG_CATCH_ENABLED; \
7571 	} while (0)
7572 #define DUK_CAT_SET_FINALLY_ENABLED(c)  do { \
7573 		(c)->flags |= DUK_CAT_FLAG_FINALLY_ENABLED; \
7574 	} while (0)
7575 #define DUK_CAT_SET_CATCH_BINDING_ENABLED(c)    do { \
7576 		(c)->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
7577 	} while (0)
7578 #define DUK_CAT_SET_LEXENV_ACTIVE(c)    do { \
7579 		(c)->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE; \
7580 	} while (0)
7581 
7582 #define DUK_CAT_CLEAR_CATCH_ENABLED(c)    do { \
7583 		(c)->flags &= ~DUK_CAT_FLAG_CATCH_ENABLED; \
7584 	} while (0)
7585 #define DUK_CAT_CLEAR_FINALLY_ENABLED(c)  do { \
7586 		(c)->flags &= ~DUK_CAT_FLAG_FINALLY_ENABLED; \
7587 	} while (0)
7588 #define DUK_CAT_CLEAR_CATCH_BINDING_ENABLED(c)    do { \
7589 		(c)->flags &= ~DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
7590 	} while (0)
7591 #define DUK_CAT_CLEAR_LEXENV_ACTIVE(c)    do { \
7592 		(c)->flags &= ~DUK_CAT_FLAG_LEXENV_ACTIVE; \
7593 	} while (0)
7594 
7595 /*
7596  *  Thread defines
7597  */
7598 
7599 #if defined(DUK_USE_ROM_STRINGS)
7600 #define DUK_HTHREAD_GET_STRING(thr,idx) \
7601 	((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
7602 #else  /* DUK_USE_ROM_STRINGS */
7603 #if defined(DUK_USE_HEAPPTR16)
7604 #define DUK_HTHREAD_GET_STRING(thr,idx) \
7605 	((duk_hstring *) DUK_USE_HEAPPTR_DEC16((thr)->heap->heap_udata, (thr)->strs16[(idx)]))
7606 #else
7607 #define DUK_HTHREAD_GET_STRING(thr,idx) \
7608 	((thr)->strs[(idx)])
7609 #endif
7610 #endif  /* DUK_USE_ROM_STRINGS */
7611 
7612 /* values for the state field */
7613 #define DUK_HTHREAD_STATE_INACTIVE     1   /* thread not currently running */
7614 #define DUK_HTHREAD_STATE_RUNNING      2   /* thread currently running (only one at a time) */
7615 #define DUK_HTHREAD_STATE_RESUMED      3   /* thread resumed another thread (active but not running) */
7616 #define DUK_HTHREAD_STATE_YIELDED      4   /* thread has yielded */
7617 #define DUK_HTHREAD_STATE_TERMINATED   5   /* thread has terminated */
7618 
7619 /* Executor interrupt default interval when nothing else requires a
7620  * smaller value.  The default interval must be small enough to allow
7621  * for reasonable execution timeout checking but large enough to keep
7622  * impact on execution performance low.
7623  */
7624 #if defined(DUK_USE_INTERRUPT_COUNTER)
7625 #define DUK_HTHREAD_INTCTR_DEFAULT     (256L * 1024L)
7626 #endif
7627 
7628 /*
7629  *  Assert context is valid: non-NULL pointer, fields look sane.
7630  *
7631  *  This is used by public API call entrypoints to catch invalid 'ctx' pointers
7632  *  as early as possible; invalid 'ctx' pointers cause very odd and difficult to
7633  *  diagnose behavior so it's worth checking even when the check is not 100%.
7634  */
7635 
7636 #if defined(DUK_USE_ASSERTIONS)
7637 /* Assertions for internals. */
7638 DUK_INTERNAL_DECL void duk_hthread_assert_valid(duk_hthread *thr);
7639 #define DUK_HTHREAD_ASSERT_VALID(thr)  do { duk_hthread_assert_valid((thr)); } while (0)
7640 
7641 /* Assertions for public API calls; a bit stronger. */
7642 DUK_INTERNAL_DECL void duk_ctx_assert_valid(duk_hthread *thr);
7643 #define DUK_CTX_ASSERT_VALID(thr)  do { duk_ctx_assert_valid((thr)); } while (0)
7644 #else
7645 #define DUK_HTHREAD_ASSERT_VALID(thr)  do {} while (0)
7646 #define DUK_CTX_ASSERT_VALID(thr)  do {} while (0)
7647 #endif
7648 
7649 /* Assertions for API call entry specifically.  Checks 'ctx' but also may
7650  * check internal state (e.g. not in a debugger transport callback).
7651  */
7652 #define DUK_ASSERT_API_ENTRY(thr) do { \
7653 		DUK_CTX_ASSERT_VALID((thr)); \
7654 		DUK_ASSERT((thr)->heap != NULL); \
7655 		DUK_ASSERT((thr)->heap->dbg_calling_transport == 0); \
7656 	} while (0)
7657 
7658 /*
7659  *  Assertion helpers.
7660  */
7661 
7662 #define DUK_ASSERT_STRIDX_VALID(val) \
7663 	DUK_ASSERT((duk_uint_t) (val) < DUK_HEAP_NUM_STRINGS)
7664 
7665 #define DUK_ASSERT_BIDX_VALID(val) \
7666 	DUK_ASSERT((duk_uint_t) (val) < DUK_NUM_BUILTINS)
7667 
7668 /*
7669  *  Misc
7670  */
7671 
7672 /* Fast access to 'this' binding.  Assumes there's a call in progress. */
7673 #define DUK_HTHREAD_THIS_PTR(thr) \
7674 	(DUK_ASSERT_EXPR((thr) != NULL), \
7675 	 DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \
7676 	 (thr)->valstack_bottom - 1)
7677 
7678 /*
7679  *  Struct defines
7680  */
7681 
7682 /* Fields are ordered for alignment/packing. */
7683 struct duk_activation {
7684 	duk_tval tv_func;       /* borrowed: full duk_tval for function being executed; for lightfuncs */
7685 	duk_hobject *func;      /* borrowed: function being executed; for bound function calls, this is the final, real function, NULL for lightfuncs */
7686 	duk_activation *parent; /* previous (parent) activation (or NULL if none) */
7687 	duk_hobject *var_env;   /* current variable environment (may be NULL if delayed) */
7688 	duk_hobject *lex_env;   /* current lexical environment (may be NULL if delayed) */
7689 	duk_catcher *cat;       /* current catcher (or NULL) */
7690 
7691 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
7692 	/* Previous value of 'func' caller, restored when unwound.  Only in use
7693 	 * when 'func' is non-strict.
7694 	 */
7695 	duk_hobject *prev_caller;
7696 #endif
7697 
7698 	duk_instr_t *curr_pc;   /* next instruction to execute (points to 'func' bytecode, stable pointer), NULL for native calls */
7699 
7700 	/* bottom_byteoff and retval_byteoff are only used for book-keeping
7701 	 * of ECMAScript-initiated calls, to allow returning to an ECMAScript
7702 	 * function properly.
7703 	 */
7704 
7705 	/* Bottom of valstack for this activation, used to reset
7706 	 * valstack_bottom on return; offset is absolute.  There's
7707 	 * no need to track 'top' because native call handling deals
7708 	 * with that using locals, and for ECMAScript returns 'nregs'
7709 	 * indicates the necessary top.
7710 	 */
7711 	duk_size_t bottom_byteoff;
7712 
7713 	/* Return value when returning to this activation (points to caller
7714 	 * reg, not callee reg); offset is absolute (only set if activation is
7715 	 * not topmost).
7716 	 *
7717 	 * Note: bottom_byteoff is always set, while retval_byteoff is only
7718 	 * applicable for activations below the topmost one.  Currently
7719 	 * retval_byteoff for the topmost activation is considered garbage
7720 	 * (and it not initialized on entry or cleared on return; may contain
7721 	 * previous or garbage values).
7722 	 */
7723 	duk_size_t retval_byteoff;
7724 
7725 	/* Current 'this' binding is the value just below bottom.
7726 	 * Previously, 'this' binding was handled with an index to the
7727 	 * (calling) valstack.  This works for everything except tail
7728 	 * calls, which must not "accumulate" valstack temps.
7729 	 */
7730 
7731 	/* Value stack reserve (valstack_end) byte offset to be restored
7732 	 * when returning to this activation.  Only used by the bytecode
7733 	 * executor.
7734 	 */
7735 	duk_size_t reserve_byteoff;
7736 
7737 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7738 	duk_uint32_t prev_line; /* needed for stepping */
7739 #endif
7740 
7741 	duk_small_uint_t flags;
7742 };
7743 
7744 struct duk_catcher {
7745 	duk_catcher *parent;            /* previous (parent) catcher (or NULL if none) */
7746 	duk_hstring *h_varname;         /* borrowed reference to catch variable name (or NULL if none) */
7747 	                                /* (reference is valid as long activation exists) */
7748 	duk_instr_t *pc_base;           /* resume execution from pc_base or pc_base+1 (points to 'func' bytecode, stable pointer) */
7749 	duk_size_t idx_base;            /* idx_base and idx_base+1 get completion value and type */
7750 	duk_uint32_t flags;             /* type and control flags, label number */
7751 	/* XXX: could pack 'flags' and 'idx_base' to same value in practice,
7752 	 * on 32-bit targets this would make duk_catcher 16 bytes.
7753 	 */
7754 };
7755 
7756 struct duk_hthread {
7757 	/* Shared object part */
7758 	duk_hobject obj;
7759 
7760 	/* Pointer to bytecode executor's 'curr_pc' variable.  Used to copy
7761 	 * the current PC back into the topmost activation when activation
7762 	 * state is about to change (or "syncing" is otherwise needed).  This
7763 	 * is rather awkward but important for performance, see execution.rst.
7764 	 */
7765 	duk_instr_t **ptr_curr_pc;
7766 
7767 	/* Backpointers. */
7768 	duk_heap *heap;
7769 
7770 	/* Current strictness flag: affects API calls. */
7771 	duk_uint8_t strict;
7772 
7773 	/* Thread state. */
7774 	duk_uint8_t state;
7775 	duk_uint8_t unused1;
7776 	duk_uint8_t unused2;
7777 
7778 	/* XXX: Valstack and callstack are currently assumed to have non-NULL
7779 	 * pointers.  Relaxing this would not lead to big benefits (except
7780 	 * perhaps for terminated threads).
7781 	 */
7782 
7783 	/* Value stack: these are expressed as pointers for faster stack
7784 	 * manipulation.  [valstack,valstack_top[ is GC-reachable,
7785 	 * [valstack_top,valstack_alloc_end[ is not GC-reachable but kept
7786 	 * initialized as 'undefined'.  [valstack,valstack_end[ is the
7787 	 * guaranteed/reserved space and the valstack cannot be resized to
7788 	 * a smaller size.  [valstack_end,valstack_alloc_end[ is currently
7789 	 * allocated slack that can be used to grow the current guaranteed
7790 	 * space but may be shrunk away without notice.
7791 	 *
7792 	 *
7793 	 * <----------------------- guaranteed --->
7794 	 *                                        <---- slack --->
7795 	 *               <--- frame --->
7796 	 * .-------------+=============+----------+--------------.
7797 	 * |xxxxxxxxxxxxx|yyyyyyyyyyyyy|uuuuuuuuuu|uuuuuuuuuuuuuu|
7798 	 * `-------------+=============+----------+--------------'
7799 	 *
7800 	 * ^             ^             ^          ^              ^
7801 	 * |             |             |          |              |
7802 	 * valstack      bottom        top        end            alloc_end
7803 	 *
7804 	 *     xxx = arbitrary values, below current frame
7805 	 *     yyy = arbitrary values, inside current frame
7806 	 *     uuu = outside active value stack, initialized to 'undefined'
7807 	 */
7808 	duk_tval *valstack;                     /* start of valstack allocation */
7809 	duk_tval *valstack_end;                 /* end of valstack reservation/guarantee (exclusive) */
7810 	duk_tval *valstack_alloc_end;           /* end of valstack allocation */
7811 	duk_tval *valstack_bottom;              /* bottom of current frame */
7812 	duk_tval *valstack_top;                 /* top of current frame (exclusive) */
7813 
7814 	/* Call stack, represented as a linked list starting from the current
7815 	 * activation (or NULL if nothing is active).
7816 	 */
7817 	duk_activation *callstack_curr;         /* current activation (or NULL if none) */
7818 	duk_size_t callstack_top;               /* number of activation records in callstack (0 if none) */
7819 	duk_size_t callstack_preventcount;      /* number of activation records in callstack preventing a yield */
7820 
7821 	/* Yield/resume book-keeping. */
7822 	duk_hthread *resumer;                   /* who resumed us (if any) */
7823 
7824 	/* Current compiler state (if any), used for augmenting SyntaxErrors. */
7825 	duk_compiler_ctx *compile_ctx;
7826 
7827 #if defined(DUK_USE_INTERRUPT_COUNTER)
7828 	/* Interrupt counter for triggering a slow path check for execution
7829 	 * timeout, debugger interaction such as breakpoints, etc.  The value
7830 	 * is valid for the current running thread, and both the init and
7831 	 * counter values are copied whenever a thread switch occurs.  It's
7832 	 * important for the counter to be conveniently accessible for the
7833 	 * bytecode executor inner loop for performance reasons.
7834 	 */
7835 	duk_int_t interrupt_counter;    /* countdown state */
7836 	duk_int_t interrupt_init;       /* start value for current countdown */
7837 #endif
7838 
7839 	/* Builtin-objects; may or may not be shared with other threads,
7840 	 * threads existing in different "compartments" will have different
7841 	 * built-ins.  Must be stored on a per-thread basis because there
7842 	 * is no intermediate structure for a thread group / compartment.
7843 	 * This takes quite a lot of space, currently 43x4 = 172 bytes on
7844 	 * 32-bit platforms.
7845 	 *
7846 	 * In some cases the builtins array could be ROM based, but it's
7847 	 * sometimes edited (e.g. for sandboxing) so it's better to keep
7848 	 * this array in RAM.
7849 	 */
7850 	duk_hobject *builtins[DUK_NUM_BUILTINS];
7851 
7852 	/* Convenience copies from heap/vm for faster access. */
7853 #if defined(DUK_USE_ROM_STRINGS)
7854 	/* No field needed when strings are in ROM. */
7855 #else
7856 #if defined(DUK_USE_HEAPPTR16)
7857 	duk_uint16_t *strs16;
7858 #else
7859 	duk_hstring **strs;
7860 #endif
7861 #endif
7862 };
7863 
7864 /*
7865  *  Prototypes
7866  */
7867 
7868 DUK_INTERNAL_DECL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to);
7869 DUK_INTERNAL_DECL void duk_hthread_create_builtin_objects(duk_hthread *thr);
7870 DUK_INTERNAL_DECL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr);
7871 DUK_INTERNAL_DECL void duk_hthread_terminate(duk_hthread *thr);
7872 
7873 DUK_INTERNAL_DECL DUK_INLINE duk_activation *duk_hthread_activation_alloc(duk_hthread *thr);
7874 DUK_INTERNAL_DECL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act);
7875 DUK_INTERNAL_DECL void duk_hthread_activation_unwind_norz(duk_hthread *thr);
7876 DUK_INTERNAL_DECL void duk_hthread_activation_unwind_reuse_norz(duk_hthread *thr);
7877 DUK_INTERNAL_DECL duk_activation *duk_hthread_get_activation_for_level(duk_hthread *thr, duk_int_t level);
7878 
7879 DUK_INTERNAL_DECL DUK_INLINE duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr);
7880 DUK_INTERNAL_DECL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat);
7881 DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activation *act);
7882 DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk_activation *act);
7883 
7884 #if defined(DUK_USE_FINALIZER_TORTURE)
7885 DUK_INTERNAL_DECL void duk_hthread_valstack_torture_realloc(duk_hthread *thr);
7886 #endif
7887 
7888 DUK_INTERNAL_DECL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud);  /* indirect allocs */
7889 
7890 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7891 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act);
7892 #endif
7893 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act);
7894 DUK_INTERNAL_DECL void duk_hthread_sync_currpc(duk_hthread *thr);
7895 DUK_INTERNAL_DECL void duk_hthread_sync_and_null_currpc(duk_hthread *thr);
7896 
7897 #endif  /* DUK_HTHREAD_H_INCLUDED */
7898 /* #include duk_harray.h */
7899 /*
7900  *  Array object representation, used for actual Array instances.
7901  *
7902  *  All objects with the exotic array behavior (which must coincide with having
7903  *  internal class array) MUST be duk_harrays.  No other object can be a
7904  *  duk_harray.  However, duk_harrays may not always have an array part.
7905  */
7906 
7907 #if !defined(DUK_HARRAY_H_INCLUDED)
7908 #define DUK_HARRAY_H_INCLUDED
7909 
7910 #if defined(DUK_USE_ASSERTIONS)
7911 DUK_INTERNAL_DECL void duk_harray_assert_valid(duk_harray *h);
7912 #define DUK_HARRAY_ASSERT_VALID(h)  do { duk_harray_assert_valid((h)); } while (0)
7913 #else
7914 #define DUK_HARRAY_ASSERT_VALID(h)  do {} while (0)
7915 #endif
7916 
7917 #define DUK_HARRAY_LENGTH_WRITABLE(h)         (!(h)->length_nonwritable)
7918 #define DUK_HARRAY_LENGTH_NONWRITABLE(h)      ((h)->length_nonwritable)
7919 #define DUK_HARRAY_SET_LENGTH_WRITABLE(h)     do { (h)->length_nonwritable = 0; } while (0)
7920 #define DUK_HARRAY_SET_LENGTH_NONWRITABLE(h)  do { (h)->length_nonwritable = 1; } while (0)
7921 
7922 struct duk_harray {
7923 	/* Shared object part. */
7924 	duk_hobject obj;
7925 
7926 	/* Array .length.
7927 	 *
7928 	 * At present Array .length may be smaller, equal, or even larger
7929 	 * than the allocated underlying array part.  Fast path code must
7930 	 * always take this into account carefully.
7931 	 */
7932 	duk_uint32_t length;
7933 
7934 	/* Array .length property attributes.  The property is always
7935 	 * non-enumerable and non-configurable.  It's initially writable
7936 	 * but per Object.defineProperty() rules it can be made non-writable
7937 	 * even if it is non-configurable.  Thus we need to track the
7938 	 * writability explicitly.
7939 	 *
7940 	 * XXX: this field to be eliminated and moved into duk_hobject
7941 	 * flags field to save space.
7942 	 */
7943 	duk_bool_t length_nonwritable;
7944 };
7945 
7946 #endif  /* DUK_HARRAY_H_INCLUDED */
7947 /* #include duk_henv.h */
7948 /*
7949  *  Environment object representation.
7950  */
7951 
7952 #if !defined(DUK_HENV_H_INCLUDED)
7953 #define DUK_HENV_H_INCLUDED
7954 
7955 #if defined(DUK_USE_ASSERTIONS)
7956 DUK_INTERNAL_DECL void duk_hdecenv_assert_valid(duk_hdecenv *h);
7957 DUK_INTERNAL_DECL void duk_hobjenv_assert_valid(duk_hobjenv *h);
7958 #define DUK_HDECENV_ASSERT_VALID(h)  do { duk_hdecenv_assert_valid((h)); } while (0)
7959 #define DUK_HOBJENV_ASSERT_VALID(h)  do { duk_hobjenv_assert_valid((h)); } while (0)
7960 #else
7961 #define DUK_HDECENV_ASSERT_VALID(h)  do {} while (0)
7962 #define DUK_HOBJENV_ASSERT_VALID(h)  do {} while (0)
7963 #endif
7964 
7965 struct duk_hdecenv {
7966 	/* Shared object part. */
7967 	duk_hobject obj;
7968 
7969 	/* These control variables provide enough information to access live
7970 	 * variables for a closure that is still open.  If thread == NULL,
7971 	 * the record is closed and the identifiers are in the property table.
7972 	 */
7973 	duk_hthread *thread;
7974 	duk_hobject *varmap;
7975 	duk_size_t regbase_byteoff;
7976 };
7977 
7978 struct duk_hobjenv {
7979 	/* Shared object part. */
7980 	duk_hobject obj;
7981 
7982 	/* Target object and 'this' binding for object binding. */
7983 	duk_hobject *target;
7984 
7985 	/* The 'target' object is used as a this binding in only some object
7986 	 * environments.  For example, the global environment does not provide
7987 	 * a this binding, but a with statement does.
7988 	 */
7989 	duk_bool_t has_this;
7990 };
7991 
7992 #endif  /* DUK_HENV_H_INCLUDED */
7993 /* #include duk_hbuffer.h */
7994 /*
7995  *  Heap buffer representation.
7996  *
7997  *  Heap allocated user data buffer which is either:
7998  *
7999  *    1. A fixed size buffer (data follows header statically)
8000  *    2. A dynamic size buffer (data pointer follows header)
8001  *
8002  *  The data pointer for a variable size buffer of zero size may be NULL.
8003  */
8004 
8005 #if !defined(DUK_HBUFFER_H_INCLUDED)
8006 #define DUK_HBUFFER_H_INCLUDED
8007 
8008 /*
8009  *  Flags
8010  *
8011  *  Fixed buffer:     0
8012  *  Dynamic buffer:   DUK_HBUFFER_FLAG_DYNAMIC
8013  *  External buffer:  DUK_HBUFFER_FLAG_DYNAMIC | DUK_HBUFFER_FLAG_EXTERNAL
8014  */
8015 
8016 #define DUK_HBUFFER_FLAG_DYNAMIC                  DUK_HEAPHDR_USER_FLAG(0)    /* buffer is behind a pointer, dynamic or external */
8017 #define DUK_HBUFFER_FLAG_EXTERNAL                 DUK_HEAPHDR_USER_FLAG(1)    /* buffer pointer is to an externally allocated buffer */
8018 
8019 #define DUK_HBUFFER_HAS_DYNAMIC(x)                DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
8020 #define DUK_HBUFFER_HAS_EXTERNAL(x)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
8021 
8022 #define DUK_HBUFFER_SET_DYNAMIC(x)                DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
8023 #define DUK_HBUFFER_SET_EXTERNAL(x)               DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
8024 
8025 #define DUK_HBUFFER_CLEAR_DYNAMIC(x)              DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
8026 #define DUK_HBUFFER_CLEAR_EXTERNAL(x)             DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
8027 
8028 /*
8029  *  Misc defines
8030  */
8031 
8032 /* Impose a maximum buffer length for now.  Restricted artificially to
8033  * ensure resize computations or adding a heap header length won't
8034  * overflow size_t and that a signed duk_int_t can hold a buffer
8035  * length.  The limit should be synchronized with DUK_HSTRING_MAX_BYTELEN.
8036  */
8037 
8038 #if defined(DUK_USE_BUFLEN16)
8039 #define DUK_HBUFFER_MAX_BYTELEN                   (0x0000ffffUL)
8040 #else
8041 /* Intentionally not 0x7fffffffUL; at least JSON code expects that
8042  * 2*len + 2 fits in 32 bits.
8043  */
8044 #define DUK_HBUFFER_MAX_BYTELEN                   (0x7ffffffeUL)
8045 #endif
8046 
8047 /*
8048  *  Field access
8049  */
8050 
8051 #if defined(DUK_USE_BUFLEN16)
8052 /* size stored in duk_heaphdr unused flag bits */
8053 #define DUK_HBUFFER_GET_SIZE(x)     ((x)->hdr.h_flags >> 16)
8054 #define DUK_HBUFFER_SET_SIZE(x,v)   do { \
8055 		duk_size_t duk__v; \
8056 		duk__v = (v); \
8057 		DUK_ASSERT(duk__v <= 0xffffUL); \
8058 		(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | (((duk_uint32_t) duk__v) << 16); \
8059 	} while (0)
8060 #define DUK_HBUFFER_ADD_SIZE(x,dv)  do { \
8061 		(x)->hdr.h_flags += ((dv) << 16); \
8062 	} while (0)
8063 #define DUK_HBUFFER_SUB_SIZE(x,dv)  do { \
8064 		(x)->hdr.h_flags -= ((dv) << 16); \
8065 	} while (0)
8066 #else
8067 #define DUK_HBUFFER_GET_SIZE(x)     (((duk_hbuffer *) (x))->size)
8068 #define DUK_HBUFFER_SET_SIZE(x,v)   do { \
8069 		((duk_hbuffer *) (x))->size = (v); \
8070 	} while (0)
8071 #define DUK_HBUFFER_ADD_SIZE(x,dv)  do { \
8072 		(x)->size += (dv); \
8073 	} while (0)
8074 #define DUK_HBUFFER_SUB_SIZE(x,dv)  do { \
8075 		(x)->size -= (dv); \
8076 	} while (0)
8077 #endif
8078 
8079 #define DUK_HBUFFER_FIXED_GET_SIZE(x)       DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
8080 #define DUK_HBUFFER_FIXED_SET_SIZE(x,v)     DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x))
8081 
8082 #define DUK_HBUFFER_DYNAMIC_GET_SIZE(x)     DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
8083 #define DUK_HBUFFER_DYNAMIC_SET_SIZE(x,v)   DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
8084 #define DUK_HBUFFER_DYNAMIC_ADD_SIZE(x,dv)  DUK_HBUFFER_ADD_SIZE((duk_hbuffer *) (x), (dv))
8085 #define DUK_HBUFFER_DYNAMIC_SUB_SIZE(x,dv)  DUK_HBUFFER_SUB_SIZE((duk_hbuffer *) (x), (dv))
8086 
8087 #define DUK_HBUFFER_EXTERNAL_GET_SIZE(x)    DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
8088 #define DUK_HBUFFER_EXTERNAL_SET_SIZE(x,v)  DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
8089 
8090 #define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap,x)    ((duk_uint8_t *) (((duk_hbuffer_fixed *) (void *) (x)) + 1))
8091 
8092 #if defined(DUK_USE_HEAPPTR16)
8093 #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) \
8094 	((void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (x))->h_extra16))
8095 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v)     do { \
8096 		((duk_heaphdr *) (x))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
8097 	} while (0)
8098 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x)  do { \
8099 		((duk_heaphdr *) (x))->h_extra16 = 0;  /* assume 0 <=> NULL */ \
8100 	} while (0)
8101 #else
8102 #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x)       ((x)->curr_alloc)
8103 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v)     do { \
8104 		(x)->curr_alloc = (void *) (v); \
8105 	} while (0)
8106 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x)  do { \
8107 		(x)->curr_alloc = (void *) NULL; \
8108 	} while (0)
8109 #endif
8110 
8111 /* No pointer compression because pointer is potentially outside of
8112  * Duktape heap.
8113  */
8114 #if defined(DUK_USE_HEAPPTR16)
8115 #define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
8116 	((void *) (x)->curr_alloc)
8117 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v)     do { \
8118 		(x)->curr_alloc = (void *) (v); \
8119 	} while (0)
8120 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x)  do { \
8121 		(x)->curr_alloc = (void *) NULL; \
8122 	} while (0)
8123 #else
8124 #define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
8125 	((void *) (x)->curr_alloc)
8126 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v)     do { \
8127 		(x)->curr_alloc = (void *) (v); \
8128 	} while (0)
8129 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x)  do { \
8130 		(x)->curr_alloc = (void *) NULL; \
8131 	} while (0)
8132 #endif
8133 
8134 /* Get a pointer to the current buffer contents (matching current allocation
8135  * size).  May be NULL for zero size dynamic/external buffer.
8136  */
8137 #if defined(DUK_USE_HEAPPTR16)
8138 #define DUK_HBUFFER_GET_DATA_PTR(heap,x)  ( \
8139 	DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
8140 		( \
8141 			DUK_HBUFFER_HAS_EXTERNAL((x)) ? \
8142 				DUK_HBUFFER_EXTERNAL_GET_DATA_PTR((heap), (duk_hbuffer_external *) (x)) : \
8143 				DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) \
8144 		) : \
8145 		DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (void *) (x)) \
8146 	)
8147 #else
8148 /* Without heap pointer compression duk_hbuffer_dynamic and duk_hbuffer_external
8149  * have the same layout so checking for fixed vs. dynamic (or external) is enough.
8150  */
8151 #define DUK_HBUFFER_GET_DATA_PTR(heap,x)  ( \
8152 	DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
8153 		DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) : \
8154 		DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (void *) (x)) \
8155 	)
8156 #endif
8157 
8158 /* Validity assert. */
8159 #if defined(DUK_USE_ASSERTIONS)
8160 DUK_INTERNAL_DECL void duk_hbuffer_assert_valid(duk_hbuffer *h);
8161 #define DUK_HBUFFER_ASSERT_VALID(h)  do { duk_hbuffer_assert_valid((h)); } while (0)
8162 #else
8163 #define DUK_HBUFFER_ASSERT_VALID(h)  do {} while (0)
8164 #endif
8165 
8166 /*
8167  *  Structs
8168  */
8169 
8170 /* Shared prefix for all buffer types. */
8171 struct duk_hbuffer {
8172 	duk_heaphdr hdr;
8173 
8174 	/* It's not strictly necessary to track the current size, but
8175 	 * it is useful for writing robust native code.
8176 	 */
8177 
8178 	/* Current size. */
8179 #if defined(DUK_USE_BUFLEN16)
8180 	/* Stored in duk_heaphdr unused flags. */
8181 #else
8182 	duk_size_t size;
8183 #endif
8184 
8185 	/*
8186 	 *  Data following the header depends on the DUK_HBUFFER_FLAG_DYNAMIC
8187 	 *  flag.
8188 	 *
8189 	 *  If the flag is clear (the buffer is a fixed size one), the buffer
8190 	 *  data follows the header directly, consisting of 'size' bytes.
8191 	 *
8192 	 *  If the flag is set, the actual buffer is allocated separately, and
8193 	 *  a few control fields follow the header.  Specifically:
8194 	 *
8195 	 *    - a "void *" pointing to the current allocation
8196 	 *    - a duk_size_t indicating the full allocated size (always >= 'size')
8197 	 *
8198 	 *  If DUK_HBUFFER_FLAG_EXTERNAL is set, the buffer has been allocated
8199 	 *  by user code, so that Duktape won't be able to resize it and won't
8200 	 *  free it.  This allows buffers to point to e.g. an externally
8201 	 *  allocated structure such as a frame buffer.
8202 	 *
8203 	 *  Unlike strings, no terminator byte (NUL) is guaranteed after the
8204 	 *  data.  This would be convenient, but would pad aligned user buffers
8205 	 *  unnecessarily upwards in size.  For instance, if user code requested
8206 	 *  a 64-byte dynamic buffer, 65 bytes would actually be allocated which
8207 	 *  would then potentially round upwards to perhaps 68 or 72 bytes.
8208 	 */
8209 };
8210 
8211 /* Fixed buffer; data follows struct, with proper alignment guaranteed by
8212  * struct size.
8213  */
8214 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
8215 #pragma pack(push, 8)
8216 #endif
8217 struct duk_hbuffer_fixed {
8218 	/* A union is used here as a portable struct size / alignment trick:
8219 	 * by adding a 32-bit or a 64-bit (unused) union member, the size of
8220 	 * the struct is effectively forced to be a multiple of 4 or 8 bytes
8221 	 * (respectively) without increasing the size of the struct unless
8222 	 * necessary.
8223 	 */
8224 	union {
8225 		struct {
8226 			duk_heaphdr hdr;
8227 #if defined(DUK_USE_BUFLEN16)
8228 			/* Stored in duk_heaphdr unused flags. */
8229 #else
8230 			duk_size_t size;
8231 #endif
8232 		} s;
8233 #if (DUK_USE_ALIGN_BY == 4)
8234 		duk_uint32_t dummy_for_align4;
8235 #elif (DUK_USE_ALIGN_BY == 8)
8236 		duk_double_t dummy_for_align8_1;
8237 #if defined(DUK_USE_64BIT_OPS)
8238 		duk_uint64_t dummy_for_align8_2;
8239 #endif
8240 #elif (DUK_USE_ALIGN_BY == 1)
8241 		/* no extra padding */
8242 #else
8243 #error invalid DUK_USE_ALIGN_BY
8244 #endif
8245 	} u;
8246 
8247 	/*
8248 	 *  Data follows the struct header.  The struct size is padded by the
8249 	 *  compiler based on the struct members.  This guarantees that the
8250 	 *  buffer data will be aligned-by-4 but not necessarily aligned-by-8.
8251 	 *
8252 	 *  On platforms where alignment does not matter, the struct padding
8253 	 *  could be removed (if there is any).  On platforms where alignment
8254 	 *  by 8 is required, the struct size must be forced to be a multiple
8255 	 *  of 8 by some means.  Without it, some user code may break, and also
8256 	 *  Duktape itself breaks (e.g. the compiler stores duk_tvals in a
8257 	 *  dynamic buffer).
8258 	 */
8259 }
8260 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR)
8261 __attribute__ ((aligned (8)))
8262 #elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR)
8263 __attribute__ ((aligned (8)))
8264 #endif
8265 ;
8266 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
8267 #pragma pack(pop)
8268 #endif
8269 
8270 /* Dynamic buffer with 'curr_alloc' pointing to a dynamic area allocated using
8271  * heap allocation primitives.  Also used for external buffers when low memory
8272  * options are not used.
8273  */
8274 struct duk_hbuffer_dynamic {
8275 	duk_heaphdr hdr;
8276 
8277 #if defined(DUK_USE_BUFLEN16)
8278 	/* Stored in duk_heaphdr unused flags. */
8279 #else
8280 	duk_size_t size;
8281 #endif
8282 
8283 #if defined(DUK_USE_HEAPPTR16)
8284 	/* Stored in duk_heaphdr h_extra16. */
8285 #else
8286 	void *curr_alloc;  /* may be NULL if alloc_size == 0 */
8287 #endif
8288 
8289 	/*
8290 	 *  Allocation size for 'curr_alloc' is alloc_size.  There is no
8291 	 *  automatic NUL terminator for buffers (see above for rationale).
8292 	 *
8293 	 *  'curr_alloc' is explicitly allocated with heap allocation
8294 	 *  primitives and will thus always have alignment suitable for
8295 	 *  e.g. duk_tval and an IEEE double.
8296 	 */
8297 };
8298 
8299 /* External buffer with 'curr_alloc' managed by user code and pointing to an
8300  * arbitrary address.  When heap pointer compression is not used, this struct
8301  * has the same layout as duk_hbuffer_dynamic.
8302  */
8303 struct duk_hbuffer_external {
8304 	duk_heaphdr hdr;
8305 
8306 #if defined(DUK_USE_BUFLEN16)
8307 	/* Stored in duk_heaphdr unused flags. */
8308 #else
8309 	duk_size_t size;
8310 #endif
8311 
8312 	/* Cannot be compressed as a heap pointer because may point to
8313 	 * an arbitrary address.
8314 	 */
8315 	void *curr_alloc;  /* may be NULL if alloc_size == 0 */
8316 };
8317 
8318 /*
8319  *  Prototypes
8320  */
8321 
8322 DUK_INTERNAL_DECL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata);
8323 DUK_INTERNAL_DECL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud);  /* indirect allocs */
8324 
8325 /* dynamic buffer ops */
8326 DUK_INTERNAL_DECL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size);
8327 DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf);
8328 
8329 #endif  /* DUK_HBUFFER_H_INCLUDED */
8330 /* #include duk_hproxy.h */
8331 /*
8332  *  Proxy object representation.
8333  */
8334 
8335 #if !defined(DUK_HPROXY_H_INCLUDED)
8336 #define DUK_HPROXY_H_INCLUDED
8337 
8338 #if defined(DUK_USE_ASSERTIONS)
8339 DUK_INTERNAL_DECL void duk_hproxy_assert_valid(duk_hproxy *h);
8340 #define DUK_HPROXY_ASSERT_VALID(h)  do { duk_hproxy_assert_valid((h)); } while (0)
8341 #else
8342 #define DUK_HPROXY_ASSERT_VALID(h)  do {} while (0)
8343 #endif
8344 
8345 struct duk_hproxy {
8346 	/* Shared object part. */
8347 	duk_hobject obj;
8348 
8349 	/* Proxy target object. */
8350 	duk_hobject *target;
8351 
8352 	/* Proxy handlers (traps). */
8353 	duk_hobject *handler;
8354 };
8355 
8356 #endif  /* DUK_HPROXY_H_INCLUDED */
8357 /* #include duk_heap.h */
8358 /*
8359  *  Heap structure.
8360  *
8361  *  Heap contains allocated heap objects, interned strings, and built-in
8362  *  strings for one or more threads.
8363  */
8364 
8365 #if !defined(DUK_HEAP_H_INCLUDED)
8366 #define DUK_HEAP_H_INCLUDED
8367 
8368 /* alloc function typedefs in duktape.h */
8369 
8370 /*
8371  *  Heap flags
8372  */
8373 
8374 #define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED            (1U << 0)  /* mark-and-sweep marking reached a recursion limit and must use multi-pass marking */
8375 #define DUK_HEAP_FLAG_INTERRUPT_RUNNING                        (1U << 1)  /* executor interrupt running (used to avoid nested interrupts) */
8376 #define DUK_HEAP_FLAG_FINALIZER_NORESCUE                       (1U << 2)  /* heap destruction ongoing, finalizer rescue no longer possible */
8377 #define DUK_HEAP_FLAG_DEBUGGER_PAUSED                          (1U << 3)  /* debugger is paused: talk with debug client until step/resume */
8378 
8379 #define DUK__HEAP_HAS_FLAGS(heap,bits)               ((heap)->flags & (bits))
8380 #define DUK__HEAP_SET_FLAGS(heap,bits)  do { \
8381 		(heap)->flags |= (bits); \
8382 	} while (0)
8383 #define DUK__HEAP_CLEAR_FLAGS(heap,bits)  do { \
8384 		(heap)->flags &= ~(bits); \
8385 	} while (0)
8386 
8387 #define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)   DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
8388 #define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap)               DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
8389 #define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)              DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
8390 #define DUK_HEAP_HAS_DEBUGGER_PAUSED(heap)                 DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
8391 
8392 #define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap)   DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
8393 #define DUK_HEAP_SET_INTERRUPT_RUNNING(heap)               DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
8394 #define DUK_HEAP_SET_FINALIZER_NORESCUE(heap)              DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
8395 #define DUK_HEAP_SET_DEBUGGER_PAUSED(heap)                 DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
8396 
8397 #define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
8398 #define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap)             DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
8399 #define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap)            DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
8400 #define DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap)               DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
8401 
8402 /*
8403  *  Longjmp types, also double as identifying continuation type for a rethrow (in 'finally')
8404  */
8405 
8406 #define DUK_LJ_TYPE_UNKNOWN      0    /* unused */
8407 #define DUK_LJ_TYPE_THROW        1    /* value1 -> error object */
8408 #define DUK_LJ_TYPE_YIELD        2    /* value1 -> yield value, iserror -> error / normal */
8409 #define DUK_LJ_TYPE_RESUME       3    /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */
8410 #define DUK_LJ_TYPE_BREAK        4    /* value1 -> label number, pseudo-type to indicate a break continuation (for ENDFIN) */
8411 #define DUK_LJ_TYPE_CONTINUE     5    /* value1 -> label number, pseudo-type to indicate a continue continuation (for ENDFIN) */
8412 #define DUK_LJ_TYPE_RETURN       6    /* value1 -> return value, pseudo-type to indicate a return continuation (for ENDFIN) */
8413 #define DUK_LJ_TYPE_NORMAL       7    /* no value, pseudo-type to indicate a normal continuation (for ENDFIN) */
8414 
8415 /*
8416  *  Mark-and-sweep flags
8417  *
8418  *  These are separate from heap level flags now but could be merged.
8419  *  The heap structure only contains a 'base mark-and-sweep flags'
8420  *  field and the GC caller can impose further flags.
8421  */
8422 
8423 /* Emergency mark-and-sweep: try extra hard, even at the cost of
8424  * performance.
8425  */
8426 #define DUK_MS_FLAG_EMERGENCY                (1U << 0)
8427 
8428 /* Voluntary mark-and-sweep: triggered periodically. */
8429 #define DUK_MS_FLAG_VOLUNTARY                (1U << 1)
8430 
8431 /* Postpone rescue decisions for reachable objects with FINALIZED set.
8432  * Used during finalize_list processing to avoid incorrect rescue
8433  * decisions due to finalize_list being a reachability root.
8434  */
8435 #define DUK_MS_FLAG_POSTPONE_RESCUE          (1U << 2)
8436 
8437 /* Don't compact objects; needed during object property table resize
8438  * to prevent a recursive resize.  It would suffice to protect only the
8439  * current object being resized, but this is not yet implemented.
8440  */
8441 #define DUK_MS_FLAG_NO_OBJECT_COMPACTION     (1U << 3)
8442 
8443 /*
8444  *  Thread switching
8445  *
8446  *  To switch heap->curr_thread, use the macro below so that interrupt counters
8447  *  get updated correctly.  The macro allows a NULL target thread because that
8448  *  happens e.g. in call handling.
8449  */
8450 
8451 #if defined(DUK_USE_INTERRUPT_COUNTER)
8452 #define DUK_HEAP_SWITCH_THREAD(heap,newthr)  duk_heap_switch_thread((heap), (newthr))
8453 #else
8454 #define DUK_HEAP_SWITCH_THREAD(heap,newthr)  do { \
8455 		(heap)->curr_thread = (newthr); \
8456 	} while (0)
8457 #endif
8458 
8459 /*
8460  *  Stats
8461  */
8462 
8463 #if defined(DUK_USE_DEBUG)
8464 #define DUK_STATS_INC(heap,fieldname) do { \
8465 		(heap)->fieldname += 1; \
8466 	} while (0)
8467 #else
8468 #define DUK_STATS_INC(heap,fieldname) do {} while (0)
8469 #endif
8470 
8471 /*
8472  *  Other heap related defines
8473  */
8474 
8475 /* Mark-and-sweep interval is relative to combined count of objects and
8476  * strings kept in the heap during the latest mark-and-sweep pass.
8477  * Fixed point .8 multiplier and .0 adder.  Trigger count (interval) is
8478  * decreased by each (re)allocation attempt (regardless of size), and each
8479  * refzero processed object.
8480  *
8481  * 'SKIP' indicates how many (re)allocations to wait until a retry if
8482  * GC is skipped because there is no thread do it with yet (happens
8483  * only during init phases).
8484  */
8485 #if defined(DUK_USE_REFERENCE_COUNTING)
8486 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT              12800L  /* 50x heap size */
8487 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD               1024L
8488 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP              256L
8489 #else
8490 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT              256L    /* 1x heap size */
8491 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD               1024L
8492 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP              256L
8493 #endif
8494 
8495 /* GC torture. */
8496 #if defined(DUK_USE_GC_TORTURE)
8497 #define DUK_GC_TORTURE(heap) do { duk_heap_mark_and_sweep((heap), 0); } while (0)
8498 #else
8499 #define DUK_GC_TORTURE(heap) do { } while (0)
8500 #endif
8501 
8502 /* Stringcache is used for speeding up char-offset-to-byte-offset
8503  * translations for non-ASCII strings.
8504  */
8505 #define DUK_HEAP_STRCACHE_SIZE                            4
8506 #define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT                16  /* strings up to the this length are not cached */
8507 
8508 /* Some list management macros. */
8509 #define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr)     duk_heap_insert_into_heap_allocated((heap), (hdr))
8510 #if defined(DUK_USE_REFERENCE_COUNTING)
8511 #define DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap,hdr)     duk_heap_remove_from_heap_allocated((heap), (hdr))
8512 #endif
8513 #if defined(DUK_USE_FINALIZER_SUPPORT)
8514 #define DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap,hdr)      duk_heap_insert_into_finalize_list((heap), (hdr))
8515 #define DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap,hdr)      duk_heap_remove_from_finalize_list((heap), (hdr))
8516 #endif
8517 
8518 /*
8519  *  Built-in strings
8520  */
8521 
8522 /* heap string indices are autogenerated in duk_strings.h */
8523 #if defined(DUK_USE_ROM_STRINGS)
8524 #define DUK_HEAP_GET_STRING(heap,idx) \
8525 	((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
8526 #else  /* DUK_USE_ROM_STRINGS */
8527 #if defined(DUK_USE_HEAPPTR16)
8528 #define DUK_HEAP_GET_STRING(heap,idx) \
8529 	((duk_hstring *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (heap)->strs16[(idx)]))
8530 #else
8531 #define DUK_HEAP_GET_STRING(heap,idx) \
8532 	((heap)->strs[(idx)])
8533 #endif
8534 #endif  /* DUK_USE_ROM_STRINGS */
8535 
8536 /*
8537  *  Raw memory calls: relative to heap, but no GC interaction
8538  */
8539 
8540 #define DUK_ALLOC_RAW(heap,size) \
8541 	((heap)->alloc_func((heap)->heap_udata, (size)))
8542 
8543 #define DUK_REALLOC_RAW(heap,ptr,newsize) \
8544 	((heap)->realloc_func((heap)->heap_udata, (void *) (ptr), (newsize)))
8545 
8546 #define DUK_FREE_RAW(heap,ptr) \
8547 	((heap)->free_func((heap)->heap_udata, (void *) (ptr)))
8548 
8549 /*
8550  *  Memory calls: relative to heap, GC interaction, but no error throwing.
8551  *
8552  *  XXX: Currently a mark-and-sweep triggered by memory allocation will run
8553  *  using the heap->heap_thread.  This thread is also used for running
8554  *  mark-and-sweep finalization; this is not ideal because it breaks the
8555  *  isolation between multiple global environments.
8556  *
8557  *  Notes:
8558  *
8559  *    - DUK_FREE() is required to ignore NULL and any other possible return
8560  *      value of a zero-sized alloc/realloc (same as ANSI C free()).
8561  *
8562  *    - There is no DUK_REALLOC_ZEROED because we don't assume to know the
8563  *      old size.  Caller must zero the reallocated memory.
8564  *
8565  *    - DUK_REALLOC_INDIRECT() must be used when a mark-and-sweep triggered
8566  *      by an allocation failure might invalidate the original 'ptr', thus
8567  *      causing a realloc retry to use an invalid pointer.  Example: we're
8568  *      reallocating the value stack and a finalizer resizes the same value
8569  *      stack during mark-and-sweep.  The indirect variant requests for the
8570  *      current location of the pointer being reallocated using a callback
8571  *      right before every realloc attempt; this circuitous approach is used
8572  *      to avoid strict aliasing issues in a more straightforward indirect
8573  *      pointer (void **) approach.  Note: the pointer in the storage
8574  *      location is read but is NOT updated; the caller must do that.
8575  */
8576 
8577 /* callback for indirect reallocs, request for current pointer */
8578 typedef void *(*duk_mem_getptr)(duk_heap *heap, void *ud);
8579 
8580 #define DUK_ALLOC(heap,size)                            duk_heap_mem_alloc((heap), (size))
8581 #define DUK_ALLOC_ZEROED(heap,size)                     duk_heap_mem_alloc_zeroed((heap), (size))
8582 #define DUK_REALLOC(heap,ptr,newsize)                   duk_heap_mem_realloc((heap), (ptr), (newsize))
8583 #define DUK_REALLOC_INDIRECT(heap,cb,ud,newsize)        duk_heap_mem_realloc_indirect((heap), (cb), (ud), (newsize))
8584 #define DUK_FREE(heap,ptr)                              duk_heap_mem_free((heap), (ptr))
8585 
8586 /*
8587  *  Checked allocation, relative to a thread
8588  *
8589  *  DUK_FREE_CHECKED() doesn't actually throw, but accepts a 'thr' argument
8590  *  for convenience.
8591  */
8592 
8593 #define DUK_ALLOC_CHECKED(thr,size)                     duk_heap_mem_alloc_checked((thr), (size))
8594 #define DUK_ALLOC_CHECKED_ZEROED(thr,size)              duk_heap_mem_alloc_checked_zeroed((thr), (size))
8595 #define DUK_FREE_CHECKED(thr,ptr)                       duk_heap_mem_free((thr)->heap, (ptr))
8596 
8597 /*
8598  *  Memory constants
8599  */
8600 
8601 #define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT           10  /* Retry allocation after mark-and-sweep for this
8602                                                               * many times.  A single mark-and-sweep round is
8603                                                               * not guaranteed to free all unreferenced memory
8604                                                               * because of finalization (in fact, ANY number of
8605                                                               * rounds is strictly not enough).
8606                                                               */
8607 
8608 #define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT  3  /* Starting from this round, use emergency mode
8609                                                               * for mark-and-sweep.
8610                                                               */
8611 
8612 /*
8613  *  Debugger support
8614  */
8615 
8616 /* Maximum number of breakpoints.  Only breakpoints that are set are
8617  * consulted so increasing this has no performance impact.
8618  */
8619 #define DUK_HEAP_MAX_BREAKPOINTS          16
8620 
8621 /* Opcode interval for a Date-based status/peek rate limit check.  Only
8622  * relevant when debugger is attached.  Requesting a timestamp may be a
8623  * slow operation on some platforms so this shouldn't be too low.  On the
8624  * other hand a high value makes Duktape react to a pause request slowly.
8625  */
8626 #define DUK_HEAP_DBG_RATELIMIT_OPCODES    4000
8627 
8628 /* Milliseconds between status notify and transport peeks. */
8629 #define DUK_HEAP_DBG_RATELIMIT_MILLISECS  200
8630 
8631 /* Debugger pause flags. */
8632 #define DUK_PAUSE_FLAG_ONE_OPCODE        (1U << 0)   /* pause when a single opcode has been executed */
8633 #define DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE (1U << 1)   /* one opcode pause actually active; artifact of current implementation */
8634 #define DUK_PAUSE_FLAG_LINE_CHANGE       (1U << 2)   /* pause when current line number changes */
8635 #define DUK_PAUSE_FLAG_FUNC_ENTRY        (1U << 3)   /* pause when entering a function */
8636 #define DUK_PAUSE_FLAG_FUNC_EXIT         (1U << 4)   /* pause when exiting current function */
8637 #define DUK_PAUSE_FLAG_CAUGHT_ERROR      (1U << 5)   /* pause when about to throw an error that is caught */
8638 #define DUK_PAUSE_FLAG_UNCAUGHT_ERROR    (1U << 6)   /* pause when about to throw an error that won't be caught */
8639 
8640 struct duk_breakpoint {
8641 	duk_hstring *filename;
8642 	duk_uint32_t line;
8643 };
8644 
8645 /*
8646  *  String cache should ideally be at duk_hthread level, but that would
8647  *  cause string finalization to slow down relative to the number of
8648  *  threads; string finalization must check the string cache for "weak"
8649  *  references to the string being finalized to avoid dead pointers.
8650  *
8651  *  Thus, string caches are now at the heap level now.
8652  */
8653 
8654 struct duk_strcache_entry {
8655 	duk_hstring *h;
8656 	duk_uint32_t bidx;
8657 	duk_uint32_t cidx;
8658 };
8659 
8660 /*
8661  *  Longjmp state, contains the information needed to perform a longjmp.
8662  *  Longjmp related values are written to value1, value2, and iserror.
8663  */
8664 
8665 struct duk_ljstate {
8666 	duk_jmpbuf *jmpbuf_ptr;   /* current setjmp() catchpoint */
8667 	duk_small_uint_t type;    /* longjmp type */
8668 	duk_bool_t iserror;       /* isError flag for yield */
8669 	duk_tval value1;          /* 1st related value (type specific) */
8670 	duk_tval value2;          /* 2nd related value (type specific) */
8671 };
8672 
8673 #define DUK_ASSERT_LJSTATE_UNSET(heap) do { \
8674 		DUK_ASSERT(heap != NULL); \
8675 		DUK_ASSERT(heap->lj.type == DUK_LJ_TYPE_UNKNOWN); \
8676 		DUK_ASSERT(heap->lj.iserror == 0); \
8677 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&heap->lj.value1)); \
8678 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&heap->lj.value2)); \
8679 	} while (0)
8680 #define DUK_ASSERT_LJSTATE_SET(heap) do { \
8681 		DUK_ASSERT(heap != NULL); \
8682 		DUK_ASSERT(heap->lj.type != DUK_LJ_TYPE_UNKNOWN); \
8683 	} while (0)
8684 
8685 /*
8686  *  Literal intern cache
8687  */
8688 
8689 struct duk_litcache_entry {
8690 	const duk_uint8_t *addr;
8691 	duk_hstring *h;
8692 };
8693 
8694 /*
8695  *  Main heap structure
8696  */
8697 
8698 #if defined(DUK_USE_ASSERTIONS)
8699 DUK_INTERNAL_DECL void duk_heap_assert_valid(duk_heap *heap);
8700 #define DUK_HEAP_ASSERT_VALID(heap)  do { duk_heap_assert_valid((heap)); } while (0)
8701 #else
8702 #define DUK_HEAP_ASSERT_VALID(heap)  do {} while (0)
8703 #endif
8704 
8705 struct duk_heap {
8706 	duk_small_uint_t flags;
8707 
8708 	/* Allocator functions. */
8709 	duk_alloc_function alloc_func;
8710 	duk_realloc_function realloc_func;
8711 	duk_free_function free_func;
8712 
8713 	/* Heap udata, used for allocator functions but also for other heap
8714 	 * level callbacks like fatal function, pointer compression, etc.
8715 	 */
8716 	void *heap_udata;
8717 
8718 	/* Fatal error handling, called e.g. when a longjmp() is needed but
8719 	 * lj.jmpbuf_ptr is NULL.  fatal_func must never return; it's not
8720 	 * declared as "noreturn" because doing that for typedefs is a bit
8721 	 * challenging portability-wise.
8722 	 */
8723 	duk_fatal_function fatal_func;
8724 
8725 	/* Main list of allocated heap objects.  Objects are either here,
8726 	 * in finalize_list waiting for processing, or in refzero_list
8727 	 * temporarily while a DECREF refzero cascade finishes.
8728 	 */
8729 	duk_heaphdr *heap_allocated;
8730 
8731 	/* Temporary work list for freeing a cascade of objects when a DECREF
8732 	 * (or DECREF_NORZ) encounters a zero refcount.  Using a work list
8733 	 * allows fixed C stack size when refcounts go to zero for a chain of
8734 	 * objects.  Outside of DECREF this is always a NULL because DECREF is
8735 	 * processed without side effects (only memory free calls).
8736 	 */
8737 #if defined(DUK_USE_REFERENCE_COUNTING)
8738 	duk_heaphdr *refzero_list;
8739 #endif
8740 
8741 #if defined(DUK_USE_FINALIZER_SUPPORT)
8742 	/* Work list for objects to be finalized. */
8743 	duk_heaphdr *finalize_list;
8744 #if defined(DUK_USE_ASSERTIONS)
8745 	/* Object whose finalizer is executing right now (no nesting). */
8746 	duk_heaphdr *currently_finalizing;
8747 #endif
8748 #endif
8749 
8750 	/* Freelist for duk_activations and duk_catchers. */
8751 #if defined(DUK_USE_CACHE_ACTIVATION)
8752 	duk_activation *activation_free;
8753 #endif
8754 #if defined(DUK_USE_CACHE_CATCHER)
8755 	duk_catcher *catcher_free;
8756 #endif
8757 
8758 	/* Voluntary mark-and-sweep trigger counter.  Intentionally signed
8759 	 * because we continue decreasing the value when voluntary GC cannot
8760 	 * run.
8761 	 */
8762 #if defined(DUK_USE_VOLUNTARY_GC)
8763 	duk_int_t ms_trigger_counter;
8764 #endif
8765 
8766 	/* Mark-and-sweep recursion control: too deep recursion causes
8767 	 * multi-pass processing to avoid growing C stack without bound.
8768 	 */
8769 	duk_uint_t ms_recursion_depth;
8770 
8771 	/* Mark-and-sweep flags automatically active (used for critical sections). */
8772 	duk_small_uint_t ms_base_flags;
8773 
8774 	/* Mark-and-sweep running flag.  Prevents re-entry, and also causes
8775 	 * refzero events to be ignored (= objects won't be queued to refzero_list).
8776 	 *
8777 	 * 0: mark-and-sweep not running
8778 	 * 1: mark-and-sweep is running
8779 	 * 2: heap destruction active or debugger active, prevent mark-and-sweep
8780 	 *    and refzero processing (but mark-and-sweep not itself running)
8781 	 */
8782 	duk_uint_t ms_running;
8783 
8784 	/* Mark-and-sweep prevent count, stacking.  Used to avoid M&S side
8785 	 * effects (besides finalizers which are controlled separately) such
8786 	 * as compacting the string table or object property tables.  This
8787 	 * is also bumped when ms_running is set to prevent recursive re-entry.
8788 	 * Can also be bumped when mark-and-sweep is not running.
8789 	 */
8790 	duk_uint_t ms_prevent_count;
8791 
8792 	/* Finalizer processing prevent count, stacking.  Bumped when finalizers
8793 	 * are processed to prevent recursive finalizer processing (first call site
8794 	 * processing finalizers handles all finalizers until the list is empty).
8795 	 * Can also be bumped explicitly to prevent finalizer execution.
8796 	 */
8797 	duk_uint_t pf_prevent_count;
8798 
8799 	/* When processing finalize_list, don't actually run finalizers but
8800 	 * queue finalizable objects back to heap_allocated as is.  This is
8801 	 * used during heap destruction to deal with finalizers that keep
8802 	 * on creating more finalizable garbage.
8803 	 */
8804 	duk_uint_t pf_skip_finalizers;
8805 
8806 #if defined(DUK_USE_ASSERTIONS)
8807 	/* Set when we're in a critical path where an error throw would cause
8808 	 * e.g. sandboxing/protected call violations or state corruption.  This
8809 	 * is just used for asserts.
8810 	 */
8811 	duk_bool_t error_not_allowed;
8812 #endif
8813 
8814 #if defined(DUK_USE_ASSERTIONS)
8815 	/* Set when heap is still being initialized, helps with writing
8816 	 * some assertions.
8817 	 */
8818 	duk_bool_t heap_initializing;
8819 #endif
8820 
8821 	/* Marker for detecting internal "double faults", errors thrown when
8822 	 * we're trying to create an error object, see duk_error_throw.c.
8823 	 */
8824 	duk_bool_t creating_error;
8825 
8826 	/* Marker for indicating we're calling a user error augmentation
8827 	 * (errCreate/errThrow) function.  Errors created/thrown during
8828 	 * such a call are not augmented.
8829 	 */
8830 #if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
8831 	duk_bool_t augmenting_error;
8832 #endif
8833 
8834 	/* Longjmp state. */
8835 	duk_ljstate lj;
8836 
8837 	/* Heap thread, used internally and for finalization. */
8838 	duk_hthread *heap_thread;
8839 
8840 	/* Current running thread. */
8841 	duk_hthread *curr_thread;
8842 
8843 	/* Heap level "stash" object (e.g., various reachability roots). */
8844 	duk_hobject *heap_object;
8845 
8846 	/* duk_handle_call / duk_handle_safe_call recursion depth limiting */
8847 	duk_int_t call_recursion_depth;
8848 	duk_int_t call_recursion_limit;
8849 
8850 	/* Mix-in value for computing string hashes; should be reasonably unpredictable. */
8851 	duk_uint32_t hash_seed;
8852 
8853 	/* Random number state for duk_util_tinyrandom.c. */
8854 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
8855 #if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
8856 	duk_uint32_t rnd_state;  /* State for Shamir's three-op algorithm */
8857 #else
8858 	duk_uint64_t rnd_state[2];  /* State for xoroshiro128+ */
8859 #endif
8860 #endif
8861 
8862 	/* Counter for unique local symbol creation. */
8863 	/* XXX: When 64-bit types are available, it would be more efficient to
8864 	 * use a duk_uint64_t at least for incrementing but maybe also for
8865 	 * string formatting in the Symbol constructor.
8866 	 */
8867 	duk_uint32_t sym_counter[2];
8868 
8869 	/* For manual debugging: instruction count based on executor and
8870 	 * interrupt counter book-keeping.  Inspect debug logs to see how
8871 	 * they match up.
8872 	 */
8873 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
8874 	duk_int_t inst_count_exec;
8875 	duk_int_t inst_count_interrupt;
8876 #endif
8877 
8878 	/* Debugger state. */
8879 #if defined(DUK_USE_DEBUGGER_SUPPORT)
8880 	/* Callbacks and udata; dbg_read_cb != NULL is used to indicate attached state. */
8881 	duk_debug_read_function dbg_read_cb;                /* required, NULL implies detached */
8882 	duk_debug_write_function dbg_write_cb;              /* required */
8883 	duk_debug_peek_function dbg_peek_cb;
8884 	duk_debug_read_flush_function dbg_read_flush_cb;
8885 	duk_debug_write_flush_function dbg_write_flush_cb;
8886 	duk_debug_request_function dbg_request_cb;
8887 	duk_debug_detached_function dbg_detached_cb;
8888 	void *dbg_udata;
8889 
8890 	/* The following are only relevant when debugger is attached. */
8891 	duk_bool_t dbg_processing;              /* currently processing messages or breakpoints: don't enter message processing recursively (e.g. no breakpoints when processing debugger eval) */
8892 	duk_bool_t dbg_state_dirty;             /* resend state next time executor is about to run */
8893 	duk_bool_t dbg_force_restart;           /* force executor restart to recheck breakpoints; used to handle function returns (see GH-303) */
8894 	duk_bool_t dbg_detaching;               /* debugger detaching; used to avoid calling detach handler recursively */
8895 	duk_small_uint_t dbg_pause_flags;       /* flags for automatic pause behavior */
8896 	duk_activation *dbg_pause_act;          /* activation related to pause behavior (pause on line change, function entry/exit) */
8897 	duk_uint32_t dbg_pause_startline;       /* starting line number for line change related pause behavior */
8898 	duk_breakpoint dbg_breakpoints[DUK_HEAP_MAX_BREAKPOINTS];  /* breakpoints: [0,breakpoint_count[ gc reachable */
8899 	duk_small_uint_t dbg_breakpoint_count;
8900 	duk_breakpoint *dbg_breakpoints_active[DUK_HEAP_MAX_BREAKPOINTS + 1];  /* currently active breakpoints: NULL term, borrowed pointers */
8901 	/* XXX: make active breakpoints actual copies instead of pointers? */
8902 
8903 	/* These are for rate limiting Status notifications and transport peeking. */
8904 	duk_uint_t dbg_exec_counter;            /* cumulative opcode execution count (overflows are OK) */
8905 	duk_uint_t dbg_last_counter;            /* value of dbg_exec_counter when we last did a Date-based check */
8906 	duk_double_t dbg_last_time;             /* time when status/peek was last done (Date-based rate limit) */
8907 
8908 	/* Used to support single-byte stream lookahead. */
8909 	duk_bool_t dbg_have_next_byte;
8910 	duk_uint8_t dbg_next_byte;
8911 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
8912 #if defined(DUK_USE_ASSERTIONS)
8913 	duk_bool_t dbg_calling_transport;       /* transport call in progress, calling into Duktape forbidden */
8914 #endif
8915 
8916 	/* String intern table (weak refs). */
8917 #if defined(DUK_USE_STRTAB_PTRCOMP)
8918 	duk_uint16_t *strtable16;
8919 #else
8920 	duk_hstring **strtable;
8921 #endif
8922 	duk_uint32_t st_mask;    /* mask for lookup, st_size - 1 */
8923 	duk_uint32_t st_size;    /* stringtable size */
8924 #if (DUK_USE_STRTAB_MINSIZE != DUK_USE_STRTAB_MAXSIZE)
8925 	duk_uint32_t st_count;   /* string count for resize load factor checks */
8926 #endif
8927 	duk_bool_t st_resizing;  /* string table is being resized; avoid recursive resize */
8928 
8929 	/* String access cache (codepoint offset -> byte offset) for fast string
8930 	 * character looping; 'weak' reference which needs special handling in GC.
8931 	 */
8932 	duk_strcache_entry strcache[DUK_HEAP_STRCACHE_SIZE];
8933 
8934 #if defined(DUK_USE_LITCACHE_SIZE)
8935 	/* Literal intern cache.  When enabled, strings interned as literals
8936 	 * (e.g. duk_push_literal()) will be pinned and cached for the lifetime
8937 	 * of the heap.
8938 	 */
8939 	duk_litcache_entry litcache[DUK_USE_LITCACHE_SIZE];
8940 #endif
8941 
8942 	/* Built-in strings. */
8943 #if defined(DUK_USE_ROM_STRINGS)
8944 	/* No field needed when strings are in ROM. */
8945 #else
8946 #if defined(DUK_USE_HEAPPTR16)
8947 	duk_uint16_t strs16[DUK_HEAP_NUM_STRINGS];
8948 #else
8949 	duk_hstring *strs[DUK_HEAP_NUM_STRINGS];
8950 #endif
8951 #endif
8952 
8953 	/* Stats. */
8954 #if defined(DUK_USE_DEBUG)
8955 	duk_int_t stats_exec_opcodes;
8956 	duk_int_t stats_exec_interrupt;
8957 	duk_int_t stats_exec_throw;
8958 	duk_int_t stats_call_all;
8959 	duk_int_t stats_call_tailcall;
8960 	duk_int_t stats_call_ecmatoecma;
8961 	duk_int_t stats_safecall_all;
8962 	duk_int_t stats_safecall_nothrow;
8963 	duk_int_t stats_safecall_throw;
8964 	duk_int_t stats_ms_try_count;
8965 	duk_int_t stats_ms_skip_count;
8966 	duk_int_t stats_ms_emergency_count;
8967 	duk_int_t stats_strtab_intern_hit;
8968 	duk_int_t stats_strtab_intern_miss;
8969 	duk_int_t stats_strtab_resize_check;
8970 	duk_int_t stats_strtab_resize_grow;
8971 	duk_int_t stats_strtab_resize_shrink;
8972 	duk_int_t stats_strtab_litcache_hit;
8973 	duk_int_t stats_strtab_litcache_miss;
8974 	duk_int_t stats_strtab_litcache_pin;
8975 	duk_int_t stats_object_realloc_props;
8976 	duk_int_t stats_object_abandon_array;
8977 	duk_int_t stats_getownpropdesc_count;
8978 	duk_int_t stats_getownpropdesc_hit;
8979 	duk_int_t stats_getownpropdesc_miss;
8980 	duk_int_t stats_getpropdesc_count;
8981 	duk_int_t stats_getpropdesc_hit;
8982 	duk_int_t stats_getpropdesc_miss;
8983 	duk_int_t stats_getprop_all;
8984 	duk_int_t stats_getprop_arrayidx;
8985 	duk_int_t stats_getprop_bufobjidx;
8986 	duk_int_t stats_getprop_bufferidx;
8987 	duk_int_t stats_getprop_bufferlen;
8988 	duk_int_t stats_getprop_stringidx;
8989 	duk_int_t stats_getprop_stringlen;
8990 	duk_int_t stats_getprop_proxy;
8991 	duk_int_t stats_getprop_arguments;
8992 	duk_int_t stats_putprop_all;
8993 	duk_int_t stats_putprop_arrayidx;
8994 	duk_int_t stats_putprop_bufobjidx;
8995 	duk_int_t stats_putprop_bufferidx;
8996 	duk_int_t stats_putprop_proxy;
8997 	duk_int_t stats_getvar_all;
8998 	duk_int_t stats_putvar_all;
8999 	duk_int_t stats_envrec_delayedcreate;
9000 	duk_int_t stats_envrec_create;
9001 	duk_int_t stats_envrec_newenv;
9002 	duk_int_t stats_envrec_oldenv;
9003 	duk_int_t stats_envrec_pushclosure;
9004 #endif
9005 };
9006 
9007 /*
9008  *  Prototypes
9009  */
9010 
9011 DUK_INTERNAL_DECL
9012 duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
9013                          duk_realloc_function realloc_func,
9014                          duk_free_function free_func,
9015                          void *heap_udata,
9016                          duk_fatal_function fatal_func);
9017 DUK_INTERNAL_DECL void duk_heap_free(duk_heap *heap);
9018 DUK_INTERNAL_DECL void duk_free_hobject(duk_heap *heap, duk_hobject *h);
9019 DUK_INTERNAL_DECL void duk_free_hbuffer(duk_heap *heap, duk_hbuffer *h);
9020 DUK_INTERNAL_DECL void duk_free_hstring(duk_heap *heap, duk_hstring *h);
9021 DUK_INTERNAL_DECL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr);
9022 
9023 DUK_INTERNAL_DECL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
9024 #if defined(DUK_USE_REFERENCE_COUNTING)
9025 DUK_INTERNAL_DECL void duk_heap_remove_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
9026 #endif
9027 #if defined(DUK_USE_FINALIZER_SUPPORT)
9028 DUK_INTERNAL_DECL void duk_heap_insert_into_finalize_list(duk_heap *heap, duk_heaphdr *hdr);
9029 DUK_INTERNAL_DECL void duk_heap_remove_from_finalize_list(duk_heap *heap, duk_heaphdr *hdr);
9030 #endif
9031 #if defined(DUK_USE_ASSERTIONS)
9032 DUK_INTERNAL_DECL duk_bool_t duk_heap_in_heap_allocated(duk_heap *heap, duk_heaphdr *ptr);
9033 #endif
9034 #if defined(DUK_USE_INTERRUPT_COUNTER)
9035 DUK_INTERNAL_DECL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr);
9036 #endif
9037 
9038 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);
9039 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len);
9040 #if defined(DUK_USE_LITCACHE_SIZE)
9041 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_literal_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen);
9042 #endif
9043 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_u32(duk_heap *heap, duk_uint32_t val);
9044 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val);
9045 #if defined(DUK_USE_REFERENCE_COUNTING)
9046 DUK_INTERNAL_DECL void duk_heap_strtable_unlink(duk_heap *heap, duk_hstring *h);
9047 #endif
9048 DUK_INTERNAL_DECL void duk_heap_strtable_unlink_prev(duk_heap *heap, duk_hstring *h, duk_hstring *prev);
9049 DUK_INTERNAL_DECL void duk_heap_strtable_force_resize(duk_heap *heap);
9050 DUK_INTERNAL void duk_heap_strtable_free(duk_heap *heap);
9051 #if defined(DUK_USE_DEBUG)
9052 DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap);
9053 #endif
9054 
9055 DUK_INTERNAL_DECL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h);
9056 DUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset);
9057 
9058 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
9059 DUK_INTERNAL_DECL void *duk_default_alloc_function(void *udata, duk_size_t size);
9060 DUK_INTERNAL_DECL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize);
9061 DUK_INTERNAL_DECL void duk_default_free_function(void *udata, void *ptr);
9062 #endif
9063 
9064 DUK_INTERNAL_DECL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size);
9065 DUK_INTERNAL_DECL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size);
9066 DUK_INTERNAL_DECL void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size);
9067 DUK_INTERNAL_DECL void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size);
9068 DUK_INTERNAL_DECL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize);
9069 DUK_INTERNAL_DECL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize);
9070 DUK_INTERNAL_DECL void duk_heap_mem_free(duk_heap *heap, void *ptr);
9071 
9072 DUK_INTERNAL_DECL void duk_heap_free_freelists(duk_heap *heap);
9073 
9074 #if defined(DUK_USE_FINALIZER_SUPPORT)
9075 DUK_INTERNAL_DECL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj);
9076 DUK_INTERNAL_DECL void duk_heap_process_finalize_list(duk_heap *heap);
9077 #endif  /* DUK_USE_FINALIZER_SUPPORT */
9078 
9079 DUK_INTERNAL_DECL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags);
9080 
9081 DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len);
9082 
9083 #endif  /* DUK_HEAP_H_INCLUDED */
9084 /* #include duk_debugger.h */
9085 #if !defined(DUK_DEBUGGER_H_INCLUDED)
9086 #define DUK_DEBUGGER_H_INCLUDED
9087 
9088 /* Debugger protocol version is defined in the public API header. */
9089 
9090 /* Initial bytes for markers. */
9091 #define DUK_DBG_IB_EOM                   0x00
9092 #define DUK_DBG_IB_REQUEST               0x01
9093 #define DUK_DBG_IB_REPLY                 0x02
9094 #define DUK_DBG_IB_ERROR                 0x03
9095 #define DUK_DBG_IB_NOTIFY                0x04
9096 
9097 /* Other initial bytes. */
9098 #define DUK_DBG_IB_INT4                  0x10
9099 #define DUK_DBG_IB_STR4                  0x11
9100 #define DUK_DBG_IB_STR2                  0x12
9101 #define DUK_DBG_IB_BUF4                  0x13
9102 #define DUK_DBG_IB_BUF2                  0x14
9103 #define DUK_DBG_IB_UNUSED                0x15
9104 #define DUK_DBG_IB_UNDEFINED             0x16
9105 #define DUK_DBG_IB_NULL                  0x17
9106 #define DUK_DBG_IB_TRUE                  0x18
9107 #define DUK_DBG_IB_FALSE                 0x19
9108 #define DUK_DBG_IB_NUMBER                0x1a
9109 #define DUK_DBG_IB_OBJECT                0x1b
9110 #define DUK_DBG_IB_POINTER               0x1c
9111 #define DUK_DBG_IB_LIGHTFUNC             0x1d
9112 #define DUK_DBG_IB_HEAPPTR               0x1e
9113 /* The short string/integer initial bytes starting from 0x60 don't have
9114  * defines now.
9115  */
9116 
9117 /* Error codes. */
9118 #define DUK_DBG_ERR_UNKNOWN              0x00
9119 #define DUK_DBG_ERR_UNSUPPORTED          0x01
9120 #define DUK_DBG_ERR_TOOMANY              0x02
9121 #define DUK_DBG_ERR_NOTFOUND             0x03
9122 #define DUK_DBG_ERR_APPLICATION          0x04
9123 
9124 /* Commands and notifys initiated by Duktape. */
9125 #define DUK_DBG_CMD_STATUS               0x01
9126 #define DUK_DBG_CMD_UNUSED_2             0x02  /* Duktape 1.x: print notify */
9127 #define DUK_DBG_CMD_UNUSED_3             0x03  /* Duktape 1.x: alert notify */
9128 #define DUK_DBG_CMD_UNUSED_4             0x04  /* Duktape 1.x: log notify */
9129 #define DUK_DBG_CMD_THROW                0x05
9130 #define DUK_DBG_CMD_DETACHING            0x06
9131 #define DUK_DBG_CMD_APPNOTIFY            0x07
9132 
9133 /* Commands initiated by debug client. */
9134 #define DUK_DBG_CMD_BASICINFO            0x10
9135 #define DUK_DBG_CMD_TRIGGERSTATUS        0x11
9136 #define DUK_DBG_CMD_PAUSE                0x12
9137 #define DUK_DBG_CMD_RESUME               0x13
9138 #define DUK_DBG_CMD_STEPINTO             0x14
9139 #define DUK_DBG_CMD_STEPOVER             0x15
9140 #define DUK_DBG_CMD_STEPOUT              0x16
9141 #define DUK_DBG_CMD_LISTBREAK            0x17
9142 #define DUK_DBG_CMD_ADDBREAK             0x18
9143 #define DUK_DBG_CMD_DELBREAK             0x19
9144 #define DUK_DBG_CMD_GETVAR               0x1a
9145 #define DUK_DBG_CMD_PUTVAR               0x1b
9146 #define DUK_DBG_CMD_GETCALLSTACK         0x1c
9147 #define DUK_DBG_CMD_GETLOCALS            0x1d
9148 #define DUK_DBG_CMD_EVAL                 0x1e
9149 #define DUK_DBG_CMD_DETACH               0x1f
9150 #define DUK_DBG_CMD_DUMPHEAP             0x20
9151 #define DUK_DBG_CMD_GETBYTECODE          0x21
9152 #define DUK_DBG_CMD_APPREQUEST           0x22
9153 #define DUK_DBG_CMD_GETHEAPOBJINFO       0x23
9154 #define DUK_DBG_CMD_GETOBJPROPDESC       0x24
9155 #define DUK_DBG_CMD_GETOBJPROPDESCRANGE  0x25
9156 
9157 /* The low 8 bits map directly to duk_hobject.h DUK_PROPDESC_FLAG_xxx.
9158  * The remaining flags are specific to the debugger.
9159  */
9160 #define DUK_DBG_PROPFLAG_SYMBOL          (1U << 8)
9161 #define DUK_DBG_PROPFLAG_HIDDEN          (1U << 9)
9162 
9163 #if defined(DUK_USE_DEBUGGER_SUPPORT)
9164 DUK_INTERNAL_DECL void duk_debug_do_detach(duk_heap *heap);
9165 
9166 DUK_INTERNAL_DECL duk_bool_t duk_debug_read_peek(duk_hthread *thr);
9167 DUK_INTERNAL_DECL void duk_debug_write_flush(duk_hthread *thr);
9168 
9169 DUK_INTERNAL_DECL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length);
9170 DUK_INTERNAL_DECL void duk_debug_skip_byte(duk_hthread *thr);
9171 
9172 DUK_INTERNAL_DECL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length);
9173 DUK_INTERNAL_DECL duk_uint8_t duk_debug_read_byte(duk_hthread *thr);
9174 DUK_INTERNAL_DECL duk_int32_t duk_debug_read_int(duk_hthread *thr);
9175 DUK_INTERNAL_DECL duk_hstring *duk_debug_read_hstring(duk_hthread *thr);
9176 /* XXX: exposed duk_debug_read_pointer */
9177 /* XXX: exposed duk_debug_read_buffer */
9178 /* XXX: exposed duk_debug_read_hbuffer */
9179 #if 0
9180 DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr);
9181 #endif
9182 #if defined(DUK_USE_DEBUGGER_INSPECT)
9183 DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr);
9184 #endif
9185 DUK_INTERNAL_DECL duk_tval *duk_debug_read_tval(duk_hthread *thr);
9186 
9187 DUK_INTERNAL_DECL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length);
9188 DUK_INTERNAL_DECL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x);
9189 DUK_INTERNAL_DECL void duk_debug_write_unused(duk_hthread *thr);
9190 DUK_INTERNAL_DECL void duk_debug_write_undefined(duk_hthread *thr);
9191 #if defined(DUK_USE_DEBUGGER_INSPECT)
9192 DUK_INTERNAL_DECL void duk_debug_write_null(duk_hthread *thr);
9193 #endif
9194 DUK_INTERNAL_DECL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val);
9195 DUK_INTERNAL_DECL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x);
9196 DUK_INTERNAL_DECL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x);
9197 DUK_INTERNAL_DECL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length);
9198 DUK_INTERNAL_DECL void duk_debug_write_cstring(duk_hthread *thr, const char *data);
9199 DUK_INTERNAL_DECL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h);
9200 DUK_INTERNAL_DECL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length);
9201 DUK_INTERNAL_DECL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h);
9202 DUK_INTERNAL_DECL void duk_debug_write_pointer(duk_hthread *thr, void *ptr);
9203 #if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
9204 DUK_INTERNAL_DECL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h);
9205 #endif
9206 DUK_INTERNAL_DECL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj);
9207 DUK_INTERNAL_DECL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv);
9208 #if 0  /* unused */
9209 DUK_INTERNAL_DECL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command);
9210 #endif
9211 DUK_INTERNAL_DECL void duk_debug_write_reply(duk_hthread *thr);
9212 DUK_INTERNAL_DECL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg);
9213 DUK_INTERNAL_DECL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command);
9214 DUK_INTERNAL_DECL void duk_debug_write_eom(duk_hthread *thr);
9215 
9216 DUK_INTERNAL_DECL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr);
9217 DUK_INTERNAL_DECL void duk_debug_send_status(duk_hthread *thr);
9218 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
9219 DUK_INTERNAL_DECL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal);
9220 #endif
9221 
9222 DUK_INTERNAL_DECL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc);
9223 DUK_INTERNAL_DECL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block);
9224 
9225 DUK_INTERNAL_DECL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line);
9226 DUK_INTERNAL_DECL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index);
9227 
9228 DUK_INTERNAL_DECL duk_bool_t duk_debug_is_attached(duk_heap *heap);
9229 DUK_INTERNAL_DECL duk_bool_t duk_debug_is_paused(duk_heap *heap);
9230 DUK_INTERNAL_DECL void duk_debug_set_paused(duk_heap *heap);
9231 DUK_INTERNAL_DECL void duk_debug_clear_paused(duk_heap *heap);
9232 DUK_INTERNAL_DECL void duk_debug_clear_pause_state(duk_heap *heap);
9233 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
9234 
9235 #endif  /* DUK_DEBUGGER_H_INCLUDED */
9236 /* #include duk_debug.h */
9237 /*
9238  *  Debugging macros, DUK_DPRINT() and its variants in particular.
9239  *
9240  *  DUK_DPRINT() allows formatted debug prints, and supports standard
9241  *  and Duktape specific formatters.  See duk_debug_vsnprintf.c for details.
9242  *
9243  *  DUK_D(x), DUK_DD(x), and DUK_DDD(x) are used together with log macros
9244  *  for technical reasons.  They are concretely used to hide 'x' from the
9245  *  compiler when the corresponding log level is disabled.  This allows
9246  *  clean builds on non-C99 compilers, at the cost of more verbose code.
9247  *  Examples:
9248  *
9249  *    DUK_D(DUK_DPRINT("foo"));
9250  *    DUK_DD(DUK_DDPRINT("foo"));
9251  *    DUK_DDD(DUK_DDDPRINT("foo"));
9252  *
9253  *  This approach is preferable to the old "double parentheses" hack because
9254  *  double parentheses make the C99 solution worse: __FILE__ and __LINE__ can
9255  *  no longer be added transparently without going through globals, which
9256  *  works poorly with threading.
9257  */
9258 
9259 #if !defined(DUK_DEBUG_H_INCLUDED)
9260 #define DUK_DEBUG_H_INCLUDED
9261 
9262 #if defined(DUK_USE_DEBUG)
9263 
9264 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
9265 #define DUK_D(x) x
9266 #else
9267 #define DUK_D(x) do { } while (0) /* omit */
9268 #endif
9269 
9270 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
9271 #define DUK_DD(x) x
9272 #else
9273 #define DUK_DD(x) do { } while (0) /* omit */
9274 #endif
9275 
9276 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
9277 #define DUK_DDD(x) x
9278 #else
9279 #define DUK_DDD(x) do { } while (0) /* omit */
9280 #endif
9281 
9282 /*
9283  *  Exposed debug macros: debugging enabled
9284  */
9285 
9286 #if defined(DUK_USE_VARIADIC_MACROS)
9287 
9288 /* Note: combining __FILE__, __LINE__, and __func__ into fmt would be
9289  * possible compile time, but waste some space with shared function names.
9290  */
9291 #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__);
9292 
9293 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
9294 #define DUK_DPRINT(...)          DUK__DEBUG_LOG(DUK_LEVEL_DEBUG, __VA_ARGS__)
9295 #else
9296 #define DUK_DPRINT(...)
9297 #endif
9298 
9299 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
9300 #define DUK_DDPRINT(...)         DUK__DEBUG_LOG(DUK_LEVEL_DDEBUG, __VA_ARGS__)
9301 #else
9302 #define DUK_DDPRINT(...)
9303 #endif
9304 
9305 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
9306 #define DUK_DDDPRINT(...)        DUK__DEBUG_LOG(DUK_LEVEL_DDDEBUG, __VA_ARGS__)
9307 #else
9308 #define DUK_DDDPRINT(...)
9309 #endif
9310 
9311 #else  /* DUK_USE_VARIADIC_MACROS */
9312 
9313 #define DUK__DEBUG_STASH(lev)    \
9314 	(void) DUK_SNPRINTF(duk_debug_file_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FILE_MACRO), \
9315 	(void) (duk_debug_file_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \
9316 	(void) (duk_debug_line_stash = (duk_int_t) DUK_LINE_MACRO), \
9317 	(void) DUK_SNPRINTF(duk_debug_func_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FUNC_MACRO), \
9318 	(void) (duk_debug_func_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \
9319 	(void) (duk_debug_level_stash = (lev))
9320 
9321 /* Without variadic macros resort to comma expression trickery to handle debug
9322  * prints.  This generates a lot of harmless warnings.  These hacks are not
9323  * needed normally because DUK_D() and friends will hide the entire debug log
9324  * statement from the compiler.
9325  */
9326 
9327 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
9328 #define DUK_DPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DEBUG), (void) duk_debug_log  /* args go here in parens */
9329 #else
9330 #define DUK_DPRINT  0 && /* args go here as a comma expression in parens */
9331 #endif
9332 
9333 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
9334 #define DUK_DDPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DDEBUG), (void) duk_debug_log  /* args go here in parens */
9335 #else
9336 #define DUK_DDPRINT  0 && /* args */
9337 #endif
9338 
9339 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
9340 #define DUK_DDDPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DDDEBUG), (void) duk_debug_log  /* args go here in parens */
9341 #else
9342 #define DUK_DDDPRINT  0 && /* args */
9343 #endif
9344 
9345 #endif  /* DUK_USE_VARIADIC_MACROS */
9346 
9347 #else  /* DUK_USE_DEBUG */
9348 
9349 /*
9350  *  Exposed debug macros: debugging disabled
9351  */
9352 
9353 #define DUK_D(x) do { } while (0) /* omit */
9354 #define DUK_DD(x) do { } while (0) /* omit */
9355 #define DUK_DDD(x) do { } while (0) /* omit */
9356 
9357 #if defined(DUK_USE_VARIADIC_MACROS)
9358 
9359 #define DUK_DPRINT(...)
9360 #define DUK_DDPRINT(...)
9361 #define DUK_DDDPRINT(...)
9362 
9363 #else  /* DUK_USE_VARIADIC_MACROS */
9364 
9365 #define DUK_DPRINT    0 && /* args go here as a comma expression in parens */
9366 #define DUK_DDPRINT   0 && /* args */
9367 #define DUK_DDDPRINT  0 && /* args */
9368 
9369 #endif  /* DUK_USE_VARIADIC_MACROS */
9370 
9371 #endif  /* DUK_USE_DEBUG */
9372 
9373 /*
9374  *  Structs
9375  */
9376 
9377 #if defined(DUK_USE_DEBUG)
9378 struct duk_fixedbuffer {
9379 	duk_uint8_t *buffer;
9380 	duk_size_t length;
9381 	duk_size_t offset;
9382 	duk_bool_t truncated;
9383 };
9384 #endif
9385 
9386 /*
9387  *  Prototypes
9388  */
9389 
9390 #if defined(DUK_USE_DEBUG)
9391 DUK_INTERNAL_DECL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap);
9392 #if 0  /*unused*/
9393 DUK_INTERNAL_DECL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...);
9394 #endif
9395 DUK_INTERNAL_DECL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size);
9396 
9397 #if defined(DUK_USE_VARIADIC_MACROS)
9398 DUK_INTERNAL_DECL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...);
9399 #else  /* DUK_USE_VARIADIC_MACROS */
9400 /* parameter passing, not thread safe */
9401 #define DUK_DEBUG_STASH_SIZE  128
9402 #if !defined(DUK_SINGLE_FILE)
9403 DUK_INTERNAL_DECL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
9404 DUK_INTERNAL_DECL duk_int_t duk_debug_line_stash;
9405 DUK_INTERNAL_DECL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
9406 DUK_INTERNAL_DECL duk_int_t duk_debug_level_stash;
9407 #endif
9408 DUK_INTERNAL_DECL void duk_debug_log(const char *fmt, ...);
9409 #endif  /* DUK_USE_VARIADIC_MACROS */
9410 
9411 DUK_INTERNAL_DECL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length);
9412 DUK_INTERNAL_DECL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x);
9413 DUK_INTERNAL_DECL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x);
9414 DUK_INTERNAL_DECL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...);
9415 DUK_INTERNAL_DECL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size);
9416 DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
9417 
9418 #endif  /* DUK_USE_DEBUG */
9419 
9420 #endif  /* DUK_DEBUG_H_INCLUDED */
9421 /* #include duk_error.h */
9422 /*
9423  *  Error handling macros, assertion macro, error codes.
9424  *
9425  *  There are three types of 'errors':
9426  *
9427  *    1. Ordinary errors relative to a thread, cause a longjmp, catchable.
9428  *    2. Fatal errors relative to a heap, cause fatal handler to be called.
9429  *    3. Fatal errors without context, cause the default (not heap specific)
9430  *       fatal handler to be called.
9431  *
9432  *  Fatal errors without context are used by debug code such as assertions.
9433  *  By providing a fatal error handler for a Duktape heap, user code can
9434  *  avoid fatal errors without context in non-debug builds.
9435  */
9436 
9437 #if !defined(DUK_ERROR_H_INCLUDED)
9438 #define DUK_ERROR_H_INCLUDED
9439 
9440 /*
9441  *  Error codes: defined in duktape.h
9442  *
9443  *  Error codes are used as a shorthand to throw exceptions from inside
9444  *  the implementation.  The appropriate ECMAScript object is constructed
9445  *  based on the code.  ECMAScript code throws objects directly.  The error
9446  *  codes are defined in the public API header because they are also used
9447  *  by calling code.
9448  */
9449 
9450 /*
9451  *  Normal error
9452  *
9453  *  Normal error is thrown with a longjmp() through the current setjmp()
9454  *  catchpoint record in the duk_heap.  The 'curr_thread' of the duk_heap
9455  *  identifies the throwing thread.
9456  *
9457  *  Error formatting is usually unnecessary.  The error macros provide a
9458  *  zero argument version (no formatting) and separate macros for small
9459  *  argument counts.  Variadic macros are not used to avoid portability
9460  *  issues and avoid the need for stash-based workarounds when they're not
9461  *  available.  Vararg calls are avoided for non-formatted error calls
9462  *  because vararg call sites are larger than normal, and there are a lot
9463  *  of call sites with no formatting.
9464  *
9465  *  Note that special formatting provided by debug macros is NOT available.
9466  *
9467  *  The _RAW variants allow the caller to specify file and line.  This makes
9468  *  it easier to write checked calls which want to use the call site of the
9469  *  checked function, not the error macro call inside the checked function.
9470  */
9471 
9472 #if defined(DUK_USE_VERBOSE_ERRORS)
9473 
9474 /* Because there are quite many call sites, pack error code (require at most
9475  * 8-bit) into a single argument.
9476  */
9477 #define DUK_ERROR(thr,err,msg) do { \
9478 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9479 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9480 		duk_err_handle_error((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
9481 	} while (0)
9482 #define DUK_ERROR_RAW(thr,file,line,err,msg) do { \
9483 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9484 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9485 		duk_err_handle_error((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
9486 	} while (0)
9487 
9488 #define DUK_ERROR_FMT1(thr,err,fmt,arg1) do { \
9489 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9490 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9491 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
9492 	} while (0)
9493 #define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) do { \
9494 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9495 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9496 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
9497 	} while (0)
9498 
9499 #define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) do { \
9500 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9501 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9502 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
9503 	} while (0)
9504 #define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) do { \
9505 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9506 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9507 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
9508 	} while (0)
9509 
9510 #define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) do { \
9511 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9512 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9513 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
9514 	} while (0)
9515 #define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) do { \
9516 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9517 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9518 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
9519 	} while (0)
9520 
9521 #define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) do { \
9522 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9523 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9524 		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)); \
9525 	} while (0)
9526 #define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) do { \
9527 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9528 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9529 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3), (arg4)); \
9530 	} while (0)
9531 
9532 #else  /* DUK_USE_VERBOSE_ERRORS */
9533 
9534 #define DUK_ERROR(thr,err,msg)                    duk_err_handle_error((thr), (err))
9535 #define DUK_ERROR_RAW(thr,file,line,err,msg)      duk_err_handle_error((thr), (err))
9536 
9537 #define DUK_ERROR_FMT1(thr,err,fmt,arg1) DUK_ERROR((thr),(err),(fmt))
9538 #define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9539 
9540 #define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) DUK_ERROR((thr),(err),(fmt))
9541 #define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9542 
9543 #define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) DUK_ERROR((thr),(err),(fmt))
9544 #define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9545 
9546 #define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR((thr),(err),(fmt))
9547 #define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9548 
9549 #endif  /* DUK_USE_VERBOSE_ERRORS */
9550 
9551 /*
9552  *  Fatal error without context
9553  *
9554  *  The macro is an expression to make it compatible with DUK_ASSERT_EXPR().
9555  */
9556 
9557 #define DUK_FATAL_WITHOUT_CONTEXT(msg) \
9558 	duk_default_fatal_handler(NULL, (msg))
9559 
9560 /*
9561  *  Error throwing helpers
9562  *
9563  *  The goal is to provide verbose and configurable error messages.  Call
9564  *  sites should be clean in source code and compile to a small footprint.
9565  *  Small footprint is also useful for performance because small cold paths
9566  *  reduce code cache pressure.  Adding macros here only makes sense if there
9567  *  are enough call sites to get concrete benefits.
9568  *
9569  *  DUK_ERROR_xxx() macros are generic and can be used anywhere.
9570  *
9571  *  DUK_DCERROR_xxx() macros can only be used in Duktape/C functions where
9572  *  the "return DUK_RET_xxx;" shorthand is available for low memory targets.
9573  *  The DUK_DCERROR_xxx() macros always either throw or perform a
9574  *  'return DUK_RET_xxx' from the calling function.
9575  */
9576 
9577 #if defined(DUK_USE_VERBOSE_ERRORS)
9578 /* Verbose errors with key/value summaries (non-paranoid) or without key/value
9579  * summaries (paranoid, for some security sensitive environments), the paranoid
9580  * vs. non-paranoid distinction affects only a few specific errors.
9581  */
9582 #if defined(DUK_USE_PARANOID_ERRORS)
9583 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
9584 		duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \
9585 	} while (0)
9586 #else  /* DUK_USE_PARANOID_ERRORS */
9587 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
9588 		duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \
9589 	} while (0)
9590 #endif  /* DUK_USE_PARANOID_ERRORS */
9591 
9592 #define DUK_ERROR_INTERNAL(thr) do { \
9593 		duk_err_error_internal((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9594 	} while (0)
9595 #define DUK_DCERROR_INTERNAL(thr) do { \
9596 		DUK_ERROR_INTERNAL((thr)); \
9597 		return 0; \
9598 	} while (0)
9599 #define DUK_ERROR_ALLOC_FAILED(thr) do { \
9600 		duk_err_error_alloc_failed((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9601 	} while (0)
9602 #define DUK_ERROR_UNSUPPORTED(thr) do { \
9603 		DUK_ERROR((thr), DUK_ERR_ERROR, DUK_STR_UNSUPPORTED); \
9604 	} while (0)
9605 #define DUK_DCERROR_UNSUPPORTED(thr) do { \
9606 		DUK_ERROR_UNSUPPORTED((thr)); \
9607 		return 0; \
9608 	} while (0)
9609 #define DUK_ERROR_ERROR(thr,msg) do { \
9610 		duk_err_error((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
9611 	} while (0)
9612 #define DUK_ERROR_RANGE_INDEX(thr,idx) do { \
9613 		duk_err_range_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx)); \
9614 	} while (0)
9615 #define DUK_ERROR_RANGE_PUSH_BEYOND(thr) do { \
9616 		duk_err_range_push_beyond((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9617 	} while (0)
9618 #define DUK_ERROR_RANGE_INVALID_ARGS(thr) do { \
9619 		DUK_ERROR_RANGE((thr), DUK_STR_INVALID_ARGS); \
9620 	} while (0)
9621 #define DUK_DCERROR_RANGE_INVALID_ARGS(thr) do { \
9622 		DUK_ERROR_RANGE_INVALID_ARGS((thr)); \
9623 		return 0; \
9624 	} while (0)
9625 #define DUK_ERROR_RANGE_INVALID_COUNT(thr) do { \
9626 		DUK_ERROR_RANGE((thr), DUK_STR_INVALID_COUNT); \
9627 	} while (0)
9628 #define DUK_DCERROR_RANGE_INVALID_COUNT(thr) do { \
9629 		DUK_ERROR_RANGE_INVALID_COUNT((thr)); \
9630 		return 0; \
9631 	} while (0)
9632 #define DUK_ERROR_RANGE_INVALID_LENGTH(thr) do { \
9633 		DUK_ERROR_RANGE((thr), DUK_STR_INVALID_LENGTH); \
9634 	} while (0)
9635 #define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) do { \
9636 		DUK_ERROR_RANGE_INVALID_LENGTH((thr)); \
9637 		return 0; \
9638 	} while (0)
9639 #define DUK_ERROR_RANGE(thr,msg) do { \
9640 		duk_err_range((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
9641 	} while (0)
9642 #define DUK_ERROR_EVAL(thr,msg) do { \
9643 		DUK_ERROR((thr), DUK_ERR_EVAL_ERROR, (msg)); \
9644 	} while (0)
9645 #define DUK_ERROR_REFERENCE(thr,msg) do { \
9646 		DUK_ERROR((thr), DUK_ERR_REFERENCE_ERROR, (msg)); \
9647 	} while (0)
9648 #define DUK_ERROR_SYNTAX(thr,msg) do { \
9649 		DUK_ERROR((thr), DUK_ERR_SYNTAX_ERROR, (msg)); \
9650 	} while (0)
9651 #define DUK_ERROR_TYPE_INVALID_ARGS(thr) do { \
9652 		duk_err_type_invalid_args((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9653 	} while (0)
9654 #define DUK_DCERROR_TYPE_INVALID_ARGS(thr) do { \
9655 		DUK_ERROR_TYPE_INVALID_ARGS((thr)); \
9656 		return 0; \
9657 	} while (0)
9658 #define DUK_ERROR_TYPE_INVALID_STATE(thr) do { \
9659 		duk_err_type_invalid_state((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9660 	} while (0)
9661 #define DUK_DCERROR_TYPE_INVALID_STATE(thr) do { \
9662 		DUK_ERROR_TYPE_INVALID_STATE((thr)); \
9663 		return 0; \
9664 	} while (0)
9665 #define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9666 		duk_err_type_invalid_trap_result((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9667 	} while (0)
9668 #define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9669 		DUK_ERROR_TYPE((thr), DUK_STR_INVALID_TRAP_RESULT); \
9670 	} while (0)
9671 #define DUK_ERROR_TYPE(thr,msg) do { \
9672 		DUK_ERROR((thr), DUK_ERR_TYPE_ERROR, (msg)); \
9673 	} while (0)
9674 #define DUK_ERROR_URI(thr,msg) do { \
9675 		DUK_ERROR((thr), DUK_ERR_URI_ERROR, (msg)); \
9676 	} while (0)
9677 #else  /* DUK_USE_VERBOSE_ERRORS */
9678 /* Non-verbose errors for low memory targets: no file, line, or message. */
9679 
9680 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
9681 		duk_err_type((thr)); \
9682 	} while (0)
9683 
9684 #define DUK_ERROR_INTERNAL(thr) do { \
9685 		duk_err_error((thr)); \
9686 	} while (0)
9687 #define DUK_DCERROR_INTERNAL(thr) do { \
9688 		DUK_UNREF((thr)); \
9689 		return DUK_RET_ERROR; \
9690 	} while (0)
9691 #define DUK_ERROR_ALLOC_FAILED(thr) do { \
9692 		duk_err_error((thr)); \
9693 	} while (0)
9694 #define DUK_ERROR_UNSUPPORTED(thr) do { \
9695 		duk_err_error((thr)); \
9696 	} while (0)
9697 #define DUK_DCERROR_UNSUPPORTED(thr) do { \
9698 		DUK_UNREF((thr)); \
9699 		return DUK_RET_ERROR; \
9700 	} while (0)
9701 #define DUK_ERROR_ERROR(thr,msg) do { \
9702 		duk_err_error((thr)); \
9703 	} while (0)
9704 #define DUK_ERROR_RANGE_INDEX(thr,idx) do { \
9705 		duk_err_range((thr)); \
9706 	} while (0)
9707 #define DUK_ERROR_RANGE_PUSH_BEYOND(thr) do { \
9708 		duk_err_range((thr)); \
9709 	} while (0)
9710 #define DUK_ERROR_RANGE_INVALID_ARGS(thr) do { \
9711 		duk_err_range((thr)); \
9712 	} while (0)
9713 #define DUK_DCERROR_RANGE_INVALID_ARGS(thr) do { \
9714 		DUK_UNREF((thr)); \
9715 		return DUK_RET_RANGE_ERROR; \
9716 	} while (0)
9717 #define DUK_ERROR_RANGE_INVALID_COUNT(thr) do { \
9718 		duk_err_range((thr)); \
9719 	} while (0)
9720 #define DUK_DCERROR_RANGE_INVALID_COUNT(thr) do { \
9721 		DUK_UNREF((thr)); \
9722 		return DUK_RET_RANGE_ERROR; \
9723 	} while (0)
9724 #define DUK_ERROR_RANGE_INVALID_LENGTH(thr) do { \
9725 		duk_err_range((thr)); \
9726 	} while (0)
9727 #define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) do { \
9728 		DUK_UNREF((thr)); \
9729 		return DUK_RET_RANGE_ERROR; \
9730 	} while (0)
9731 #define DUK_ERROR_RANGE(thr,msg) do { \
9732 		duk_err_range((thr)); \
9733 	} while (0)
9734 #define DUK_ERROR_EVAL(thr,msg) do { \
9735 		duk_err_eval((thr)); \
9736 	} while (0)
9737 #define DUK_ERROR_REFERENCE(thr,msg) do { \
9738 		duk_err_reference((thr)); \
9739 	} while (0)
9740 #define DUK_ERROR_SYNTAX(thr,msg) do { \
9741 		duk_err_syntax((thr)); \
9742 	} while (0)
9743 #define DUK_ERROR_TYPE_INVALID_ARGS(thr) do { \
9744 		duk_err_type((thr)); \
9745 	} while (0)
9746 #define DUK_DCERROR_TYPE_INVALID_ARGS(thr) do { \
9747 		DUK_UNREF((thr)); \
9748 		return DUK_RET_TYPE_ERROR; \
9749 	} while (0)
9750 #define DUK_ERROR_TYPE_INVALID_STATE(thr) do { \
9751 		duk_err_type((thr)); \
9752 	} while (0)
9753 #define DUK_DCERROR_TYPE_INVALID_STATE(thr) do { \
9754 		duk_err_type((thr)); \
9755 	} while (0)
9756 #define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9757 		duk_err_type((thr)); \
9758 	} while (0)
9759 #define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9760 		DUK_UNREF((thr)); \
9761 		return DUK_RET_TYPE_ERROR; \
9762 	} while (0)
9763 #define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9764 		duk_err_type((thr)); \
9765 	} while (0)
9766 #define DUK_ERROR_TYPE(thr,msg) do { \
9767 		duk_err_type((thr)); \
9768 	} while (0)
9769 #define DUK_ERROR_URI(thr,msg) do { \
9770 		duk_err_uri((thr)); \
9771 	} while (0)
9772 #endif  /* DUK_USE_VERBOSE_ERRORS */
9773 
9774 /*
9775  *  Assert macro: failure causes a fatal error.
9776  *
9777  *  NOTE: since the assert macro doesn't take a heap/context argument, there's
9778  *  no way to look up a heap/context specific fatal error handler which may have
9779  *  been given by the application.  Instead, assertion failures always use the
9780  *  internal default fatal error handler; it can be replaced via duk_config.h
9781  *  and then applies to all Duktape heaps.
9782  */
9783 
9784 #if defined(DUK_USE_ASSERTIONS)
9785 
9786 /* The message should be a compile time constant without formatting (less risk);
9787  * we don't care about assertion text size because they're not used in production
9788  * builds.
9789  */
9790 #define DUK_ASSERT(x)  do { \
9791 	if (!(x)) { \
9792 		DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x \
9793 			" (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"); \
9794 	} \
9795 	} while (0)
9796 
9797 /* Assertion compatible inside a comma expression, evaluates to void. */
9798 #define DUK_ASSERT_EXPR(x) \
9799 	((void) ((x) ? 0 : (DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x \
9800 				" (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"), 0)))
9801 
9802 #else  /* DUK_USE_ASSERTIONS */
9803 
9804 #define DUK_ASSERT(x)  do { /* assertion omitted */ } while (0)
9805 
9806 #define DUK_ASSERT_EXPR(x)  ((void) 0)
9807 
9808 #endif  /* DUK_USE_ASSERTIONS */
9809 
9810 /* this variant is used when an assert would generate a compile warning by
9811  * being always true (e.g. >= 0 comparison for an unsigned value
9812  */
9813 #define DUK_ASSERT_DISABLE(x)  do { /* assertion disabled */ } while (0)
9814 
9815 /*
9816  *  Assertion helpers
9817  */
9818 
9819 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
9820 #define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)  do { \
9821 		DUK_ASSERT((h) == NULL || DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) (h)) > 0); \
9822 	} while (0)
9823 #define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)  do { \
9824 		if ((tv) != NULL && DUK_TVAL_IS_HEAP_ALLOCATED((tv))) { \
9825 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(DUK_TVAL_GET_HEAPHDR((tv))) > 0); \
9826 		} \
9827 	} while (0)
9828 #else
9829 #define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)  /* no refcount check */
9830 #define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)    /* no refcount check */
9831 #endif
9832 
9833 #define DUK_ASSERT_TOP(ctx,n)  DUK_ASSERT((duk_idx_t) duk_get_top((ctx)) == (duk_idx_t) (n))
9834 
9835 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_PACKED_TVAL)
9836 #define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)  do { \
9837 		duk_double_union duk__assert_tmp_du; \
9838 		duk__assert_tmp_du.d = (dval); \
9839 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&duk__assert_tmp_du)); \
9840 	} while (0)
9841 #else
9842 #define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)  /* nop */
9843 #endif
9844 
9845 #define DUK_ASSERT_VS_SPACE(thr) \
9846 	DUK_ASSERT(thr->valstack_top < thr->valstack_end)
9847 
9848 /*
9849  *  Helper to initialize a memory area (e.g. struct) with garbage when
9850  *  assertions enabled.
9851  */
9852 
9853 #if defined(DUK_USE_ASSERTIONS)
9854 #define DUK_ASSERT_SET_GARBAGE(ptr,size) do { \
9855 		duk_memset_unsafe((void *) (ptr), 0x5a, size); \
9856 	} while (0)
9857 #else
9858 #define DUK_ASSERT_SET_GARBAGE(ptr,size) do {} while (0)
9859 #endif
9860 
9861 /*
9862  *  Helper for valstack space
9863  *
9864  *  Caller of DUK_ASSERT_VALSTACK_SPACE() estimates the number of free stack entries
9865  *  required for its own use, and any child calls which are not (a) Duktape API calls
9866  *  or (b) Duktape calls which involve extending the valstack (e.g. getter call).
9867  */
9868 
9869 #define DUK_VALSTACK_ASSERT_EXTRA  5  /* this is added to checks to allow for Duktape
9870                                        * API calls in addition to function's own use
9871                                        */
9872 #if defined(DUK_USE_ASSERTIONS)
9873 #define DUK_ASSERT_VALSTACK_SPACE(thr,n)   do { \
9874 		DUK_ASSERT((thr) != NULL); \
9875 		DUK_ASSERT((thr)->valstack_end - (thr)->valstack_top >= (n) + DUK_VALSTACK_ASSERT_EXTRA); \
9876 	} while (0)
9877 #else
9878 #define DUK_ASSERT_VALSTACK_SPACE(thr,n)   /* no valstack space check */
9879 #endif
9880 
9881 /*
9882  *  Prototypes
9883  */
9884 
9885 #if defined(DUK_USE_VERBOSE_ERRORS)
9886 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));
9887 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, ...));
9888 #else  /* DUK_USE_VERBOSE_ERRORS */
9889 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code));
9890 #endif  /* DUK_USE_VERBOSE_ERRORS */
9891 
9892 #if defined(DUK_USE_VERBOSE_ERRORS)
9893 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));
9894 #else
9895 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code));
9896 #endif
9897 
9898 DUK_NORETURN(DUK_INTERNAL_DECL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc));
9899 
9900 #define DUK_AUGMENT_FLAG_NOBLAME_FILELINE  (1U << 0)  /* if set, don't blame C file/line for .fileName and .lineNumber */
9901 #define DUK_AUGMENT_FLAG_SKIP_ONE          (1U << 1)  /* if set, skip topmost activation in traceback construction */
9902 
9903 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
9904 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);
9905 #endif
9906 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
9907 DUK_INTERNAL_DECL void duk_err_augment_error_throw(duk_hthread *thr);
9908 #endif
9909 
9910 #if defined(DUK_USE_VERBOSE_ERRORS)
9911 #if defined(DUK_USE_PARANOID_ERRORS)
9912 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));
9913 #else
9914 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));
9915 #endif
9916 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber));
9917 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber));
9918 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
9919 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx));
9920 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber));
9921 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
9922 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber));
9923 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber));
9924 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber));
9925 #else  /* DUK_VERBOSE_ERRORS */
9926 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr));
9927 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr));
9928 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_eval(duk_hthread *thr));
9929 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_reference(duk_hthread *thr));
9930 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_syntax(duk_hthread *thr));
9931 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type(duk_hthread *thr));
9932 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_uri(duk_hthread *thr));
9933 #endif /* DUK_VERBOSE_ERRORS */
9934 
9935 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_longjmp(duk_hthread *thr));
9936 
9937 DUK_NORETURN(DUK_INTERNAL_DECL void duk_default_fatal_handler(void *udata, const char *msg));
9938 
9939 DUK_INTERNAL_DECL void duk_err_setup_ljstate1(duk_hthread *thr, duk_small_uint_t lj_type, duk_tval *tv_val);
9940 #if defined(DUK_USE_DEBUGGER_SUPPORT)
9941 DUK_INTERNAL_DECL void duk_err_check_debugger_integration(duk_hthread *thr);
9942 #endif
9943 
9944 DUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t err_code);
9945 
9946 #endif  /* DUK_ERROR_H_INCLUDED */
9947 /* #include duk_unicode.h */
9948 /*
9949  *  Unicode helpers
9950  */
9951 
9952 #if !defined(DUK_UNICODE_H_INCLUDED)
9953 #define DUK_UNICODE_H_INCLUDED
9954 
9955 /*
9956  *  UTF-8 / XUTF-8 / CESU-8 constants
9957  */
9958 
9959 #define DUK_UNICODE_MAX_XUTF8_LENGTH      7   /* up to 36 bit codepoints */
9960 #define DUK_UNICODE_MAX_XUTF8_BMP_LENGTH  3   /* all codepoints up to U+FFFF */
9961 #define DUK_UNICODE_MAX_CESU8_LENGTH      6   /* all codepoints up to U+10FFFF */
9962 #define DUK_UNICODE_MAX_CESU8_BMP_LENGTH  3   /* all codepoints up to U+FFFF */
9963 
9964 /*
9965  *  Useful Unicode codepoints
9966  *
9967  *  Integer constants must be signed to avoid unexpected coercions
9968  *  in comparisons.
9969  */
9970 
9971 #define DUK_UNICODE_CP_ZWNJ                   0x200cL  /* zero-width non-joiner */
9972 #define DUK_UNICODE_CP_ZWJ                    0x200dL  /* zero-width joiner */
9973 #define DUK_UNICODE_CP_REPLACEMENT_CHARACTER  0xfffdL  /* http://en.wikipedia.org/wiki/Replacement_character#Replacement_character */
9974 
9975 /*
9976  *  ASCII character constants
9977  *
9978  *  C character literals like 'x' have a platform specific value and do
9979  *  not match ASCII (UTF-8) values on e.g. EBCDIC platforms.  So, use
9980  *  these (admittedly awkward) constants instead.  These constants must
9981  *  also have signed values to avoid unexpected coercions in comparisons.
9982  *
9983  *  http://en.wikipedia.org/wiki/ASCII
9984  */
9985 
9986 #define DUK_ASC_NUL              0x00
9987 #define DUK_ASC_SOH              0x01
9988 #define DUK_ASC_STX              0x02
9989 #define DUK_ASC_ETX              0x03
9990 #define DUK_ASC_EOT              0x04
9991 #define DUK_ASC_ENQ              0x05
9992 #define DUK_ASC_ACK              0x06
9993 #define DUK_ASC_BEL              0x07
9994 #define DUK_ASC_BS               0x08
9995 #define DUK_ASC_HT               0x09
9996 #define DUK_ASC_LF               0x0a
9997 #define DUK_ASC_VT               0x0b
9998 #define DUK_ASC_FF               0x0c
9999 #define DUK_ASC_CR               0x0d
10000 #define DUK_ASC_SO               0x0e
10001 #define DUK_ASC_SI               0x0f
10002 #define DUK_ASC_DLE              0x10
10003 #define DUK_ASC_DC1              0x11
10004 #define DUK_ASC_DC2              0x12
10005 #define DUK_ASC_DC3              0x13
10006 #define DUK_ASC_DC4              0x14
10007 #define DUK_ASC_NAK              0x15
10008 #define DUK_ASC_SYN              0x16
10009 #define DUK_ASC_ETB              0x17
10010 #define DUK_ASC_CAN              0x18
10011 #define DUK_ASC_EM               0x19
10012 #define DUK_ASC_SUB              0x1a
10013 #define DUK_ASC_ESC              0x1b
10014 #define DUK_ASC_FS               0x1c
10015 #define DUK_ASC_GS               0x1d
10016 #define DUK_ASC_RS               0x1e
10017 #define DUK_ASC_US               0x1f
10018 #define DUK_ASC_SPACE            0x20
10019 #define DUK_ASC_EXCLAMATION      0x21
10020 #define DUK_ASC_DOUBLEQUOTE      0x22
10021 #define DUK_ASC_HASH             0x23
10022 #define DUK_ASC_DOLLAR           0x24
10023 #define DUK_ASC_PERCENT          0x25
10024 #define DUK_ASC_AMP              0x26
10025 #define DUK_ASC_SINGLEQUOTE      0x27
10026 #define DUK_ASC_LPAREN           0x28
10027 #define DUK_ASC_RPAREN           0x29
10028 #define DUK_ASC_STAR             0x2a
10029 #define DUK_ASC_PLUS             0x2b
10030 #define DUK_ASC_COMMA            0x2c
10031 #define DUK_ASC_MINUS            0x2d
10032 #define DUK_ASC_PERIOD           0x2e
10033 #define DUK_ASC_SLASH            0x2f
10034 #define DUK_ASC_0                0x30
10035 #define DUK_ASC_1                0x31
10036 #define DUK_ASC_2                0x32
10037 #define DUK_ASC_3                0x33
10038 #define DUK_ASC_4                0x34
10039 #define DUK_ASC_5                0x35
10040 #define DUK_ASC_6                0x36
10041 #define DUK_ASC_7                0x37
10042 #define DUK_ASC_8                0x38
10043 #define DUK_ASC_9                0x39
10044 #define DUK_ASC_COLON            0x3a
10045 #define DUK_ASC_SEMICOLON        0x3b
10046 #define DUK_ASC_LANGLE           0x3c
10047 #define DUK_ASC_EQUALS           0x3d
10048 #define DUK_ASC_RANGLE           0x3e
10049 #define DUK_ASC_QUESTION         0x3f
10050 #define DUK_ASC_ATSIGN           0x40
10051 #define DUK_ASC_UC_A             0x41
10052 #define DUK_ASC_UC_B             0x42
10053 #define DUK_ASC_UC_C             0x43
10054 #define DUK_ASC_UC_D             0x44
10055 #define DUK_ASC_UC_E             0x45
10056 #define DUK_ASC_UC_F             0x46
10057 #define DUK_ASC_UC_G             0x47
10058 #define DUK_ASC_UC_H             0x48
10059 #define DUK_ASC_UC_I             0x49
10060 #define DUK_ASC_UC_J             0x4a
10061 #define DUK_ASC_UC_K             0x4b
10062 #define DUK_ASC_UC_L             0x4c
10063 #define DUK_ASC_UC_M             0x4d
10064 #define DUK_ASC_UC_N             0x4e
10065 #define DUK_ASC_UC_O             0x4f
10066 #define DUK_ASC_UC_P             0x50
10067 #define DUK_ASC_UC_Q             0x51
10068 #define DUK_ASC_UC_R             0x52
10069 #define DUK_ASC_UC_S             0x53
10070 #define DUK_ASC_UC_T             0x54
10071 #define DUK_ASC_UC_U             0x55
10072 #define DUK_ASC_UC_V             0x56
10073 #define DUK_ASC_UC_W             0x57
10074 #define DUK_ASC_UC_X             0x58
10075 #define DUK_ASC_UC_Y             0x59
10076 #define DUK_ASC_UC_Z             0x5a
10077 #define DUK_ASC_LBRACKET         0x5b
10078 #define DUK_ASC_BACKSLASH        0x5c
10079 #define DUK_ASC_RBRACKET         0x5d
10080 #define DUK_ASC_CARET            0x5e
10081 #define DUK_ASC_UNDERSCORE       0x5f
10082 #define DUK_ASC_GRAVE            0x60
10083 #define DUK_ASC_LC_A             0x61
10084 #define DUK_ASC_LC_B             0x62
10085 #define DUK_ASC_LC_C             0x63
10086 #define DUK_ASC_LC_D             0x64
10087 #define DUK_ASC_LC_E             0x65
10088 #define DUK_ASC_LC_F             0x66
10089 #define DUK_ASC_LC_G             0x67
10090 #define DUK_ASC_LC_H             0x68
10091 #define DUK_ASC_LC_I             0x69
10092 #define DUK_ASC_LC_J             0x6a
10093 #define DUK_ASC_LC_K             0x6b
10094 #define DUK_ASC_LC_L             0x6c
10095 #define DUK_ASC_LC_M             0x6d
10096 #define DUK_ASC_LC_N             0x6e
10097 #define DUK_ASC_LC_O             0x6f
10098 #define DUK_ASC_LC_P             0x70
10099 #define DUK_ASC_LC_Q             0x71
10100 #define DUK_ASC_LC_R             0x72
10101 #define DUK_ASC_LC_S             0x73
10102 #define DUK_ASC_LC_T             0x74
10103 #define DUK_ASC_LC_U             0x75
10104 #define DUK_ASC_LC_V             0x76
10105 #define DUK_ASC_LC_W             0x77
10106 #define DUK_ASC_LC_X             0x78
10107 #define DUK_ASC_LC_Y             0x79
10108 #define DUK_ASC_LC_Z             0x7a
10109 #define DUK_ASC_LCURLY           0x7b
10110 #define DUK_ASC_PIPE             0x7c
10111 #define DUK_ASC_RCURLY           0x7d
10112 #define DUK_ASC_TILDE            0x7e
10113 #define DUK_ASC_DEL              0x7f
10114 
10115 /*
10116  *  Miscellaneous
10117  */
10118 
10119 /* Uppercase A is 0x41, lowercase a is 0x61; OR 0x20 to convert uppercase
10120  * to lowercase.
10121  */
10122 #define DUK_LOWERCASE_CHAR_ASCII(x)  ((x) | 0x20)
10123 
10124 /*
10125  *  Unicode tables
10126  */
10127 
10128 #if defined(DUK_USE_SOURCE_NONBMP)
10129 /*
10130  *  Automatically generated by extract_chars.py, do not edit!
10131  */
10132 
10133 extern const duk_uint8_t duk_unicode_ids_noa[1116];
10134 #else
10135 /*
10136  *  Automatically generated by extract_chars.py, do not edit!
10137  */
10138 
10139 extern const duk_uint8_t duk_unicode_ids_noabmp[625];
10140 #endif
10141 
10142 #if defined(DUK_USE_SOURCE_NONBMP)
10143 /*
10144  *  Automatically generated by extract_chars.py, do not edit!
10145  */
10146 
10147 extern const duk_uint8_t duk_unicode_ids_m_let_noa[42];
10148 #else
10149 /*
10150  *  Automatically generated by extract_chars.py, do not edit!
10151  */
10152 
10153 extern const duk_uint8_t duk_unicode_ids_m_let_noabmp[24];
10154 #endif
10155 
10156 #if defined(DUK_USE_SOURCE_NONBMP)
10157 /*
10158  *  Automatically generated by extract_chars.py, do not edit!
10159  */
10160 
10161 extern const duk_uint8_t duk_unicode_idp_m_ids_noa[576];
10162 #else
10163 /*
10164  *  Automatically generated by extract_chars.py, do not edit!
10165  */
10166 
10167 extern const duk_uint8_t duk_unicode_idp_m_ids_noabmp[358];
10168 #endif
10169 
10170 /*
10171  *  Automatically generated by extract_caseconv.py, do not edit!
10172  */
10173 
10174 extern const duk_uint8_t duk_unicode_caseconv_uc[1411];
10175 extern const duk_uint8_t duk_unicode_caseconv_lc[706];
10176 
10177 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
10178 /*
10179  *  Automatically generated by extract_caseconv.py, do not edit!
10180  */
10181 
10182 extern const duk_uint16_t duk_unicode_re_canon_lookup[65536];
10183 #endif
10184 
10185 #if defined(DUK_USE_REGEXP_CANON_BITMAP)
10186 /*
10187  *  Automatically generated by extract_caseconv.py, do not edit!
10188  */
10189 
10190 #define DUK_CANON_BITMAP_BLKSIZE                                      32
10191 #define DUK_CANON_BITMAP_BLKSHIFT                                     5
10192 #define DUK_CANON_BITMAP_BLKMASK                                      31
10193 extern const duk_uint8_t duk_unicode_re_canon_bitmap[256];
10194 #endif
10195 
10196 /*
10197  *  Extern
10198  */
10199 
10200 /* duk_unicode_support.c */
10201 #if !defined(DUK_SINGLE_FILE)
10202 DUK_INTERNAL_DECL const duk_uint8_t duk_unicode_xutf8_markers[7];
10203 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_digit[2];
10204 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_white[22];
10205 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_wordchar[8];
10206 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_digit[4];
10207 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_white[24];
10208 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10];
10209 DUK_INTERNAL_DECL const duk_int8_t duk_is_idchar_tab[128];
10210 #endif  /* !DUK_SINGLE_FILE */
10211 
10212 /*
10213  *  Prototypes
10214  */
10215 
10216 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp);
10217 #if defined(DUK_USE_ASSERTIONS)
10218 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp);
10219 #endif
10220 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out);
10221 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out);
10222 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);
10223 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);
10224 DUK_INTERNAL_DECL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen);
10225 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp);
10226 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp);
10227 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp);
10228 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp);
10229 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp);
10230 DUK_INTERNAL_DECL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase);
10231 #if defined(DUK_USE_REGEXP_SUPPORT)
10232 DUK_INTERNAL_DECL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp);
10233 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp);
10234 #endif
10235 
10236 #endif  /* DUK_UNICODE_H_INCLUDED */
10237 /* #include duk_json.h */
10238 /*
10239  *  Defines for JSON, especially duk_bi_json.c.
10240  */
10241 
10242 #if !defined(DUK_JSON_H_INCLUDED)
10243 #define DUK_JSON_H_INCLUDED
10244 
10245 /* Encoding/decoding flags */
10246 #define DUK_JSON_FLAG_ASCII_ONLY              (1U << 0)  /* escape any non-ASCII characters */
10247 #define DUK_JSON_FLAG_AVOID_KEY_QUOTES        (1U << 1)  /* avoid key quotes when key is an ASCII Identifier */
10248 #define DUK_JSON_FLAG_EXT_CUSTOM              (1U << 2)  /* extended types: custom encoding */
10249 #define DUK_JSON_FLAG_EXT_COMPATIBLE          (1U << 3)  /* extended types: compatible encoding */
10250 
10251 /* How much stack to require on entry to object/array encode */
10252 #define DUK_JSON_ENC_REQSTACK                 32
10253 
10254 /* How much stack to require on entry to object/array decode */
10255 #define DUK_JSON_DEC_REQSTACK                 32
10256 
10257 /* How large a loop detection stack to use */
10258 #define DUK_JSON_ENC_LOOPARRAY                64
10259 
10260 /* Encoding state.  Heap object references are all borrowed. */
10261 typedef struct {
10262 	duk_hthread *thr;
10263 	duk_bufwriter_ctx bw;        /* output bufwriter */
10264 	duk_hobject *h_replacer;     /* replacer function */
10265 	duk_hstring *h_gap;          /* gap (if empty string, NULL) */
10266 	duk_idx_t idx_proplist;      /* explicit PropertyList */
10267 	duk_idx_t idx_loop;          /* valstack index of loop detection object */
10268 	duk_small_uint_t flags;
10269 	duk_small_uint_t flag_ascii_only;
10270 	duk_small_uint_t flag_avoid_key_quotes;
10271 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
10272 	duk_small_uint_t flag_ext_custom;
10273 	duk_small_uint_t flag_ext_compatible;
10274 	duk_small_uint_t flag_ext_custom_or_compatible;
10275 #endif
10276 	duk_uint_t recursion_depth;
10277 	duk_uint_t recursion_limit;
10278 	duk_uint_t mask_for_undefined;      /* type bit mask: types which certainly produce 'undefined' */
10279 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
10280 	duk_small_uint_t stridx_custom_undefined;
10281 	duk_small_uint_t stridx_custom_nan;
10282 	duk_small_uint_t stridx_custom_neginf;
10283 	duk_small_uint_t stridx_custom_posinf;
10284 	duk_small_uint_t stridx_custom_function;
10285 #endif
10286 	duk_hobject *visiting[DUK_JSON_ENC_LOOPARRAY];  /* indexed by recursion_depth */
10287 } duk_json_enc_ctx;
10288 
10289 typedef struct {
10290 	duk_hthread *thr;
10291 	const duk_uint8_t *p;
10292 	const duk_uint8_t *p_start;
10293 	const duk_uint8_t *p_end;
10294 	duk_idx_t idx_reviver;
10295 	duk_small_uint_t flags;
10296 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
10297 	duk_small_uint_t flag_ext_custom;
10298 	duk_small_uint_t flag_ext_compatible;
10299 	duk_small_uint_t flag_ext_custom_or_compatible;
10300 #endif
10301 	duk_int_t recursion_depth;
10302 	duk_int_t recursion_limit;
10303 } duk_json_dec_ctx;
10304 
10305 #endif  /* DUK_JSON_H_INCLUDED */
10306 /* #include duk_js.h */
10307 /*
10308  *  ECMAScript execution, support primitives.
10309  */
10310 
10311 #if !defined(DUK_JS_H_INCLUDED)
10312 #define DUK_JS_H_INCLUDED
10313 
10314 /* Flags for call handling.  Lowest flags must match bytecode DUK_BC_CALL_FLAG_xxx 1:1. */
10315 #define DUK_CALL_FLAG_TAILCALL                 (1U << 0)  /* setup for a tail call */
10316 #define DUK_CALL_FLAG_CONSTRUCT                (1U << 1)  /* constructor call (i.e. called as 'new Foo()') */
10317 #define DUK_CALL_FLAG_CALLED_AS_EVAL           (1U << 2)  /* call was made using the identifier 'eval' */
10318 #define DUK_CALL_FLAG_ALLOW_ECMATOECMA         (1U << 3)  /* ecma-to-ecma call with executor reuse is possible */
10319 #define DUK_CALL_FLAG_DIRECT_EVAL              (1U << 4)  /* call is a direct eval call */
10320 #define DUK_CALL_FLAG_CONSTRUCT_PROXY          (1U << 5)  /* handled via 'construct' proxy trap, check return value invariant(s) */
10321 #define DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED (1U << 6)  /* prototype of 'default instance' updated, temporary flag in call handling */
10322 
10323 /* Flags for duk_js_equals_helper(). */
10324 #define DUK_EQUALS_FLAG_SAMEVALUE            (1U << 0)  /* use SameValue instead of non-strict equality */
10325 #define DUK_EQUALS_FLAG_STRICT               (1U << 1)  /* use strict equality instead of non-strict equality */
10326 
10327 /* Flags for duk_js_compare_helper(). */
10328 #define DUK_COMPARE_FLAG_NEGATE              (1U << 0)  /* negate result */
10329 #define DUK_COMPARE_FLAG_EVAL_LEFT_FIRST     (1U << 1)  /* eval left argument first */
10330 
10331 /* conversions, coercions, comparison, etc */
10332 DUK_INTERNAL_DECL duk_bool_t duk_js_toboolean(duk_tval *tv);
10333 DUK_INTERNAL_DECL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv);
10334 DUK_INTERNAL_DECL duk_double_t duk_js_tointeger_number(duk_double_t x);
10335 DUK_INTERNAL_DECL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv);
10336 DUK_INTERNAL_DECL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv);
10337 DUK_INTERNAL_DECL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv);
10338 DUK_INTERNAL_DECL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv);
10339 DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, duk_uint32_t blen);
10340 #if !defined(DUK_USE_HSTRING_ARRIDX)
10341 DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_hstring_fast_known(duk_hstring *h);
10342 DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h);
10343 #endif
10344 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);
10345 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);
10346 DUK_INTERNAL_DECL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2);
10347 #if 0  /* unused */
10348 DUK_INTERNAL_DECL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2);
10349 #endif
10350 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);
10351 DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
10352 #if defined(DUK_USE_SYMBOL_BUILTIN)
10353 DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof_ordinary(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
10354 #endif
10355 DUK_INTERNAL_DECL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
10356 DUK_INTERNAL_DECL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x);
10357 
10358 /* arithmetic */
10359 DUK_INTERNAL_DECL double duk_js_arith_pow(double x, double y);
10360 DUK_INTERNAL_DECL double duk_js_arith_mod(double x, double y);
10361 
10362 #define duk_js_equals(thr,tv_x,tv_y) \
10363 	duk_js_equals_helper((thr), (tv_x), (tv_y), 0)
10364 #define duk_js_strict_equals(tv_x,tv_y) \
10365 	duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_STRICT)
10366 #define duk_js_samevalue(tv_x,tv_y) \
10367 	duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_SAMEVALUE)
10368 
10369 /* E5 Sections 11.8.1, 11.8.5; x < y */
10370 #define duk_js_lessthan(thr,tv_x,tv_y) \
10371 	duk_js_compare_helper((thr), (tv_x), (tv_Y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
10372 
10373 /* E5 Sections 11.8.2, 11.8.5; x > y  -->  y < x */
10374 #define duk_js_greaterthan(thr,tv_x,tv_y) \
10375 	duk_js_compare_helper((thr), (tv_y), (tv_x), 0)
10376 
10377 /* E5 Sections 11.8.3, 11.8.5; x <= y  -->  not (x > y)  -->  not (y < x) */
10378 #define duk_js_lessthanorequal(thr,tv_x,tv_y) \
10379 	duk_js_compare_helper((thr), (tv_y), (tv_x), DUK_COMPARE_FLAG_NEGATE)
10380 
10381 /* E5 Sections 11.8.4, 11.8.5; x >= y  -->  not (x < y) */
10382 #define duk_js_greaterthanorequal(thr,tv_x,tv_y) \
10383 	duk_js_compare_helper((thr), (tv_x), (tv_y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
10384 
10385 /* identifiers and environment handling */
10386 #if 0  /*unused*/
10387 DUK_INTERNAL duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
10388 #endif
10389 DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_bool_t throw_flag);
10390 DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_bool_t throw_flag);
10391 DUK_INTERNAL_DECL void duk_js_putvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_tval *val, duk_bool_t strict);
10392 DUK_INTERNAL_DECL void duk_js_putvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_bool_t strict);
10393 #if 0  /*unused*/
10394 DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
10395 #endif
10396 DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name);
10397 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);
10398 DUK_INTERNAL_DECL void duk_js_init_activation_environment_records_delayed(duk_hthread *thr, duk_activation *act);
10399 DUK_INTERNAL_DECL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env);
10400 DUK_INTERNAL_DECL duk_hobject *duk_create_activation_environment_record(duk_hthread *thr, duk_hobject *func, duk_size_t bottom_byteoff);
10401 DUK_INTERNAL_DECL void duk_js_push_closure(duk_hthread *thr,
10402                                            duk_hcompfunc *fun_temp,
10403                                            duk_hobject *outer_var_env,
10404                                            duk_hobject *outer_lex_env,
10405                                            duk_bool_t add_auto_proto);
10406 
10407 /* call handling */
10408 DUK_INTERNAL_DECL void duk_native_stack_check(duk_hthread *thr);
10409 DUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected(duk_hthread *thr, duk_idx_t idx_func, duk_small_uint_t call_flags);
10410 DUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags);
10411 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);
10412 DUK_INTERNAL_DECL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uint_t proxy_invariant);
10413 #if defined(DUK_USE_VERBOSE_ERRORS)
10414 DUK_INTERNAL_DECL void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_base, duk_tval *tv_key);
10415 #endif
10416 
10417 /* bytecode execution */
10418 DUK_INTERNAL_DECL void duk_js_execute_bytecode(duk_hthread *exec_thr);
10419 
10420 #endif  /* DUK_JS_H_INCLUDED */
10421 /* #include duk_numconv.h */
10422 /*
10423  *  Number-to-string conversion.  The semantics of these is very tightly
10424  *  bound with the ECMAScript semantics required for call sites.
10425  */
10426 
10427 #if !defined(DUK_NUMCONV_H_INCLUDED)
10428 #define DUK_NUMCONV_H_INCLUDED
10429 
10430 /* Output a specified number of digits instead of using the shortest
10431  * form.  Used for toPrecision() and toFixed().
10432  */
10433 #define DUK_N2S_FLAG_FIXED_FORMAT         (1U << 0)
10434 
10435 /* Force exponential format.  Used for toExponential(). */
10436 #define DUK_N2S_FLAG_FORCE_EXP            (1U << 1)
10437 
10438 /* If number would need zero padding (for whole number part), use
10439  * exponential format instead.  E.g. if input number is 12300, 3
10440  * digits are generated ("123"), output "1.23e+4" instead of "12300".
10441  * Used for toPrecision().
10442  */
10443 #define DUK_N2S_FLAG_NO_ZERO_PAD          (1U << 2)
10444 
10445 /* Digit count indicates number of fractions (i.e. an absolute
10446  * digit index instead of a relative one).  Used together with
10447  * DUK_N2S_FLAG_FIXED_FORMAT for toFixed().
10448  */
10449 #define DUK_N2S_FLAG_FRACTION_DIGITS      (1U << 3)
10450 
10451 /*
10452  *  String-to-number conversion
10453  */
10454 
10455 /* Maximum exponent value when parsing numbers.  This is not strictly
10456  * compliant as there should be no upper limit, but as we parse the
10457  * exponent without a bigint, impose some limit.  The limit should be
10458  * small enough that multiplying it (or limit-1 to be precise) won't
10459  * overflow signed 32-bit integer range.  Exponent is only parsed with
10460  * radix 10, but with maximum radix (36) a safe limit is:
10461  * (10000000*36).toString(16) -> '15752a00'
10462  */
10463 #define DUK_S2N_MAX_EXPONENT              10000000L
10464 
10465 /* Trim white space (= allow leading and trailing whitespace) */
10466 #define DUK_S2N_FLAG_TRIM_WHITE           (1U << 0)
10467 
10468 /* Allow exponent */
10469 #define DUK_S2N_FLAG_ALLOW_EXP            (1U << 1)
10470 
10471 /* Allow trailing garbage (e.g. treat "123foo" as "123) */
10472 #define DUK_S2N_FLAG_ALLOW_GARBAGE        (1U << 2)
10473 
10474 /* Allow leading plus sign */
10475 #define DUK_S2N_FLAG_ALLOW_PLUS           (1U << 3)
10476 
10477 /* Allow leading minus sign */
10478 #define DUK_S2N_FLAG_ALLOW_MINUS          (1U << 4)
10479 
10480 /* Allow 'Infinity' */
10481 #define DUK_S2N_FLAG_ALLOW_INF            (1U << 5)
10482 
10483 /* Allow fraction part */
10484 #define DUK_S2N_FLAG_ALLOW_FRAC           (1U << 6)
10485 
10486 /* Allow naked fraction (e.g. ".123") */
10487 #define DUK_S2N_FLAG_ALLOW_NAKED_FRAC     (1U << 7)
10488 
10489 /* Allow empty fraction (e.g. "123.") */
10490 #define DUK_S2N_FLAG_ALLOW_EMPTY_FRAC     (1U << 8)
10491 
10492 /* Allow empty string to be interpreted as 0 */
10493 #define DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO  (1U << 9)
10494 
10495 /* Allow leading zeroes (e.g. "0123" -> "123") */
10496 #define DUK_S2N_FLAG_ALLOW_LEADING_ZERO   (1U << 10)
10497 
10498 /* Allow automatic detection of hex base ("0x" or "0X" prefix),
10499  * overrides radix argument and forces integer mode.
10500  */
10501 #define DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT   (1U << 11)
10502 
10503 /* Allow automatic detection of legacy octal base ("0n"),
10504  * overrides radix argument and forces integer mode.
10505  */
10506 #define DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT   (1U << 12)
10507 
10508 /* Allow automatic detection of ES2015 octal base ("0o123"),
10509  * overrides radix argument and forces integer mode.
10510  */
10511 #define DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT   (1U << 13)
10512 
10513 /* Allow automatic detection of ES2015 binary base ("0b10001"),
10514  * overrides radix argument and forces integer mode.
10515  */
10516 #define DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT   (1U << 14)
10517 
10518 /*
10519  *  Prototypes
10520  */
10521 
10522 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);
10523 DUK_INTERNAL_DECL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags);
10524 
10525 #endif  /* DUK_NUMCONV_H_INCLUDED */
10526 /* #include duk_bi_protos.h */
10527 /*
10528  *  Prototypes for built-in functions not automatically covered by the
10529  *  header declarations emitted by genbuiltins.py.
10530  */
10531 
10532 #if !defined(DUK_BUILTIN_PROTOS_H_INCLUDED)
10533 #define DUK_BUILTIN_PROTOS_H_INCLUDED
10534 
10535 /* Buffer size needed for ISO 8601 formatting.
10536  * Accurate value is 32 + 1 for NUL termination:
10537  *   >>> len('+123456-01-23T12:34:56.123+12:34')
10538  *   32
10539  * Include additional space to be safe.
10540  */
10541 #define  DUK_BI_DATE_ISO8601_BUFSIZE  40
10542 
10543 /* Helpers exposed for internal use */
10544 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);
10545 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags);
10546 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year);
10547 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x);
10548 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t year);
10549 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x);
10550 /* Built-in providers */
10551 #if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
10552 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_gettimeofday(void);
10553 #endif
10554 #if defined(DUK_USE_DATE_NOW_TIME)
10555 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_time(void);
10556 #endif
10557 #if defined(DUK_USE_DATE_NOW_WINDOWS)
10558 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows(void);
10559 #endif
10560 #if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
10561 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows_subms(void);
10562 #endif
10563 #if defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S) || defined(DUK_USE_DATE_TZO_GMTIME)
10564 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d);
10565 #endif
10566 #if defined(DUK_USE_DATE_TZO_WINDOWS)
10567 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d);
10568 #endif
10569 #if defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST)
10570 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d);
10571 #endif
10572 #if defined(DUK_USE_DATE_PRS_STRPTIME)
10573 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, const char *str);
10574 #endif
10575 #if defined(DUK_USE_DATE_PRS_GETDATE)
10576 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const char *str);
10577 #endif
10578 #if defined(DUK_USE_DATE_FMT_STRFTIME)
10579 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);
10580 #endif
10581 
10582 #if defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)
10583 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_monotonic_time_clock_gettime(void);
10584 #endif
10585 #if defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC)
10586 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void);
10587 #endif
10588 
10589 DUK_INTERNAL_DECL
10590 void duk_bi_json_parse_helper(duk_hthread *thr,
10591                               duk_idx_t idx_value,
10592                               duk_idx_t idx_reviver,
10593                               duk_small_uint_t flags);
10594 DUK_INTERNAL_DECL
10595 void duk_bi_json_stringify_helper(duk_hthread *thr,
10596                                   duk_idx_t idx_value,
10597                                   duk_idx_t idx_replacer,
10598                                   duk_idx_t idx_space,
10599                                   duk_small_uint_t flags);
10600 
10601 DUK_INTERNAL_DECL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_hthread *thr);
10602 
10603 #if defined(DUK_USE_ES6_PROXY)
10604 DUK_INTERNAL_DECL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h_proxy_target, duk_uint_t flags);
10605 #endif
10606 
10607 #endif  /* DUK_BUILTIN_PROTOS_H_INCLUDED */
10608 /* #include duk_selftest.h */
10609 /*
10610  *  Selftest code
10611  */
10612 
10613 #if !defined(DUK_SELFTEST_H_INCLUDED)
10614 #define DUK_SELFTEST_H_INCLUDED
10615 
10616 #if defined(DUK_USE_SELF_TESTS)
10617 DUK_INTERNAL_DECL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,
10618                                                     duk_realloc_function realloc_func,
10619                                                     duk_free_function free_func,
10620                                                     void *udata);
10621 #endif
10622 
10623 #endif  /* DUK_SELFTEST_H_INCLUDED */
10624 
10625 #endif  /* DUK_INTERNAL_H_INCLUDED */
10626 
10627 #if defined(DUK_USE_COMPUTED_NAN)
10628 DUK_INTERNAL double duk_computed_nan;
10629 #endif
10630 
10631 #if defined(DUK_USE_COMPUTED_INFINITY)
10632 DUK_INTERNAL double duk_computed_infinity;
10633 #endif
10634 
10635 #if defined(DUK_USE_REPL_FPCLASSIFY)
duk_repl_fpclassify(double x)10636 DUK_INTERNAL int duk_repl_fpclassify(double x) {
10637 	duk_double_union u;
10638 	duk_uint_fast16_t expt;
10639 	duk_small_int_t mzero;
10640 
10641 	u.d = x;
10642 	expt = (duk_uint_fast16_t) (u.us[DUK_DBL_IDX_US0] & 0x7ff0UL);
10643 	if (expt > 0x0000UL && expt < 0x7ff0UL) {
10644 		/* expt values [0x001,0x7fe] = normal */
10645 		return DUK_FP_NORMAL;
10646 	}
10647 
10648 	mzero = (u.ui[DUK_DBL_IDX_UI1] == 0 && (u.ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) == 0);
10649 	if (expt == 0x0000UL) {
10650 		/* expt 0x000 is zero/subnormal */
10651 		if (mzero) {
10652 			return DUK_FP_ZERO;
10653 		} else {
10654 			return DUK_FP_SUBNORMAL;
10655 		}
10656 	} else {
10657 		/* expt 0xfff is infinite/nan */
10658 		if (mzero) {
10659 			return DUK_FP_INFINITE;
10660 		} else {
10661 			return DUK_FP_NAN;
10662 		}
10663 	}
10664 }
10665 #endif
10666 
10667 #if defined(DUK_USE_REPL_SIGNBIT)
duk_repl_signbit(double x)10668 DUK_INTERNAL int duk_repl_signbit(double x) {
10669 	duk_double_union u;
10670 	u.d = x;
10671 	return (int) (u.uc[DUK_DBL_IDX_UC0] & 0x80UL);
10672 }
10673 #endif
10674 
10675 #if defined(DUK_USE_REPL_ISFINITE)
duk_repl_isfinite(double x)10676 DUK_INTERNAL int duk_repl_isfinite(double x) {
10677 	int c = DUK_FPCLASSIFY(x);
10678 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
10679 		return 0;
10680 	} else {
10681 		return 1;
10682 	}
10683 }
10684 #endif
10685 
10686 #if defined(DUK_USE_REPL_ISNAN)
duk_repl_isnan(double x)10687 DUK_INTERNAL int duk_repl_isnan(double x) {
10688 	int c = DUK_FPCLASSIFY(x);
10689 	return (c == DUK_FP_NAN);
10690 }
10691 #endif
10692 
10693 #if defined(DUK_USE_REPL_ISINF)
duk_repl_isinf(double x)10694 DUK_INTERNAL int duk_repl_isinf(double x) {
10695 	int c = DUK_FPCLASSIFY(x);
10696 	return (c == DUK_FP_INFINITE);
10697 }
10698 #endif
10699 /*
10700  *  Debugging macro calls.
10701  */
10702 
10703 /* #include duk_internal.h -> already included */
10704 
10705 #if defined(DUK_USE_DEBUG)
10706 
10707 /*
10708  *  Debugging enabled
10709  */
10710 
10711 #include <stdio.h>
10712 #include <stdlib.h>
10713 #include <stdarg.h>
10714 
10715 #if !defined(DUK_USE_DEBUG_WRITE)
10716 #error debugging enabled (DUK_USE_DEBUG) but DUK_USE_DEBUG_WRITE not defined
10717 #endif
10718 
10719 #define DUK__DEBUG_BUFSIZE  DUK_USE_DEBUG_BUFSIZE
10720 
10721 #if defined(DUK_USE_VARIADIC_MACROS)
10722 
duk_debug_log(duk_int_t level,const char * file,duk_int_t line,const char * func,const char * fmt,...)10723 DUK_INTERNAL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...) {
10724 	va_list ap;
10725 	long arg_level;
10726 	const char *arg_file;
10727 	long arg_line;
10728 	const char *arg_func;
10729 	const char *arg_msg;
10730 	char buf[DUK__DEBUG_BUFSIZE];
10731 
10732 	va_start(ap, fmt);
10733 
10734 	duk_memzero((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
10735 	duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
10736 
10737 	arg_level = (long) level;
10738 	arg_file = (const char *) file;
10739 	arg_line = (long) line;
10740 	arg_func = (const char *) func;
10741 	arg_msg = (const char *) buf;
10742 	DUK_USE_DEBUG_WRITE(arg_level, arg_file, arg_line, arg_func, arg_msg);
10743 
10744 	va_end(ap);
10745 }
10746 
10747 #else  /* DUK_USE_VARIADIC_MACROS */
10748 
10749 DUK_INTERNAL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
10750 DUK_INTERNAL duk_int_t duk_debug_line_stash;
10751 DUK_INTERNAL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
10752 DUK_INTERNAL duk_int_t duk_debug_level_stash;
10753 
duk_debug_log(const char * fmt,...)10754 DUK_INTERNAL void duk_debug_log(const char *fmt, ...) {
10755 	va_list ap;
10756 	long arg_level;
10757 	const char *arg_file;
10758 	long arg_line;
10759 	const char *arg_func;
10760 	const char *arg_msg;
10761 	char buf[DUK__DEBUG_BUFSIZE];
10762 
10763 	va_start(ap, fmt);
10764 
10765 	duk_memzero((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
10766 	duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
10767 
10768 	arg_level = (long) duk_debug_level_stash;
10769 	arg_file = (const char *) duk_debug_file_stash;
10770 	arg_line = (long) duk_debug_line_stash;
10771 	arg_func = (const char *) duk_debug_func_stash;
10772 	arg_msg = (const char *) buf;
10773 	DUK_USE_DEBUG_WRITE(arg_level, arg_file, arg_line, arg_func, arg_msg);
10774 
10775 	va_end(ap);
10776 }
10777 
10778 #endif  /* DUK_USE_VARIADIC_MACROS */
10779 
10780 #else  /* DUK_USE_DEBUG */
10781 
10782 /*
10783  *  Debugging disabled
10784  */
10785 
10786 #endif  /* DUK_USE_DEBUG */
10787 
10788 /* automatic undefs */
10789 #undef DUK__DEBUG_BUFSIZE
10790 /*
10791  *  Automatically generated by genbuiltins.py, do not edit!
10792  */
10793 
10794 /* #include duk_internal.h -> already included */
10795 
10796 #if defined(DUK_USE_ASSERTIONS)
10797 #define DUK__REFCINIT(refc) 0 /*h_assert_refcount*/, (refc) /*actual*/
10798 #else
10799 #define DUK__REFCINIT(refc) (refc) /*actual*/
10800 #endif
10801 
10802 #if defined(DUK_USE_ROM_STRINGS)
10803 #error ROM support not enabled, rerun configure.py with --rom-support
10804 #else  /* DUK_USE_ROM_STRINGS */
10805 DUK_INTERNAL const duk_uint8_t duk_strings_data[967] = {
10806 79,40,209,144,168,105,6,78,54,139,89,185,44,48,46,90,120,8,154,140,35,103,
10807 35,113,193,73,5,52,112,180,104,166,135,52,188,4,98,12,27,146,156,80,211,31,
10808 129,115,150,64,52,220,109,24,18,68,156,24,38,67,114,36,55,9,119,151,132,
10809 140,93,18,113,128,153,201,212,201,205,2,248,8,196,24,224,104,82,146,40,224,
10810 193,48,114,168,37,147,196,54,123,28,4,98,12,43,148,67,103,177,192,70,32,
10811 196,121,68,54,123,28,18,192,199,144,124,4,98,12,43,136,108,244,117,184,8,
10812 196,24,95,40,134,207,71,91,128,140,65,133,113,13,158,158,151,1,24,131,11,
10813 229,16,217,233,233,112,17,136,48,206,21,110,4,244,244,184,8,196,24,103,10,
10814 183,2,122,218,156,4,98,12,24,203,112,64,179,113,193,79,8,218,155,131,32,
10815 184,70,212,220,13,10,82,68,252,123,144,217,146,38,228,207,18,0,100,37,64,
10816 178,212,11,161,17,104,162,96,10,200,193,57,165,65,169,16,5,100,81,27,70,18,
10817 32,10,200,68,185,13,116,221,197,184,64,89,57,41,197,13,49,234,5,208,156,
10818 113,87,55,118,147,20,187,56,161,166,92,221,212,73,210,236,226,134,153,115,
10819 119,76,201,203,179,138,26,99,73,212,136,136,164,25,174,137,56,32,72,137,
10820 101,23,52,45,13,34,86,9,79,136,104,201,114,149,96,52,138,134,140,151,75,
10821 226,233,186,120,121,22,39,54,83,141,5,55,68,236,36,164,3,16,225,115,150,64,
10822 52,205,163,2,72,154,83,138,26,99,75,12,11,150,103,5,36,20,211,70,140,133,
10823 67,72,49,241,160,227,81,196,52,168,106,39,132,252,183,136,105,80,212,79,2,
10824 249,110,128,126,88,95,133,109,237,237,237,151,235,127,46,249,119,203,190,
10825 186,206,33,181,2,208,61,190,12,19,34,65,19,81,132,108,228,97,1,107,33,12,
10826 32,45,100,137,64,247,175,9,19,155,41,198,130,155,134,69,146,100,227,226,
10827 231,146,51,192,204,73,140,224,145,221,102,241,68,196,169,248,30,75,12,11,
10828 151,242,233,187,143,138,24,137,162,164,255,253,63,3,201,97,129,114,254,92,
10829 112,75,136,108,166,6,136,159,255,167,224,121,44,48,46,95,203,166,238,74,
10830 113,67,77,201,128,223,255,223,224,121,44,48,46,95,203,145,46,9,205,16,39,
10831 201,62,36,0,192,21,147,255,238,145,39,199,197,211,116,240,242,113,197,78,
10832 214,211,226,233,187,107,105,19,119,37,56,161,166,52,221,212,201,205,36,240,
10833 242,16,96,152,12,178,52,211,56,228,73,150,83,0,148,39,137,75,67,73,198,209,
10834 129,36,85,185,201,196,2,32,193,48,17,160,97,16,84,44,156,104,24,67,189,200,
10835 108,201,19,238,114,96,137,137,50,238,113,164,188,211,185,192,226,100,19,
10836 134,68,110,112,174,139,0,185,31,115,149,4,88,7,159,115,146,117,34,34,35,
10837 115,143,22,146,208,210,19,115,140,3,207,185,202,130,36,109,85,185,194,161,
10838 160,90,50,72,155,115,149,2,232,67,137,204,122,22,66,161,175,164,210,72,199,
10839 130,137,1,50,32,145,143,38,120,186,195,35,106,51,146,230,8,36,77,109,65,38,
10840 226,72,159,191,189,181,70,140,133,222,249,212,227,66,125,245,187,251,219,
10841 77,3,119,190,117,56,208,159,125,110,254,246,210,26,93,239,157,78,52,39,223,
10842 93,191,189,180,212,52,187,223,58,156,104,79,190,187,127,123,104,180,104,
10843 183,190,117,56,208,159,125,102,254,209,104,209,124,234,113,161,62,250,80,
10844 196,128,81,4,9,16,162,4,196,116,9,205,154,27,66,32,100,13,12,98,68,227,33,
10845 65,69,204,195,34,201,50,8,110,33,23,34,28,168,104,22,188,12,174,138,11,70,
10846 138,104,115,68,130,137,13,82,27,41,129,162,35,138,54,146,198,137,39,72,180,
10847 210,178,38,35,146,103,68,139,51,197,214,28,227,131,79,15,35,138,58,130,37,
10848 19,155,41,146,174,64,203,99,161,100,37,145,51,148,75,4,164,66,54,140,49,46,
10849 247,70,103,37,230,70,142,70,67,30,232,204,178,163,201,18,54,139,89,39,26,
10850 16,165,2,228,69,33,143,89,24,70,206,73,67,102,72,148,2,32,214,73,157,224,
10851 18,128,98,29,241,69,65,50,37,241,116,200,41,144,102,125,2,180,8,210,152,38,
10852 129,23,8,34,198,
10853 };
10854 #endif  /* DUK_USE_ROM_STRINGS */
10855 
10856 #if defined(DUK_USE_ROM_OBJECTS)
10857 #error ROM support not enabled, rerun configure.py with --rom-support
10858 #else  /* DUK_USE_ROM_OBJECTS */
10859 /* native functions: 183 */
10860 DUK_INTERNAL const duk_c_function duk_bi_native_functions[183] = {
10861 	NULL,
10862 	duk_bi_array_constructor,
10863 	duk_bi_array_constructor_is_array,
10864 	duk_bi_array_prototype_concat,
10865 	duk_bi_array_prototype_indexof_shared,
10866 	duk_bi_array_prototype_iter_shared,
10867 	duk_bi_array_prototype_join_shared,
10868 	duk_bi_array_prototype_pop,
10869 	duk_bi_array_prototype_push,
10870 	duk_bi_array_prototype_reduce_shared,
10871 	duk_bi_array_prototype_reverse,
10872 	duk_bi_array_prototype_shift,
10873 	duk_bi_array_prototype_slice,
10874 	duk_bi_array_prototype_sort,
10875 	duk_bi_array_prototype_splice,
10876 	duk_bi_array_prototype_to_string,
10877 	duk_bi_array_prototype_unshift,
10878 	duk_bi_arraybuffer_constructor,
10879 	duk_bi_arraybuffer_isview,
10880 	duk_bi_boolean_constructor,
10881 	duk_bi_boolean_prototype_tostring_shared,
10882 	duk_bi_buffer_compare_shared,
10883 	duk_bi_buffer_readfield,
10884 	duk_bi_buffer_slice_shared,
10885 	duk_bi_buffer_writefield,
10886 	duk_bi_dataview_constructor,
10887 	duk_bi_date_constructor,
10888 	duk_bi_date_constructor_now,
10889 	duk_bi_date_constructor_parse,
10890 	duk_bi_date_constructor_utc,
10891 	duk_bi_date_prototype_get_shared,
10892 	duk_bi_date_prototype_get_timezone_offset,
10893 	duk_bi_date_prototype_set_shared,
10894 	duk_bi_date_prototype_set_time,
10895 	duk_bi_date_prototype_to_json,
10896 	duk_bi_date_prototype_toprimitive,
10897 	duk_bi_date_prototype_tostring_shared,
10898 	duk_bi_date_prototype_value_of,
10899 	duk_bi_duktape_object_act,
10900 	duk_bi_duktape_object_compact,
10901 	duk_bi_duktape_object_dec,
10902 	duk_bi_duktape_object_enc,
10903 	duk_bi_duktape_object_fin,
10904 	duk_bi_duktape_object_gc,
10905 	duk_bi_duktape_object_info,
10906 	duk_bi_error_constructor_shared,
10907 	duk_bi_error_prototype_filename_getter,
10908 	duk_bi_error_prototype_filename_setter,
10909 	duk_bi_error_prototype_linenumber_getter,
10910 	duk_bi_error_prototype_linenumber_setter,
10911 	duk_bi_error_prototype_stack_getter,
10912 	duk_bi_error_prototype_stack_setter,
10913 	duk_bi_error_prototype_to_string,
10914 	duk_bi_function_constructor,
10915 	duk_bi_function_prototype,
10916 	duk_bi_function_prototype_apply,
10917 	duk_bi_function_prototype_bind,
10918 	duk_bi_function_prototype_call,
10919 	duk_bi_function_prototype_hasinstance,
10920 	duk_bi_function_prototype_to_string,
10921 	duk_bi_global_object_decode_uri,
10922 	duk_bi_global_object_decode_uri_component,
10923 	duk_bi_global_object_encode_uri,
10924 	duk_bi_global_object_encode_uri_component,
10925 	duk_bi_global_object_escape,
10926 	duk_bi_global_object_eval,
10927 	duk_bi_global_object_is_finite,
10928 	duk_bi_global_object_is_nan,
10929 	duk_bi_global_object_parse_float,
10930 	duk_bi_global_object_parse_int,
10931 	duk_bi_global_object_unescape,
10932 	duk_bi_json_object_parse,
10933 	duk_bi_json_object_stringify,
10934 	duk_bi_math_object_clz32,
10935 	duk_bi_math_object_hypot,
10936 	duk_bi_math_object_imul,
10937 	duk_bi_math_object_max,
10938 	duk_bi_math_object_min,
10939 	duk_bi_math_object_onearg_shared,
10940 	duk_bi_math_object_random,
10941 	duk_bi_math_object_sign,
10942 	duk_bi_math_object_twoarg_shared,
10943 	duk_bi_native_function_length,
10944 	duk_bi_native_function_name,
10945 	duk_bi_nodejs_buffer_byte_length,
10946 	duk_bi_nodejs_buffer_concat,
10947 	duk_bi_nodejs_buffer_constructor,
10948 	duk_bi_nodejs_buffer_copy,
10949 	duk_bi_nodejs_buffer_fill,
10950 	duk_bi_nodejs_buffer_is_buffer,
10951 	duk_bi_nodejs_buffer_is_encoding,
10952 	duk_bi_nodejs_buffer_tojson,
10953 	duk_bi_nodejs_buffer_tostring,
10954 	duk_bi_nodejs_buffer_write,
10955 	duk_bi_number_check_shared,
10956 	duk_bi_number_constructor,
10957 	duk_bi_number_prototype_to_exponential,
10958 	duk_bi_number_prototype_to_fixed,
10959 	duk_bi_number_prototype_to_locale_string,
10960 	duk_bi_number_prototype_to_precision,
10961 	duk_bi_number_prototype_to_string,
10962 	duk_bi_number_prototype_value_of,
10963 	duk_bi_object_constructor,
10964 	duk_bi_object_constructor_assign,
10965 	duk_bi_object_constructor_create,
10966 	duk_bi_object_constructor_define_properties,
10967 	duk_bi_object_constructor_define_property,
10968 	duk_bi_object_constructor_get_own_property_descriptor,
10969 	duk_bi_object_constructor_is,
10970 	duk_bi_object_constructor_is_extensible,
10971 	duk_bi_object_constructor_is_sealed_frozen_shared,
10972 	duk_bi_object_constructor_keys_shared,
10973 	duk_bi_object_constructor_prevent_extensions,
10974 	duk_bi_object_constructor_seal_freeze_shared,
10975 	duk_bi_object_getprototype_shared,
10976 	duk_bi_object_prototype_defineaccessor,
10977 	duk_bi_object_prototype_has_own_property,
10978 	duk_bi_object_prototype_is_prototype_of,
10979 	duk_bi_object_prototype_lookupaccessor,
10980 	duk_bi_object_prototype_property_is_enumerable,
10981 	duk_bi_object_prototype_to_locale_string,
10982 	duk_bi_object_prototype_to_string,
10983 	duk_bi_object_prototype_value_of,
10984 	duk_bi_object_setprototype_shared,
10985 	duk_bi_performance_now,
10986 	duk_bi_pointer_constructor,
10987 	duk_bi_pointer_prototype_tostring_shared,
10988 	duk_bi_proxy_constructor,
10989 	duk_bi_reflect_apply,
10990 	duk_bi_reflect_construct,
10991 	duk_bi_reflect_object_delete_property,
10992 	duk_bi_reflect_object_get,
10993 	duk_bi_reflect_object_has,
10994 	duk_bi_reflect_object_set,
10995 	duk_bi_regexp_constructor,
10996 	duk_bi_regexp_prototype_exec,
10997 	duk_bi_regexp_prototype_flags,
10998 	duk_bi_regexp_prototype_shared_getter,
10999 	duk_bi_regexp_prototype_test,
11000 	duk_bi_regexp_prototype_tostring,
11001 	duk_bi_string_constructor,
11002 	duk_bi_string_constructor_from_char_code,
11003 	duk_bi_string_constructor_from_code_point,
11004 	duk_bi_string_prototype_caseconv_shared,
11005 	duk_bi_string_prototype_char_at,
11006 	duk_bi_string_prototype_char_code_at,
11007 	duk_bi_string_prototype_concat,
11008 	duk_bi_string_prototype_includes,
11009 	duk_bi_string_prototype_indexof_shared,
11010 	duk_bi_string_prototype_locale_compare,
11011 	duk_bi_string_prototype_match,
11012 	duk_bi_string_prototype_repeat,
11013 	duk_bi_string_prototype_replace,
11014 	duk_bi_string_prototype_search,
11015 	duk_bi_string_prototype_slice,
11016 	duk_bi_string_prototype_split,
11017 	duk_bi_string_prototype_startswith_endswith,
11018 	duk_bi_string_prototype_substr,
11019 	duk_bi_string_prototype_substring,
11020 	duk_bi_string_prototype_to_string,
11021 	duk_bi_string_prototype_trim,
11022 	duk_bi_symbol_constructor_shared,
11023 	duk_bi_symbol_key_for,
11024 	duk_bi_symbol_toprimitive,
11025 	duk_bi_symbol_tostring_shared,
11026 	duk_bi_textdecoder_constructor,
11027 	duk_bi_textdecoder_prototype_decode,
11028 	duk_bi_textdecoder_prototype_shared_getter,
11029 	duk_bi_textencoder_constructor,
11030 	duk_bi_textencoder_prototype_encode,
11031 	duk_bi_textencoder_prototype_encoding_getter,
11032 	duk_bi_thread_constructor,
11033 	duk_bi_thread_current,
11034 	duk_bi_thread_resume,
11035 	duk_bi_thread_yield,
11036 	duk_bi_type_error_thrower,
11037 	duk_bi_typedarray_buffer_getter,
11038 	duk_bi_typedarray_bytelength_getter,
11039 	duk_bi_typedarray_byteoffset_getter,
11040 	duk_bi_typedarray_constructor,
11041 	duk_bi_typedarray_set,
11042 	duk_bi_uint8array_allocplain,
11043 	duk_bi_uint8array_plainof,
11044 };
11045 #if defined(DUK_USE_DOUBLE_LE)
11046 DUK_INTERNAL const duk_uint8_t duk_builtins_data[4251] = {
11047 144,148,105,225,32,68,52,228,126,12,104,201,37,132,52,167,194,138,105,244,
11048 124,57,28,211,57,18,64,52,238,254,44,138,111,171,241,164,19,87,137,30,33,
11049 167,18,145,159,8,211,137,9,225,42,5,240,145,139,163,163,8,211,137,10,228,
11050 64,211,19,132,140,93,29,56,70,156,72,119,34,66,146,36,104,137,194,70,46,
11051 142,172,35,78,36,47,146,195,102,11,240,145,139,163,175,8,211,137,9,228,240,
11052 242,112,145,139,163,179,8,211,137,8,237,34,130,118,49,116,118,225,26,48,0,
11053 1,94,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
11054 33,8,66,26,180,41,97,167,64,150,34,33,154,112,0,1,87,247,35,79,103,237,198,
11055 174,216,47,31,23,95,17,13,31,217,96,211,49,50,53,212,77,141,24,0,0,179,10,
11056 228,240,242,15,128,140,65,128,134,188,0,0,89,167,97,181,224,0,2,205,62,53,
11057 224,0,2,205,66,237,120,0,0,179,81,204,107,192,0,5,154,150,67,94,0,0,44,212,
11058 245,90,240,0,1,102,169,162,215,128,0,11,53,93,150,188,0,0,89,171,111,53,
11059 108,150,163,70,0,0,42,2,249,50,94,124,35,68,225,146,49,13,24,0,0,165,161,
11060 124,153,47,62,12,130,112,201,24,132,56,97,115,16,0,0,0,0,0,0,62,31,243,48,
11061 0,0,0,0,0,0,60,31,242,241,32,26,193,55,132,112,161,156,72,135,26,41,200,
11062 140,114,163,156,201,7,56,79,9,80,47,132,140,93,19,160,43,145,3,76,78,18,49,
11063 116,78,144,238,68,133,36,72,209,19,132,140,93,19,168,47,146,195,102,11,240,
11064 145,139,162,117,132,242,120,121,56,72,197,209,59,2,59,72,160,157,140,93,19,
11065 181,36,242,50,143,36,31,131,162,166,7,144,238,133,227,226,235,224,242,161,
11066 249,18,21,100,20,207,44,199,151,180,122,89,135,152,154,121,153,199,156,158,
11067 121,218,7,158,162,121,250,71,160,166,122,26,135,162,170,122,58,199,164,16,
11068 240,70,68,226,27,51,199,138,120,35,34,112,171,112,38,121,1,124,153,47,62,
11069 17,162,112,201,19,211,11,228,201,121,240,100,19,134,72,158,160,91,201,18,
11070 186,44,3,68,79,122,168,151,115,165,40,21,18,227,65,198,231,200,8,68,184,84,
11071 53,19,38,120,128,145,144,78,25,59,72,163,48,64,144,200,39,12,157,164,80,46,
11072 185,143,115,72,217,230,72,9,35,68,225,147,180,138,51,68,9,17,162,112,201,
11073 218,69,2,235,152,247,52,141,158,108,128,98,72,64,121,51,132,4,81,164,144,
11074 128,242,104,136,0,16,92,38,14,49,39,199,197,211,116,240,242,113,197,231,18,
11075 53,189,116,65,131,18,124,117,155,199,197,207,36,103,142,12,146,20,80,249,
11076 186,60,116,4,204,73,241,214,111,31,23,60,145,158,56,208,48,146,229,146,3,2,
11077 82,65,155,195,94,3,10,36,4,201,196,64,56,100,42,26,78,62,46,121,35,60,113,
11078 152,16,25,10,134,147,143,139,158,72,205,4,151,21,0,73,16,11,230,144,12,88,
11079 144,153,39,52,144,69,241,37,72,217,240,151,153,27,36,57,178,230,16,16,137,
11080 114,68,2,200,62,81,1,8,151,11,23,100,141,229,18,6,34,92,37,230,70,201,1,89,
11081 57,36,2,40,152,151,44,129,83,18,124,117,155,199,197,207,36,103,142,75,12,
11082 11,151,46,89,40,18,37,200,64,12,154,236,252,238,185,23,95,213,1,132,234,0,
11083 194,245,128,14,56,37,199,89,188,124,92,242,70,120,232,16,26,137,113,241,
11084 116,221,60,60,156,113,122,36,10,62,46,121,35,60,113,18,225,27,70,18,32,10,
11085 201,211,32,67,107,104,100,42,26,78,24,147,153,35,181,181,207,64,67,107,104,
11086 100,42,26,78,72,147,153,35,181,181,207,68,16,218,218,91,156,170,63,134,36,
11087 230,72,237,109,116,136,16,218,218,91,156,170,63,146,36,230,72,237,109,116,
11088 137,16,96,128,228,2,6,191,46,3,71,147,68,4,16,22,188,169,240,16,40,104,242,
11089 135,198,171,44,68,65,5,217,231,215,6,231,62,188,8,49,1,3,162,92,4,98,12,41,
11090 7,33,148,53,242,128,97,32,130,3,9,205,16,38,199,198,14,9,0,111,115,225,0,8,
11091 250,72,240,207,128,241,37,73,25,18,40,0,178,58,11,56,192,2,201,104,17,35,
11092 160,9,39,70,114,8,6,147,214,129,18,74,240,30,141,145,208,89,203,62,3,161,
11093 163,37,248,226,185,244,11,88,37,62,33,163,37,248,226,185,252,0,127,255,130,
11094 146,164,142,32,26,1,36,230,18,1,164,7,43,163,194,0,71,128,105,64,216,7,192,
11095 52,192,197,66,230,72,192,52,224,209,32,232,34,68,62,129,113,32,232,34,114,
11096 40,49,231,16,254,0,63,255,208,99,2,140,44,92,206,8,224,143,4,225,147,210,
11097 124,13,44,92,206,9,195,39,30,228,54,126,163,225,200,169,198,133,42,166,191,
11098 246,3,11,251,0,24,71,4,120,9,251,8,10,17,193,30,9,195,39,1,63,105,1,98,112,
11099 201,199,185,13,159,1,63,105,32,48,156,209,2,126,227,224,58,26,50,95,142,47,
11100 192,208,22,176,74,124,67,70,75,241,197,248,26,64,213,184,64,89,56,39,49,
11101 224,137,62,36,2,176,19,17,254,68,3,196,143,88,4,79,162,0,210,32,34,35,253,
11102 72,5,146,208,34,125,144,5,147,214,137,253,208,9,149,3,41,197,13,55,233,0,
11103 185,187,139,117,137,30,8,18,39,172,1,25,187,139,112,128,178,113,110,177,35,
11104 193,2,68,245,128,23,55,114,143,121,35,193,2,68,245,130,8,205,220,91,132,5,
11105 147,148,123,201,30,8,18,39,172,16,18,113,67,63,128,3,68,143,32,39,243,32,
11106 42,83,4,103,46,89,19,63,224,208,16,70,142,92,178,38,127,193,164,8,67,68,
11107 186,12,146,247,154,1,165,64,202,113,252,160,131,32,7,35,167,26,50,235,231,
11108 130,48,179,192,65,148,69,19,214,2,251,85,2,232,72,31,255,255,255,255,255,
11109 253,239,226,122,196,55,106,160,93,9,0,4,0,0,0,0,0,0,3,49,0,0,0,0,0,0,3,225,
11110 252,143,94,233,34,104,169,54,144,210,161,168,158,32,0,0,0,0,0,0,120,63,145,
11111 235,72,96,77,21,38,210,26,84,53,19,196,0,0,0,0,0,0,15,15,240,253,35,228,
11112 133,185,176,0,0,0,0,0,0,44,15,8,117,128,190,212,128,82,109,33,179,33,137,
11113 24,31,255,255,255,255,255,231,232,100,58,196,55,106,64,41,54,144,217,144,
11114 196,140,15,255,255,255,255,255,243,252,49,15,4,100,78,33,179,60,120,167,
11115 130,50,39,10,183,2,103,144,113,8,151,10,134,162,100,221,16,18,137,113,13,
11116 153,12,72,238,137,1,81,46,52,28,110,232,148,53,18,228,128,82,113,13,153,12,
11117 72,238,137,142,73,78,52,0,0,0,0,0,0,0,0,8,58,254,1,12,38,248,134,23,130,0,
11118 60,221,194,162,228,30,244,128,217,187,132,187,220,210,54,104,2,247,132,5,
11119 205,220,124,72,36,73,14,110,252,132,25,128,193,94,8,200,149,200,3,237,38,
11120 43,31,192,54,186,213,128,57,45,56,210,0,0,0,0,0,0,62,31,241,90,251,224,6,
11121 77,220,24,38,78,74,113,67,77,124,16,50,110,228,208,194,114,83,138,26,107,
11122 224,172,37,240,97,41,187,139,112,128,178,112,96,153,57,41,197,13,53,240,
11123 113,41,187,139,112,128,178,114,104,97,57,41,197,13,53,240,128,195,95,8,44,
11124 61,240,132,216,93,33,133,192,128,14,98,79,147,67,9,129,0,44,196,159,11,69,
11125 175,152,32,35,100,33,135,24,147,237,38,34,246,139,95,48,64,70,200,68,8,49,
11126 39,198,57,179,61,144,138,22,98,79,180,152,153,215,54,103,178,17,129,204,73,
11127 240,96,153,44,132,112,163,18,125,164,196,62,130,100,178,18,1,140,73,240,96,
11128 197,144,146,18,98,79,180,152,135,208,98,200,74,8,49,39,195,186,145,149,144,
11129 150,22,98,79,180,152,143,215,82,50,178,19,2,140,73,241,136,109,38,73,89,9,
11130 161,166,36,251,73,137,157,67,105,50,74,200,78,10,49,39,201,16,78,104,229,
11131 100,39,134,152,147,237,38,41,116,130,115,71,43,33,64,60,196,159,24,133,173,
11132 18,32,156,209,202,200,81,18,49,39,218,76,76,234,22,180,72,130,115,71,43,33,
11133 72,68,196,159,38,134,19,46,105,56,226,150,68,157,160,1,228,73,242,104,97,
11134 46,16,31,34,79,140,66,214,137,16,78,104,229,108,169,137,72,147,237,38,38,
11135 117,11,90,36,65,57,163,149,178,168,21,34,79,146,32,156,209,202,218,250,161,
11136 178,36,251,73,138,93,32,156,209,202,218,250,193,82,36,248,196,54,147,36,
11137 173,191,174,27,34,79,180,152,153,212,54,147,36,173,191,176,17,34,79,135,
11138 117,35,43,115,236,133,200,147,237,38,35,245,212,140,173,207,180,15,34,79,
11139 131,4,201,108,173,133,72,147,237,38,33,244,19,37,178,184,17,34,79,140,115,
11140 102,123,107,238,133,200,147,237,38,38,117,205,153,237,175,188,23,34,79,133,
11141 162,215,204,16,17,182,254,248,116,137,62,210,98,47,104,181,243,4,4,109,191,
11142 192,131,152,147,230,8,8,217,12,16,60,137,62,96,128,141,178,193,181,55,136,
11143 200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,32,98,115,249,73,
11144 117,243,249,67,21,159,202,38,47,63,148,86,8,75,144,94,50,1,38,73,79,204,67,
11145 95,231,1,6,128,14,79,129,185,40,249,18,149,181,207,142,199,155,172,248,172,
11146 89,183,207,140,198,137,175,200,0,159,72,10,5,21,220,138,120,74,129,124,36,
11147 98,232,228,74,81,62,160,20,10,107,185,21,114,32,105,137,194,70,46,142,68,
11148 165,19,235,1,64,170,187,145,119,34,66,146,36,104,137,194,70,46,142,68,165,
11149 19,236,1,64,174,187,145,95,37,134,204,23,225,35,23,71,34,82,137,246,128,
11150 160,89,93,200,167,147,195,201,194,70,46,142,68,165,19,238,1,64,182,187,145,
11151 71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,72,115,96,0,0,0,0,0,118,
11152 105,160,91,60,165,195,201,194,8,134,149,216,130,0,192,41,224,136,2,48,176,
11153 228,1,149,13,195,15,0,200,209,97,71,128,99,32,176,131,192,113,57,143,0,167,
11154 131,32,230,80,28,202,139,175,237,2,48,189,160,20,1,119,48,87,193,186,129,
11155 89,56,72,197,209,200,193,185,35,23,71,109,13,219,36,98,232,237,156,13,26,
11156 208,211,14,102,19,87,137,91,95,128,0,10,64,24,92,0,0,82,2,53,63,240,49,204,
11157 202,10,14,38,78,44,141,52,207,31,0,0,22,32,129,100,180,8,148,145,78,102,
11158 152,80,113,50,113,100,105,166,120,248,0,0,177,1,65,196,201,199,20,178,36,
11159 227,224,0,2,200,3,6,133,41,35,31,0,0,22,1,44,57,137,62,33,179,216,162,152,
11160 192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,81,76,104,73,
11161 137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,166,56,36,196,
11162 159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,20,188,20,98,
11163 79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,68,137,62,81,
11164 13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,159,40,134,207,
11165 71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,67,103,167,165,
11166 77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,173,192,158,182,
11167 165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,140,35,103,0,0,
11168 0,0,0,0,3,192,252,206,25,228,35,208,226,100,150,211,201,29,162,44,140,35,
11169 103,0,0,0,0,0,0,3,192,252,206,25,244,35,208,226,100,150,211,201,29,162,44,
11170 140,35,103,0,0,0,0,0,0,3,192,252,206,26,4,35,208,226,100,150,211,201,29,
11171 162,44,140,35,103,0,0,0,0,0,0,0,1,0,206,26,20,35,208,226,100,150,211,201,
11172 29,162,44,140,35,103,0,0,0,0,0,0,0,1,0,206,26,36,35,208,226,100,150,211,
11173 201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,52,35,208,226,100,150,
11174 211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,68,35,208,226,100,
11175 150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,84,35,208,226,
11176 100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,129,0,195,154,99,16,38,
11177 36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,25,18,0,125,
11178 162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,235,116,36,
11179 162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,196,54,122,
11180 58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,200,144,3,
11181 237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,213,146,138,
11182 77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,183,2,125,89,
11183 40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,221,64,172,157,
11184 89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,31,104,142,182,
11185 125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,18,0,124,67,103,
11186 213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,59,68,117,179,
11187 216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,39,104,142,182,
11188 122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,73,77,162,6,90,
11189 40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,61,29,110,132,
11190 148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,67,109,20,76,
11191 157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,167,165,213,
11192 146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,68,201,194,
11193 173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,193,182,138,
11194 38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,178,116,36,
11195 166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,157,162,58,
11196 217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,81,50,113,
11197 13,159,66,74,113,97,175,220,48,216,109,192,4,42,22,189,163,0,196,133,0,185,
11198 80,32,28,78,99,193,18,80,36,4,19,159,141,156,0,178,90,4,74,73,0,22,209,68,
11199 201,185,129,4,2,8,3,132,64,60,36,6,149,113,72,176,171,240,84,0,157,91,116,
11200 116,32,11,42,218,221,216,181,129,32,3,234,219,165,3,188,231,235,249,8,187,
11201 152,252,47,86,227,105,18,7,244,17,91,42,56,175,185,248,110,173,198,209,208,
11202 36,0,238,82,97,87,188,189,179,240,93,122,32,12,22,162,42,125,144,132,160,7,
11203 236,161,25,232,237,105,64,205,59,127,102,158,160,230,63,11,217,66,51,210,
11204 129,154,118,254,205,61,65,236,127,171,197,34,168,48,6,90,162,1,0,39,75,84,
11205 72,8,9,33,186,162,80,64,76,13,213,19,2,130,96,110,150,181,0,65,6,51,213,20,
11206 128,65,17,11,213,19,130,137,121,211,210,210,144,6,39,75,84,80,0,201,119,
11207 234,138,8,41,86,231,71,84,80,129,79,135,186,122,101,224,34,25,69,233,208,3,
11208 91,141,170,40,96,139,113,180,181,69,36,21,110,54,142,134,168,165,1,176,23,
11209 212,47,0,216,134,234,87,128,111,117,181,168,128,209,3,70,230,106,192,5,139,
11210 168,209,234,138,32,36,144,102,235,8,3,146,27,170,40,160,146,132,103,170,40,
11211 192,115,3,117,69,28,22,113,163,69,170,41,103,1,66,188,17,145,52,104,4,202,
11212 113,67,76,130,227,72,194,13,240,108,0,0,83,96,0,2,185,0,104,146,84,97,48,0,
11213 1,90,192,56,169,24,145,179,192,0,5,96,8,56,16,32,128,56,18,52,125,198,86,
11214 147,186,140,28,50,21,13,39,31,23,60,145,158,56,204,141,47,121,6,155,190,
11215 188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,199,68,
11216 14,49,39,199,197,211,116,240,242,113,197,231,18,180,254,4,3,17,46,18,243,
11217 35,100,128,172,156,146,70,163,150,76,34,248,146,164,108,248,75,204,141,146,
11218 28,217,115,9,27,79,11,241,173,235,162,160,224,200,2,206,9,113,13,148,192,
11219 209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,178,66,213,136,68,
11220 201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,38,232,255,252,92,
11221 221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,38,3,66,213,47,131,
11222 250,72,12,162,99,133,116,127,196,32,225,1,3,34,92,170,9,105,164,32,225,64,
11223 131,156,1,193,133,7,19,39,22,70,154,103,143,128,0,11,16,20,28,76,156,113,
11224 75,34,78,62,0,0,44,128,48,104,82,146,49,240,0,1,96,11,180,192,0,5,162,1,18,
11225 160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,121,35,180,69,145,132,
11226 108,224,0,0,0,0,0,0,120,31,153,188,56,132,122,28,76,146,218,121,35,180,69,
11227 145,132,108,224,0,0,0,0,0,0,120,31,168,160,45,110,23,30,176,33,184,0,0,181,
11228 32,29,235,2,27,199,23,0,0,22,196,51,120,129,8,244,56,153,37,180,242,71,104,
11229 139,35,8,217,192,0,0,0,0,0,0,240,63,51,120,145,8,244,56,153,37,180,242,71,
11230 104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,120,161,8,244,56,153,37,180,242,
11231 71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,120,177,8,244,56,153,37,180,
11232 242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,120,193,8,244,56,153,37,
11233 180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,120,209,8,244,56,153,
11234 37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,120,225,8,244,56,
11235 153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,32,64,32,227,194,0,97,
11236 57,162,4,246,40,5,34,92,35,68,225,161,166,219,16,16,137,112,52,41,73,29,
11237 169,1,65,196,201,197,145,166,153,246,8,3,137,204,120,34,74,8,200,58,128,28,
11238 211,160,130,52,78,26,26,110,248,0,0,170,4,12,70,137,195,38,0,0,42,68,159,7,
11239 84,3,154,150,16,70,137,195,67,77,223,0,0,20,224,20,160,152,23,223,0,0,20,
11240 226,9,65,154,232,147,161,115,59,224,0,2,156,84,12,50,9,195,38,0,0,41,133,
11241 30,224,32,54,186,221,128,60,
11242 };
11243 #elif defined(DUK_USE_DOUBLE_BE)
11244 DUK_INTERNAL const duk_uint8_t duk_builtins_data[4251] = {
11245 144,148,105,225,32,68,52,228,126,12,104,201,37,132,52,167,194,138,105,244,
11246 124,57,28,211,57,18,64,52,238,254,44,138,111,171,241,164,19,87,137,30,33,
11247 167,18,145,159,8,211,137,9,225,42,5,240,145,139,163,163,8,211,137,10,228,
11248 64,211,19,132,140,93,29,56,70,156,72,119,34,66,146,36,104,137,194,70,46,
11249 142,172,35,78,36,47,146,195,102,11,240,145,139,163,175,8,211,137,9,228,240,
11250 242,112,145,139,163,179,8,211,137,8,237,34,130,118,49,116,118,225,26,48,0,
11251 1,94,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
11252 33,8,66,26,180,41,97,167,64,150,34,33,154,112,0,1,87,247,35,79,103,237,198,
11253 174,216,47,31,23,95,17,13,31,217,96,211,49,50,53,212,77,141,24,0,0,179,10,
11254 228,240,242,15,128,140,65,128,134,188,0,0,89,167,97,181,224,0,2,205,62,53,
11255 224,0,2,205,66,237,120,0,0,179,81,204,107,192,0,5,154,150,67,94,0,0,44,212,
11256 245,90,240,0,1,102,169,162,215,128,0,11,53,93,150,188,0,0,89,171,111,53,
11257 108,150,163,70,0,0,42,2,249,50,94,124,35,68,225,146,49,13,24,0,0,165,161,
11258 124,153,47,62,12,130,112,201,24,132,56,97,115,16,31,254,0,0,0,0,0,0,51,48,
11259 31,252,0,0,0,0,0,0,50,241,32,26,193,55,132,112,161,156,72,135,26,41,200,
11260 140,114,163,156,201,7,56,79,9,80,47,132,140,93,19,160,43,145,3,76,78,18,49,
11261 116,78,144,238,68,133,36,72,209,19,132,140,93,19,168,47,146,195,102,11,240,
11262 145,139,162,117,132,242,120,121,56,72,197,209,59,2,59,72,160,157,140,93,19,
11263 181,36,242,50,143,36,31,131,162,166,7,144,238,133,227,226,235,224,242,161,
11264 249,18,21,100,20,207,44,199,151,180,122,89,135,152,154,121,153,199,156,158,
11265 121,218,7,158,162,121,250,71,160,166,122,26,135,162,170,122,58,199,164,16,
11266 240,70,68,226,27,51,199,138,120,35,34,112,171,112,38,121,1,124,153,47,62,
11267 17,162,112,201,19,211,11,228,201,121,240,100,19,134,72,158,160,91,201,18,
11268 186,44,3,68,79,122,168,151,115,165,40,21,18,227,65,198,231,200,8,68,184,84,
11269 53,19,38,120,128,145,144,78,25,59,72,163,48,64,144,200,39,12,157,164,80,46,
11270 185,143,115,72,217,230,72,9,35,68,225,147,180,138,51,68,9,17,162,112,201,
11271 218,69,2,235,152,247,52,141,158,108,128,98,72,64,121,51,132,4,81,164,144,
11272 128,242,104,136,0,16,92,38,14,49,39,199,197,211,116,240,242,113,197,231,18,
11273 53,189,116,65,131,18,124,117,155,199,197,207,36,103,142,12,146,20,80,249,
11274 186,60,116,4,204,73,241,214,111,31,23,60,145,158,56,208,48,146,229,146,3,2,
11275 82,65,155,195,94,3,10,36,4,201,196,64,56,100,42,26,78,62,46,121,35,60,113,
11276 152,16,25,10,134,147,143,139,158,72,205,4,151,21,0,73,16,11,230,144,12,88,
11277 144,153,39,52,144,69,241,37,72,217,240,151,153,27,36,57,178,230,16,16,137,
11278 114,68,2,200,62,81,1,8,151,11,23,100,141,229,18,6,34,92,37,230,70,201,1,89,
11279 57,36,2,40,152,151,44,129,83,18,124,117,155,199,197,207,36,103,142,75,12,
11280 11,151,46,89,40,18,37,200,64,12,154,236,252,238,185,23,95,213,1,132,234,0,
11281 194,245,128,14,56,37,199,89,188,124,92,242,70,120,232,16,26,137,113,241,
11282 116,221,60,60,156,113,122,36,10,62,46,121,35,60,113,18,225,27,70,18,32,10,
11283 201,211,32,67,107,104,100,42,26,78,24,147,153,35,181,181,207,64,67,107,104,
11284 100,42,26,78,72,147,153,35,181,181,207,68,16,218,218,91,156,170,63,134,36,
11285 230,72,237,109,116,136,16,218,218,91,156,170,63,146,36,230,72,237,109,116,
11286 137,16,96,128,228,2,6,191,46,3,71,147,68,4,16,22,188,169,240,16,40,104,242,
11287 135,198,171,44,68,65,5,217,231,215,6,231,62,188,8,49,1,3,162,92,4,98,12,41,
11288 7,33,148,53,242,128,97,32,130,3,9,205,16,38,199,198,14,9,0,111,115,225,0,8,
11289 250,72,240,207,128,241,37,73,25,18,40,0,178,58,11,56,192,2,201,104,17,35,
11290 160,9,39,70,114,8,6,147,214,129,18,74,240,30,141,145,208,89,203,62,3,161,
11291 163,37,248,226,185,244,11,88,37,62,33,163,37,248,226,185,252,0,127,255,130,
11292 146,164,142,32,26,1,36,230,18,1,164,7,43,163,194,0,71,128,105,64,216,7,192,
11293 52,192,197,66,230,72,192,52,224,209,32,232,34,68,62,129,113,32,232,34,114,
11294 40,49,231,16,254,0,63,255,208,99,2,140,44,92,206,8,224,143,4,225,147,210,
11295 124,13,44,92,206,9,195,39,30,228,54,126,163,225,200,169,198,133,42,166,191,
11296 246,3,11,251,0,24,71,4,120,9,251,8,10,17,193,30,9,195,39,1,63,105,1,98,112,
11297 201,199,185,13,159,1,63,105,32,48,156,209,2,126,227,224,58,26,50,95,142,47,
11298 192,208,22,176,74,124,67,70,75,241,197,248,26,64,213,184,64,89,56,39,49,
11299 224,137,62,36,2,176,19,17,254,68,3,196,143,88,4,79,162,0,210,32,34,35,253,
11300 72,5,146,208,34,125,144,5,147,214,137,253,208,9,149,3,41,197,13,55,233,0,
11301 185,187,139,117,137,30,8,18,39,172,1,25,187,139,112,128,178,113,110,177,35,
11302 193,2,68,245,128,23,55,114,143,121,35,193,2,68,245,130,8,205,220,91,132,5,
11303 147,148,123,201,30,8,18,39,172,16,18,113,67,63,128,3,68,143,32,39,243,32,
11304 42,83,4,103,46,89,19,63,224,208,16,70,142,92,178,38,127,193,164,8,67,68,
11305 186,12,146,247,154,1,165,64,202,113,252,160,131,32,7,35,167,26,50,235,231,
11306 130,48,179,192,65,148,69,19,214,2,251,85,2,232,72,15,253,255,255,255,255,
11307 255,255,226,122,196,55,106,160,93,9,0,0,0,0,0,0,0,0,7,49,1,255,224,0,0,0,0,
11308 0,0,143,94,233,34,104,169,54,144,210,161,168,158,32,63,248,0,0,0,0,0,0,17,
11309 235,72,96,77,21,38,210,26,84,53,19,196,15,255,0,0,0,0,0,0,0,253,35,228,133,
11310 185,176,15,44,0,0,0,0,0,0,8,117,128,190,212,128,82,109,33,179,33,137,24,8,
11311 103,255,255,255,255,255,255,228,58,196,55,106,64,41,54,144,217,144,196,140,
11312 12,51,255,255,255,255,255,255,241,15,4,100,78,33,179,60,120,167,130,50,39,
11313 10,183,2,103,144,113,8,151,10,134,162,100,221,16,18,137,113,13,153,12,72,
11314 238,137,1,81,46,52,28,110,232,148,53,18,228,128,82,113,13,153,12,72,238,
11315 137,142,73,78,52,0,0,0,0,0,0,0,0,8,58,254,1,12,38,248,134,23,130,0,60,221,
11316 194,162,228,30,244,128,217,187,132,187,220,210,54,104,2,247,132,5,205,220,
11317 124,72,36,73,14,110,252,132,25,128,193,94,8,200,149,200,3,237,38,43,31,192,
11318 54,186,213,128,57,45,56,210,31,254,0,0,0,0,0,0,49,90,251,224,6,77,220,24,
11319 38,78,74,113,67,77,124,16,50,110,228,208,194,114,83,138,26,107,224,172,37,
11320 240,97,41,187,139,112,128,178,112,96,153,57,41,197,13,53,240,113,41,187,
11321 139,112,128,178,114,104,97,57,41,197,13,53,240,128,195,95,8,44,61,240,132,
11322 216,93,33,133,192,128,14,98,79,147,67,9,129,0,44,196,159,11,69,175,152,32,
11323 35,100,33,135,24,147,237,38,34,246,139,95,48,64,70,200,68,8,49,39,198,57,
11324 179,61,144,138,22,98,79,180,152,153,215,54,103,178,17,129,204,73,240,96,
11325 153,44,132,112,163,18,125,164,196,62,130,100,178,18,1,140,73,240,96,197,
11326 144,146,18,98,79,180,152,135,208,98,200,74,8,49,39,195,186,145,149,144,150,
11327 22,98,79,180,152,143,215,82,50,178,19,2,140,73,241,136,109,38,73,89,9,161,
11328 166,36,251,73,137,157,67,105,50,74,200,78,10,49,39,201,16,78,104,229,100,
11329 39,134,152,147,237,38,41,116,130,115,71,43,33,64,60,196,159,24,133,173,18,
11330 32,156,209,202,200,81,18,49,39,218,76,76,234,22,180,72,130,115,71,43,33,72,
11331 68,196,159,38,134,19,46,105,56,226,150,68,157,160,1,228,73,242,104,97,46,
11332 16,31,34,79,140,66,214,137,16,78,104,229,108,169,137,72,147,237,38,38,117,
11333 11,90,36,65,57,163,149,178,168,21,34,79,146,32,156,209,202,218,250,161,178,
11334 36,251,73,138,93,32,156,209,202,218,250,193,82,36,248,196,54,147,36,173,
11335 191,174,27,34,79,180,152,153,212,54,147,36,173,191,176,17,34,79,135,117,35,
11336 43,115,236,133,200,147,237,38,35,245,212,140,173,207,180,15,34,79,131,4,
11337 201,108,173,133,72,147,237,38,33,244,19,37,178,184,17,34,79,140,115,102,
11338 123,107,238,133,200,147,237,38,38,117,205,153,237,175,188,23,34,79,133,162,
11339 215,204,16,17,182,254,248,116,137,62,210,98,47,104,181,243,4,4,109,191,192,
11340 131,152,147,230,8,8,217,12,16,60,137,62,96,128,141,178,193,181,55,136,200,
11341 51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,32,98,115,249,73,117,
11342 243,249,67,21,159,202,38,47,63,148,86,8,75,144,94,50,1,38,73,79,204,67,95,
11343 231,1,6,128,14,79,129,185,40,249,18,149,181,207,142,199,155,172,248,172,89,
11344 183,207,140,198,137,175,200,0,159,72,10,5,21,220,138,120,74,129,124,36,98,
11345 232,228,74,81,62,160,20,10,107,185,21,114,32,105,137,194,70,46,142,68,165,
11346 19,235,1,64,170,187,145,119,34,66,146,36,104,137,194,70,46,142,68,165,19,
11347 236,1,64,174,187,145,95,37,134,204,23,225,35,23,71,34,82,137,246,128,160,
11348 89,93,200,167,147,195,201,194,70,46,142,68,165,19,238,1,64,182,187,145,71,
11349 105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,72,115,96,32,105,246,0,0,0,
11350 0,0,91,60,165,195,201,194,8,134,149,216,130,0,192,41,224,136,2,48,176,228,
11351 1,149,13,195,15,0,200,209,97,71,128,99,32,176,131,192,113,57,143,0,167,131,
11352 32,230,80,28,202,139,175,237,2,48,189,160,20,1,119,48,87,193,186,129,89,56,
11353 72,197,209,200,193,185,35,23,71,109,13,219,36,98,232,237,156,13,26,208,211,
11354 14,102,19,87,137,91,95,128,0,10,64,24,92,0,0,82,2,53,63,240,49,204,202,10,
11355 14,38,78,44,141,52,207,31,0,0,22,32,129,100,180,8,148,145,78,102,152,80,
11356 113,50,113,100,105,166,120,248,0,0,177,1,65,196,201,199,20,178,36,227,224,
11357 0,2,200,3,6,133,41,35,31,0,0,22,1,44,57,137,62,33,179,216,162,152,192,131,
11358 18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,81,76,104,73,137,62,
11359 81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,166,56,36,196,159,40,
11360 134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,20,188,20,98,79,133,
11361 91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,68,137,62,81,13,158,
11362 197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,159,40,134,207,71,90,
11363 155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,67,103,167,165,77,
11364 174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,173,192,158,182,
11365 165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,140,35,103,0,
11366 255,192,0,0,0,0,0,0,206,25,228,35,208,226,100,150,211,201,29,162,44,140,35,
11367 103,0,255,192,0,0,0,0,0,0,206,25,244,35,208,226,100,150,211,201,29,162,44,
11368 140,35,103,0,255,192,0,0,0,0,0,0,206,26,4,35,208,226,100,150,211,201,29,
11369 162,44,140,35,103,1,0,0,0,0,0,0,0,0,206,26,20,35,208,226,100,150,211,201,
11370 29,162,44,140,35,103,1,0,0,0,0,0,0,0,0,206,26,36,35,208,226,100,150,211,
11371 201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,52,35,208,226,100,150,
11372 211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,68,35,208,226,100,
11373 150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,84,35,208,226,
11374 100,150,211,201,29,162,44,140,35,103,1,0,128,0,0,0,0,0,0,195,154,99,16,38,
11375 36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,25,18,0,125,
11376 162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,235,116,36,
11377 162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,196,54,122,
11378 58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,200,144,3,
11379 237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,213,146,138,
11380 77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,183,2,125,89,
11381 40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,221,64,172,157,
11382 89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,31,104,142,182,
11383 125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,18,0,124,67,103,
11384 213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,59,68,117,179,
11385 216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,39,104,142,182,
11386 122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,73,77,162,6,90,
11387 40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,61,29,110,132,
11388 148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,67,109,20,76,
11389 157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,167,165,213,
11390 146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,68,201,194,
11391 173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,193,182,138,
11392 38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,178,116,36,
11393 166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,157,162,58,
11394 217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,81,50,113,
11395 13,159,66,74,113,97,175,220,48,216,109,192,4,42,22,189,163,0,196,133,0,185,
11396 80,32,28,78,99,193,18,80,36,4,19,159,141,156,0,178,90,4,74,73,0,22,209,68,
11397 201,185,129,4,2,8,3,132,64,60,36,4,0,91,240,168,177,69,118,144,157,91,116,
11398 116,32,32,1,53,216,221,218,170,139,3,234,219,165,0,255,152,185,11,251,232,
11399 231,188,47,86,227,105,18,1,255,184,170,59,41,92,23,240,110,173,198,209,208,
11400 36,3,253,188,183,177,82,110,80,224,93,122,32,32,4,144,253,170,34,22,140,7,
11401 236,161,25,232,237,105,64,63,230,160,158,102,127,59,205,11,217,66,51,210,
11402 128,127,237,65,60,204,254,119,155,171,197,34,168,48,6,90,162,1,0,39,75,84,
11403 72,8,9,33,186,162,80,64,76,13,213,19,2,130,96,110,150,181,0,65,6,51,213,20,
11404 128,65,17,11,213,19,130,137,121,211,210,210,144,6,39,75,84,80,0,201,119,
11405 234,138,8,41,86,231,71,84,80,129,79,135,186,122,101,224,34,25,69,233,208,3,
11406 91,141,170,40,96,139,113,180,181,69,36,21,110,54,142,134,168,165,1,176,23,
11407 212,47,0,216,134,234,87,128,111,117,181,168,128,209,3,70,230,106,192,5,139,
11408 168,209,234,138,32,36,144,102,235,8,3,146,27,170,40,160,146,132,103,170,40,
11409 192,115,3,117,69,28,22,113,163,69,170,41,103,1,66,188,17,145,52,104,4,202,
11410 113,67,76,130,227,72,194,13,240,108,0,0,83,96,0,2,185,0,104,146,84,97,48,0,
11411 1,90,192,56,169,24,145,179,192,0,5,96,8,56,16,32,128,56,18,52,125,198,86,
11412 147,186,140,28,50,21,13,39,31,23,60,145,158,56,204,141,47,121,6,155,190,
11413 188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,199,68,
11414 14,49,39,199,197,211,116,240,242,113,197,231,18,180,254,4,3,17,46,18,243,
11415 35,100,128,172,156,146,70,163,150,76,34,248,146,164,108,248,75,204,141,146,
11416 28,217,115,9,27,79,11,241,173,235,162,160,224,200,2,206,9,113,13,148,192,
11417 209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,178,66,213,136,68,
11418 201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,38,232,255,252,92,
11419 221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,38,3,66,213,47,131,
11420 250,72,12,162,99,133,116,127,196,32,225,1,3,34,92,170,9,105,164,32,225,64,
11421 131,156,1,193,133,7,19,39,22,70,154,103,143,128,0,11,16,20,28,76,156,113,
11422 75,34,78,62,0,0,44,128,48,104,82,146,49,240,0,1,96,11,180,192,0,5,162,1,18,
11423 160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,121,35,180,69,145,132,
11424 108,224,31,248,0,0,0,0,0,0,25,188,56,132,122,28,76,146,218,121,35,180,69,
11425 145,132,108,224,31,248,0,0,0,0,0,0,40,160,45,110,23,30,176,33,184,0,0,181,
11426 32,29,235,2,27,199,23,0,0,22,196,51,120,129,8,244,56,153,37,180,242,71,104,
11427 139,35,8,217,192,63,240,0,0,0,0,0,0,51,120,145,8,244,56,153,37,180,242,71,
11428 104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,120,161,8,244,56,153,37,180,242,
11429 71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,120,177,8,244,56,153,37,180,
11430 242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,120,193,8,244,56,153,37,
11431 180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,120,209,8,244,56,153,
11432 37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,120,225,8,244,56,
11433 153,37,180,242,71,104,139,35,8,217,192,64,32,0,0,0,0,0,0,32,227,194,0,97,
11434 57,162,4,246,40,5,34,92,35,68,225,161,166,219,16,16,137,112,52,41,73,29,
11435 169,1,65,196,201,197,145,166,153,246,8,3,137,204,120,34,74,8,200,58,128,28,
11436 211,160,130,52,78,26,26,110,248,0,0,170,4,12,70,137,195,38,0,0,42,68,159,7,
11437 84,3,154,150,16,70,137,195,67,77,223,0,0,20,224,20,160,152,23,223,0,0,20,
11438 226,9,65,154,232,147,161,115,59,224,0,2,156,84,12,50,9,195,38,0,0,41,133,
11439 30,224,32,54,186,221,128,60,
11440 };
11441 #elif defined(DUK_USE_DOUBLE_ME)
11442 DUK_INTERNAL const duk_uint8_t duk_builtins_data[4251] = {
11443 144,148,105,225,32,68,52,228,126,12,104,201,37,132,52,167,194,138,105,244,
11444 124,57,28,211,57,18,64,52,238,254,44,138,111,171,241,164,19,87,137,30,33,
11445 167,18,145,159,8,211,137,9,225,42,5,240,145,139,163,163,8,211,137,10,228,
11446 64,211,19,132,140,93,29,56,70,156,72,119,34,66,146,36,104,137,194,70,46,
11447 142,172,35,78,36,47,146,195,102,11,240,145,139,163,175,8,211,137,9,228,240,
11448 242,112,145,139,163,179,8,211,137,8,237,34,130,118,49,116,118,225,26,48,0,
11449 1,94,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
11450 33,8,66,26,180,41,97,167,64,150,34,33,154,112,0,1,87,247,35,79,103,237,198,
11451 174,216,47,31,23,95,17,13,31,217,96,211,49,50,53,212,77,141,24,0,0,179,10,
11452 228,240,242,15,128,140,65,128,134,188,0,0,89,167,97,181,224,0,2,205,62,53,
11453 224,0,2,205,66,237,120,0,0,179,81,204,107,192,0,5,154,150,67,94,0,0,44,212,
11454 245,90,240,0,1,102,169,162,215,128,0,11,53,93,150,188,0,0,89,171,111,53,
11455 108,150,163,70,0,0,42,2,249,50,94,124,35,68,225,146,49,13,24,0,0,165,161,
11456 124,153,47,62,12,130,112,201,24,132,56,97,115,16,0,0,62,31,192,0,0,0,51,48,
11457 0,0,60,31,192,0,0,0,50,241,32,26,193,55,132,112,161,156,72,135,26,41,200,
11458 140,114,163,156,201,7,56,79,9,80,47,132,140,93,19,160,43,145,3,76,78,18,49,
11459 116,78,144,238,68,133,36,72,209,19,132,140,93,19,168,47,146,195,102,11,240,
11460 145,139,162,117,132,242,120,121,56,72,197,209,59,2,59,72,160,157,140,93,19,
11461 181,36,242,50,143,36,31,131,162,166,7,144,238,133,227,226,235,224,242,161,
11462 249,18,21,100,20,207,44,199,151,180,122,89,135,152,154,121,153,199,156,158,
11463 121,218,7,158,162,121,250,71,160,166,122,26,135,162,170,122,58,199,164,16,
11464 240,70,68,226,27,51,199,138,120,35,34,112,171,112,38,121,1,124,153,47,62,
11465 17,162,112,201,19,211,11,228,201,121,240,100,19,134,72,158,160,91,201,18,
11466 186,44,3,68,79,122,168,151,115,165,40,21,18,227,65,198,231,200,8,68,184,84,
11467 53,19,38,120,128,145,144,78,25,59,72,163,48,64,144,200,39,12,157,164,80,46,
11468 185,143,115,72,217,230,72,9,35,68,225,147,180,138,51,68,9,17,162,112,201,
11469 218,69,2,235,152,247,52,141,158,108,128,98,72,64,121,51,132,4,81,164,144,
11470 128,242,104,136,0,16,92,38,14,49,39,199,197,211,116,240,242,113,197,231,18,
11471 53,189,116,65,131,18,124,117,155,199,197,207,36,103,142,12,146,20,80,249,
11472 186,60,116,4,204,73,241,214,111,31,23,60,145,158,56,208,48,146,229,146,3,2,
11473 82,65,155,195,94,3,10,36,4,201,196,64,56,100,42,26,78,62,46,121,35,60,113,
11474 152,16,25,10,134,147,143,139,158,72,205,4,151,21,0,73,16,11,230,144,12,88,
11475 144,153,39,52,144,69,241,37,72,217,240,151,153,27,36,57,178,230,16,16,137,
11476 114,68,2,200,62,81,1,8,151,11,23,100,141,229,18,6,34,92,37,230,70,201,1,89,
11477 57,36,2,40,152,151,44,129,83,18,124,117,155,199,197,207,36,103,142,75,12,
11478 11,151,46,89,40,18,37,200,64,12,154,236,252,238,185,23,95,213,1,132,234,0,
11479 194,245,128,14,56,37,199,89,188,124,92,242,70,120,232,16,26,137,113,241,
11480 116,221,60,60,156,113,122,36,10,62,46,121,35,60,113,18,225,27,70,18,32,10,
11481 201,211,32,67,107,104,100,42,26,78,24,147,153,35,181,181,207,64,67,107,104,
11482 100,42,26,78,72,147,153,35,181,181,207,68,16,218,218,91,156,170,63,134,36,
11483 230,72,237,109,116,136,16,218,218,91,156,170,63,146,36,230,72,237,109,116,
11484 137,16,96,128,228,2,6,191,46,3,71,147,68,4,16,22,188,169,240,16,40,104,242,
11485 135,198,171,44,68,65,5,217,231,215,6,231,62,188,8,49,1,3,162,92,4,98,12,41,
11486 7,33,148,53,242,128,97,32,130,3,9,205,16,38,199,198,14,9,0,111,115,225,0,8,
11487 250,72,240,207,128,241,37,73,25,18,40,0,178,58,11,56,192,2,201,104,17,35,
11488 160,9,39,70,114,8,6,147,214,129,18,74,240,30,141,145,208,89,203,62,3,161,
11489 163,37,248,226,185,244,11,88,37,62,33,163,37,248,226,185,252,0,127,255,130,
11490 146,164,142,32,26,1,36,230,18,1,164,7,43,163,194,0,71,128,105,64,216,7,192,
11491 52,192,197,66,230,72,192,52,224,209,32,232,34,68,62,129,113,32,232,34,114,
11492 40,49,231,16,254,0,63,255,208,99,2,140,44,92,206,8,224,143,4,225,147,210,
11493 124,13,44,92,206,9,195,39,30,228,54,126,163,225,200,169,198,133,42,166,191,
11494 246,3,11,251,0,24,71,4,120,9,251,8,10,17,193,30,9,195,39,1,63,105,1,98,112,
11495 201,199,185,13,159,1,63,105,32,48,156,209,2,126,227,224,58,26,50,95,142,47,
11496 192,208,22,176,74,124,67,70,75,241,197,248,26,64,213,184,64,89,56,39,49,
11497 224,137,62,36,2,176,19,17,254,68,3,196,143,88,4,79,162,0,210,32,34,35,253,
11498 72,5,146,208,34,125,144,5,147,214,137,253,208,9,149,3,41,197,13,55,233,0,
11499 185,187,139,117,137,30,8,18,39,172,1,25,187,139,112,128,178,113,110,177,35,
11500 193,2,68,245,128,23,55,114,143,121,35,193,2,68,245,130,8,205,220,91,132,5,
11501 147,148,123,201,30,8,18,39,172,16,18,113,67,63,128,3,68,143,32,39,243,32,
11502 42,83,4,103,46,89,19,63,224,208,16,70,142,92,178,38,127,193,164,8,67,68,
11503 186,12,146,247,154,1,165,64,202,113,252,160,131,32,7,35,167,26,50,235,231,
11504 130,48,179,192,65,148,69,19,214,2,251,85,2,232,72,31,255,253,239,255,255,
11505 255,255,226,122,196,55,106,160,93,9,0,0,0,0,0,4,0,0,3,49,0,0,3,225,252,0,0,
11506 0,0,143,94,233,34,104,169,54,144,210,161,168,158,32,0,0,120,63,128,0,0,0,
11507 17,235,72,96,77,21,38,210,26,84,53,19,196,0,0,15,15,240,0,0,0,0,253,35,228,
11508 133,185,176,0,0,44,15,0,0,0,0,8,117,128,190,212,128,82,109,33,179,33,137,
11509 24,31,255,231,232,127,255,255,255,228,58,196,55,106,64,41,54,144,217,144,
11510 196,140,15,255,243,252,63,255,255,255,241,15,4,100,78,33,179,60,120,167,
11511 130,50,39,10,183,2,103,144,113,8,151,10,134,162,100,221,16,18,137,113,13,
11512 153,12,72,238,137,1,81,46,52,28,110,232,148,53,18,228,128,82,113,13,153,12,
11513 72,238,137,142,73,78,52,0,0,0,0,0,0,0,0,8,58,254,1,12,38,248,134,23,130,0,
11514 60,221,194,162,228,30,244,128,217,187,132,187,220,210,54,104,2,247,132,5,
11515 205,220,124,72,36,73,14,110,252,132,25,128,193,94,8,200,149,200,3,237,38,
11516 43,31,192,54,186,213,128,57,45,56,210,0,0,62,31,192,0,0,0,49,90,251,224,6,
11517 77,220,24,38,78,74,113,67,77,124,16,50,110,228,208,194,114,83,138,26,107,
11518 224,172,37,240,97,41,187,139,112,128,178,112,96,153,57,41,197,13,53,240,
11519 113,41,187,139,112,128,178,114,104,97,57,41,197,13,53,240,128,195,95,8,44,
11520 61,240,132,216,93,33,133,192,128,14,98,79,147,67,9,129,0,44,196,159,11,69,
11521 175,152,32,35,100,33,135,24,147,237,38,34,246,139,95,48,64,70,200,68,8,49,
11522 39,198,57,179,61,144,138,22,98,79,180,152,153,215,54,103,178,17,129,204,73,
11523 240,96,153,44,132,112,163,18,125,164,196,62,130,100,178,18,1,140,73,240,96,
11524 197,144,146,18,98,79,180,152,135,208,98,200,74,8,49,39,195,186,145,149,144,
11525 150,22,98,79,180,152,143,215,82,50,178,19,2,140,73,241,136,109,38,73,89,9,
11526 161,166,36,251,73,137,157,67,105,50,74,200,78,10,49,39,201,16,78,104,229,
11527 100,39,134,152,147,237,38,41,116,130,115,71,43,33,64,60,196,159,24,133,173,
11528 18,32,156,209,202,200,81,18,49,39,218,76,76,234,22,180,72,130,115,71,43,33,
11529 72,68,196,159,38,134,19,46,105,56,226,150,68,157,160,1,228,73,242,104,97,
11530 46,16,31,34,79,140,66,214,137,16,78,104,229,108,169,137,72,147,237,38,38,
11531 117,11,90,36,65,57,163,149,178,168,21,34,79,146,32,156,209,202,218,250,161,
11532 178,36,251,73,138,93,32,156,209,202,218,250,193,82,36,248,196,54,147,36,
11533 173,191,174,27,34,79,180,152,153,212,54,147,36,173,191,176,17,34,79,135,
11534 117,35,43,115,236,133,200,147,237,38,35,245,212,140,173,207,180,15,34,79,
11535 131,4,201,108,173,133,72,147,237,38,33,244,19,37,178,184,17,34,79,140,115,
11536 102,123,107,238,133,200,147,237,38,38,117,205,153,237,175,188,23,34,79,133,
11537 162,215,204,16,17,182,254,248,116,137,62,210,98,47,104,181,243,4,4,109,191,
11538 192,131,152,147,230,8,8,217,12,16,60,137,62,96,128,141,178,193,181,55,136,
11539 200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,32,98,115,249,73,
11540 117,243,249,67,21,159,202,38,47,63,148,86,8,75,144,94,50,1,38,73,79,204,67,
11541 95,231,1,6,128,14,79,129,185,40,249,18,149,181,207,142,199,155,172,248,172,
11542 89,183,207,140,198,137,175,200,0,159,72,10,5,21,220,138,120,74,129,124,36,
11543 98,232,228,74,81,62,160,20,10,107,185,21,114,32,105,137,194,70,46,142,68,
11544 165,19,235,1,64,170,187,145,119,34,66,146,36,104,137,194,70,46,142,68,165,
11545 19,236,1,64,174,187,145,95,37,134,204,23,225,35,23,71,34,82,137,246,128,
11546 160,89,93,200,167,147,195,201,194,70,46,142,68,165,19,238,1,64,182,187,145,
11547 71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,72,115,96,0,118,105,160,
11548 0,0,0,0,91,60,165,195,201,194,8,134,149,216,130,0,192,41,224,136,2,48,176,
11549 228,1,149,13,195,15,0,200,209,97,71,128,99,32,176,131,192,113,57,143,0,167,
11550 131,32,230,80,28,202,139,175,237,2,48,189,160,20,1,119,48,87,193,186,129,
11551 89,56,72,197,209,200,193,185,35,23,71,109,13,219,36,98,232,237,156,13,26,
11552 208,211,14,102,19,87,137,91,95,128,0,10,64,24,92,0,0,82,2,53,63,240,49,204,
11553 202,10,14,38,78,44,141,52,207,31,0,0,22,32,129,100,180,8,148,145,78,102,
11554 152,80,113,50,113,100,105,166,120,248,0,0,177,1,65,196,201,199,20,178,36,
11555 227,224,0,2,200,3,6,133,41,35,31,0,0,22,1,44,57,137,62,33,179,216,162,152,
11556 192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,81,76,104,73,
11557 137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,166,56,36,196,
11558 159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,20,188,20,98,
11559 79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,68,137,62,81,
11560 13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,159,40,134,207,
11561 71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,67,103,167,165,
11562 77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,173,192,158,182,
11563 165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,140,35,103,0,0,
11564 3,192,252,0,0,0,0,206,25,228,35,208,226,100,150,211,201,29,162,44,140,35,
11565 103,0,0,3,192,252,0,0,0,0,206,25,244,35,208,226,100,150,211,201,29,162,44,
11566 140,35,103,0,0,3,192,252,0,0,0,0,206,26,4,35,208,226,100,150,211,201,29,
11567 162,44,140,35,103,0,0,0,1,0,0,0,0,0,206,26,20,35,208,226,100,150,211,201,
11568 29,162,44,140,35,103,0,0,0,1,0,0,0,0,0,206,26,36,35,208,226,100,150,211,
11569 201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,52,35,208,226,100,150,
11570 211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,68,35,208,226,100,
11571 150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,84,35,208,226,
11572 100,150,211,201,29,162,44,140,35,103,0,0,0,129,0,0,0,0,0,195,154,99,16,38,
11573 36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,25,18,0,125,
11574 162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,235,116,36,
11575 162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,196,54,122,
11576 58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,200,144,3,
11577 237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,213,146,138,
11578 77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,183,2,125,89,
11579 40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,221,64,172,157,
11580 89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,31,104,142,182,
11581 125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,18,0,124,67,103,
11582 213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,59,68,117,179,
11583 216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,39,104,142,182,
11584 122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,73,77,162,6,90,
11585 40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,61,29,110,132,
11586 148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,67,109,20,76,
11587 157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,167,165,213,
11588 146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,68,201,194,
11589 173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,193,182,138,
11590 38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,178,116,36,
11591 166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,157,162,58,
11592 217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,81,50,113,
11593 13,159,66,74,113,97,175,220,48,216,109,192,4,42,22,189,163,0,196,133,0,185,
11594 80,32,28,78,99,193,18,80,36,4,19,159,141,156,0,178,90,4,74,73,0,22,209,68,
11595 201,185,129,4,2,8,3,132,64,60,36,0,171,240,84,6,149,113,72,176,157,91,116,
11596 116,32,88,181,129,32,11,42,218,221,131,234,219,165,1,8,187,152,255,188,231,
11597 235,248,47,86,227,105,18,2,56,175,185,255,244,17,91,40,110,173,198,209,208,
11598 36,7,188,189,179,240,238,82,97,80,93,122,32,125,144,132,160,12,22,162,42,7,
11599 236,161,25,232,237,105,64,158,160,230,63,205,59,127,102,11,217,66,51,210,
11600 129,61,65,236,127,154,118,254,205,171,197,34,168,48,6,90,162,1,0,39,75,84,
11601 72,8,9,33,186,162,80,64,76,13,213,19,2,130,96,110,150,181,0,65,6,51,213,20,
11602 128,65,17,11,213,19,130,137,121,211,210,210,144,6,39,75,84,80,0,201,119,
11603 234,138,8,41,86,231,71,84,80,129,79,135,186,122,101,224,34,25,69,233,208,3,
11604 91,141,170,40,96,139,113,180,181,69,36,21,110,54,142,134,168,165,1,176,23,
11605 212,47,0,216,134,234,87,128,111,117,181,168,128,209,3,70,230,106,192,5,139,
11606 168,209,234,138,32,36,144,102,235,8,3,146,27,170,40,160,146,132,103,170,40,
11607 192,115,3,117,69,28,22,113,163,69,170,41,103,1,66,188,17,145,52,104,4,202,
11608 113,67,76,130,227,72,194,13,240,108,0,0,83,96,0,2,185,0,104,146,84,97,48,0,
11609 1,90,192,56,169,24,145,179,192,0,5,96,8,56,16,32,128,56,18,52,125,198,86,
11610 147,186,140,28,50,21,13,39,31,23,60,145,158,56,204,141,47,121,6,155,190,
11611 188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,199,68,
11612 14,49,39,199,197,211,116,240,242,113,197,231,18,180,254,4,3,17,46,18,243,
11613 35,100,128,172,156,146,70,163,150,76,34,248,146,164,108,248,75,204,141,146,
11614 28,217,115,9,27,79,11,241,173,235,162,160,224,200,2,206,9,113,13,148,192,
11615 209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,178,66,213,136,68,
11616 201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,38,232,255,252,92,
11617 221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,38,3,66,213,47,131,
11618 250,72,12,162,99,133,116,127,196,32,225,1,3,34,92,170,9,105,164,32,225,64,
11619 131,156,1,193,133,7,19,39,22,70,154,103,143,128,0,11,16,20,28,76,156,113,
11620 75,34,78,62,0,0,44,128,48,104,82,146,49,240,0,1,96,11,180,192,0,5,162,1,18,
11621 160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,121,35,180,69,145,132,
11622 108,224,0,0,120,31,128,0,0,0,25,188,56,132,122,28,76,146,218,121,35,180,69,
11623 145,132,108,224,0,0,120,31,128,0,0,0,40,160,45,110,23,30,176,33,184,0,0,
11624 181,32,29,235,2,27,199,23,0,0,22,196,51,120,129,8,244,56,153,37,180,242,71,
11625 104,139,35,8,217,192,0,0,240,63,0,0,0,0,51,120,145,8,244,56,153,37,180,242,
11626 71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,120,161,8,244,56,153,37,180,
11627 242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,120,177,8,244,56,153,37,
11628 180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,120,193,8,244,56,153,
11629 37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,120,209,8,244,56,
11630 153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,120,225,8,244,
11631 56,153,37,180,242,71,104,139,35,8,217,192,0,0,32,64,0,0,0,0,32,227,194,0,
11632 97,57,162,4,246,40,5,34,92,35,68,225,161,166,219,16,16,137,112,52,41,73,29,
11633 169,1,65,196,201,197,145,166,153,246,8,3,137,204,120,34,74,8,200,58,128,28,
11634 211,160,130,52,78,26,26,110,248,0,0,170,4,12,70,137,195,38,0,0,42,68,159,7,
11635 84,3,154,150,16,70,137,195,67,77,223,0,0,20,224,20,160,152,23,223,0,0,20,
11636 226,9,65,154,232,147,161,115,59,224,0,2,156,84,12,50,9,195,38,0,0,41,133,
11637 30,224,32,54,186,221,128,60,
11638 };
11639 #else
11640 #error invalid endianness defines
11641 #endif
11642 #endif  /* DUK_USE_ROM_OBJECTS */
11643 
11644 /* automatic undefs */
11645 #undef DUK__REFCINIT
11646 /*
11647  *  Error and fatal handling.
11648  */
11649 
11650 /* #include duk_internal.h -> already included */
11651 
11652 #define DUK__ERRFMT_BUFSIZE  256  /* size for formatting buffers */
11653 
11654 #if defined(DUK_USE_VERBOSE_ERRORS)
11655 
duk_err_handle_error_fmt(duk_hthread * thr,const char * filename,duk_uint_t line_and_code,const char * fmt,...)11656 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, ...) {
11657 	va_list ap;
11658 	char msg[DUK__ERRFMT_BUFSIZE];
11659 	va_start(ap, fmt);
11660 	(void) DUK_VSNPRINTF(msg, sizeof(msg), fmt, ap);
11661 	msg[sizeof(msg) - 1] = (char) 0;
11662 	duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
11663 	va_end(ap);  /* dead code, but ensures portability (see Linux man page notes) */
11664 }
11665 
duk_err_handle_error(duk_hthread * thr,const char * filename,duk_uint_t line_and_code,const char * msg)11666 DUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg) {
11667 	duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
11668 }
11669 
11670 #else  /* DUK_USE_VERBOSE_ERRORS */
11671 
duk_err_handle_error(duk_hthread * thr,duk_errcode_t code)11672 DUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code) {
11673 	duk_err_create_and_throw(thr, code);
11674 }
11675 
11676 #endif  /* DUK_USE_VERBOSE_ERRORS */
11677 
11678 /*
11679  *  Error throwing helpers
11680  */
11681 
11682 #if defined(DUK_USE_VERBOSE_ERRORS)
11683 #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)11684 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) {
11685 	DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
11686 	                   expect_name, duk_get_type_name(thr, idx), (long) idx);
11687 }
11688 #else
duk_err_require_type_index(duk_hthread * thr,const char * filename,duk_int_t linenumber,duk_idx_t idx,const char * expect_name)11689 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) {
11690 	DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
11691 	                   expect_name, duk_push_string_readable(thr, idx), (long) idx);
11692 }
11693 #endif
duk_err_error_internal(duk_hthread * thr,const char * filename,duk_int_t linenumber)11694 DUK_INTERNAL DUK_COLD void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11695 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, DUK_STR_INTERNAL_ERROR);
11696 }
duk_err_error_alloc_failed(duk_hthread * thr,const char * filename,duk_int_t linenumber)11697 DUK_INTERNAL DUK_COLD void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11698 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, DUK_STR_ALLOC_FAILED);
11699 }
duk_err_error(duk_hthread * thr,const char * filename,duk_int_t linenumber,const char * message)11700 DUK_INTERNAL DUK_COLD void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
11701 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, message);
11702 }
duk_err_range(duk_hthread * thr,const char * filename,duk_int_t linenumber,const char * message)11703 DUK_INTERNAL DUK_COLD void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
11704 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, message);
11705 }
duk_err_range_index(duk_hthread * thr,const char * filename,duk_int_t linenumber,duk_idx_t idx)11706 DUK_INTERNAL DUK_COLD void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx) {
11707 	DUK_ERROR_RAW_FMT1(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, "invalid stack index %ld", (long) (idx));
11708 }
duk_err_range_push_beyond(duk_hthread * thr,const char * filename,duk_int_t linenumber)11709 DUK_INTERNAL DUK_COLD void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11710 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
11711 }
duk_err_type_invalid_args(duk_hthread * thr,const char * filename,duk_int_t linenumber)11712 DUK_INTERNAL DUK_COLD void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11713 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_ARGS);
11714 }
duk_err_type_invalid_state(duk_hthread * thr,const char * filename,duk_int_t linenumber)11715 DUK_INTERNAL DUK_COLD void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11716 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_STATE);
11717 }
duk_err_type_invalid_trap_result(duk_hthread * thr,const char * filename,duk_int_t linenumber)11718 DUK_INTERNAL DUK_COLD void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11719 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_TRAP_RESULT);
11720 }
11721 #else
11722 /* The file/line arguments are NULL and 0, they're ignored by DUK_ERROR_RAW()
11723  * when non-verbose errors are used.
11724  */
11725 
11726 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)11727 DUK_LOCAL void duk__err_shared(duk_hthread *thr, duk_errcode_t code) {
11728 	DUK_ERROR_RAW(thr, NULL, 0, code, NULL);
11729 }
duk_err_error(duk_hthread * thr)11730 DUK_INTERNAL DUK_COLD void duk_err_error(duk_hthread *thr) {
11731 	duk__err_shared(thr, DUK_ERR_ERROR);
11732 }
duk_err_range(duk_hthread * thr)11733 DUK_INTERNAL DUK_COLD void duk_err_range(duk_hthread *thr) {
11734 	duk__err_shared(thr, DUK_ERR_RANGE_ERROR);
11735 }
duk_err_eval(duk_hthread * thr)11736 DUK_INTERNAL DUK_COLD void duk_err_eval(duk_hthread *thr) {
11737 	duk__err_shared(thr, DUK_ERR_EVAL_ERROR);
11738 }
duk_err_reference(duk_hthread * thr)11739 DUK_INTERNAL DUK_COLD void duk_err_reference(duk_hthread *thr) {
11740 	duk__err_shared(thr, DUK_ERR_REFERENCE_ERROR);
11741 }
duk_err_syntax(duk_hthread * thr)11742 DUK_INTERNAL DUK_COLD void duk_err_syntax(duk_hthread *thr) {
11743 	duk__err_shared(thr, DUK_ERR_SYNTAX_ERROR);
11744 }
duk_err_type(duk_hthread * thr)11745 DUK_INTERNAL DUK_COLD void duk_err_type(duk_hthread *thr) {
11746 	duk__err_shared(thr, DUK_ERR_TYPE_ERROR);
11747 }
duk_err_uri(duk_hthread * thr)11748 DUK_INTERNAL DUK_COLD void duk_err_uri(duk_hthread *thr) {
11749 	duk__err_shared(thr, DUK_ERR_URI_ERROR);
11750 }
11751 #endif
11752 
11753 /*
11754  *  Default fatal error handler
11755  */
11756 
duk_default_fatal_handler(void * udata,const char * msg)11757 DUK_INTERNAL DUK_COLD void duk_default_fatal_handler(void *udata, const char *msg) {
11758 	DUK_UNREF(udata);
11759 	DUK_UNREF(msg);
11760 
11761 	msg = msg ? msg : "NULL";
11762 
11763 #if defined(DUK_USE_FATAL_HANDLER)
11764 	/* duk_config.h provided a custom default fatal handler. */
11765 	DUK_D(DUK_DPRINT("custom default fatal error handler called: %s", msg));
11766 	DUK_USE_FATAL_HANDLER(udata, msg);
11767 #elif defined(DUK_USE_CPP_EXCEPTIONS)
11768 	/* With C++ use a duk_fatal_exception which user code can catch in
11769 	 * a natural way.
11770 	 */
11771 	DUK_D(DUK_DPRINT("built-in default C++ fatal error handler called: %s", msg));
11772 	throw duk_fatal_exception(msg);
11773 #else
11774 	/* Default behavior is to abort() on error.  There's no printout
11775 	 * which makes this awkward, so it's always recommended to use an
11776 	 * explicit fatal error handler.
11777 	 *
11778 	 * ====================================================================
11779 	 * NOTE: If you are seeing this, you are most likely dealing with an
11780 	 * uncaught error.  You should provide a fatal error handler in Duktape
11781 	 * heap creation, and should consider using a protected call as your
11782 	 * first call into an empty Duktape context to properly handle errors.
11783 	 * See:
11784 	 *   - http://duktape.org/guide.html#error-handling
11785 	 *   - http://wiki.duktape.org/HowtoFatalErrors.html
11786 	 *   - http://duktape.org/api.html#taglist-protected
11787 	 * ====================================================================
11788 	 */
11789 	DUK_D(DUK_DPRINT("built-in default fatal error handler called: %s", msg));
11790 	DUK_ABORT();
11791 #endif
11792 
11793 	DUK_D(DUK_DPRINT("fatal error handler returned, enter forever loop"));
11794 	for (;;) {
11795 		/* Loop forever to ensure we don't return. */
11796 	}
11797 }
11798 
11799 /* automatic undefs */
11800 #undef DUK__ERRFMT_BUFSIZE
11801 /*
11802  *  Various Unicode help functions for character classification predicates,
11803  *  case conversion, decoding, etc.
11804  */
11805 
11806 /* #include duk_internal.h -> already included */
11807 
11808 /*
11809  *  Fast path tables
11810  */
11811 
11812 #if defined(DUK_USE_IDCHAR_FASTPATH)
11813 DUK_INTERNAL const duk_int8_t duk_is_idchar_tab[128] = {
11814 	/* 0: not IdentifierStart or IdentifierPart
11815 	 * 1: IdentifierStart and IdentifierPart
11816 	 * -1: IdentifierPart only
11817 	 */
11818 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x00...0x0f */
11819 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x10...0x1f */
11820 	0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x20...0x2f */
11821 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  0,  0,  0,  0,  0,   /* 0x30...0x3f */
11822 	0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,   /* 0x40...0x4f */
11823 	1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  1,   /* 0x50...0x5f */
11824 	0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,   /* 0x60...0x6f */
11825 	1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0    /* 0x70...0x7f */
11826 };
11827 #endif
11828 
11829 /*
11830  *  XUTF-8 and CESU-8 encoding/decoding
11831  */
11832 
duk_unicode_get_xutf8_length(duk_ucodepoint_t cp)11833 DUK_INTERNAL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp) {
11834 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
11835 	if (x < 0x80UL) {
11836 		/* 7 bits */
11837 		return 1;
11838 	} else if (x < 0x800UL) {
11839 		/* 11 bits */
11840 		return 2;
11841 	} else if (x < 0x10000UL) {
11842 		/* 16 bits */
11843 		return 3;
11844 	} else if (x < 0x200000UL) {
11845 		/* 21 bits */
11846 		return 4;
11847 	} else if (x < 0x4000000UL) {
11848 		/* 26 bits */
11849 		return 5;
11850 	} else if (x < (duk_ucodepoint_t) 0x80000000UL) {
11851 		/* 31 bits */
11852 		return 6;
11853 	} else {
11854 		/* 36 bits */
11855 		return 7;
11856 	}
11857 }
11858 
11859 #if defined(DUK_USE_ASSERTIONS)
duk_unicode_get_cesu8_length(duk_ucodepoint_t cp)11860 DUK_INTERNAL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp) {
11861 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
11862 	if (x < 0x80UL) {
11863 		/* 7 bits */
11864 		return 1;
11865 	} else if (x < 0x800UL) {
11866 		/* 11 bits */
11867 		return 2;
11868 	} else if (x < 0x10000UL) {
11869 		/* 16 bits */
11870 		return 3;
11871 	} else {
11872 		/* Encoded as surrogate pair, each encoding to 3 bytes for
11873 		 * 6 bytes total.  Codepoints above U+10FFFF encode as 6 bytes
11874 		 * too, see duk_unicode_encode_cesu8().
11875 		  */
11876 		return 3 + 3;
11877 	}
11878 }
11879 #endif  /* DUK_USE_ASSERTIONS */
11880 
11881 DUK_INTERNAL const duk_uint8_t duk_unicode_xutf8_markers[7] = {
11882 	0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe
11883 };
11884 
11885 /* Encode to extended UTF-8; 'out' must have space for at least
11886  * DUK_UNICODE_MAX_XUTF8_LENGTH bytes.  Allows encoding of any
11887  * 32-bit (unsigned) codepoint.
11888  */
duk_unicode_encode_xutf8(duk_ucodepoint_t cp,duk_uint8_t * out)11889 DUK_INTERNAL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out) {
11890 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
11891 	duk_small_int_t len;
11892 	duk_uint8_t marker;
11893 	duk_small_int_t i;
11894 
11895 	len = duk_unicode_get_xutf8_length(cp);
11896 	DUK_ASSERT(len > 0);
11897 
11898 	marker = duk_unicode_xutf8_markers[len - 1];  /* 64-bit OK because always >= 0 */
11899 
11900 	i = len;
11901 	DUK_ASSERT(i > 0);
11902 	do {
11903 		i--;
11904 		if (i > 0) {
11905 			out[i] = (duk_uint8_t) (0x80 + (x & 0x3f));
11906 			x >>= 6;
11907 		} else {
11908 			/* Note: masking of 'x' is not necessary because of
11909 			 * range check and shifting -> no bits overlapping
11910 			 * the marker should be set.
11911 			 */
11912 			out[0] = (duk_uint8_t) (marker + x);
11913 		}
11914 	} while (i > 0);
11915 
11916 	return len;
11917 }
11918 
11919 /* Encode to CESU-8; 'out' must have space for at least
11920  * DUK_UNICODE_MAX_CESU8_LENGTH bytes; codepoints above U+10FFFF
11921  * will encode to garbage but won't overwrite the output buffer.
11922  */
duk_unicode_encode_cesu8(duk_ucodepoint_t cp,duk_uint8_t * out)11923 DUK_INTERNAL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out) {
11924 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
11925 	duk_small_int_t len;
11926 
11927 	if (x < 0x80UL) {
11928 		out[0] = (duk_uint8_t) x;
11929 		len = 1;
11930 	} else if (x < 0x800UL) {
11931 		out[0] = (duk_uint8_t) (0xc0 + ((x >> 6) & 0x1f));
11932 		out[1] = (duk_uint8_t) (0x80 + (x & 0x3f));
11933 		len = 2;
11934 	} else if (x < 0x10000UL) {
11935 		/* surrogate pairs get encoded here */
11936 		out[0] = (duk_uint8_t) (0xe0 + ((x >> 12) & 0x0f));
11937 		out[1] = (duk_uint8_t) (0x80 + ((x >> 6) & 0x3f));
11938 		out[2] = (duk_uint8_t) (0x80 + (x & 0x3f));
11939 		len = 3;
11940 	} else {
11941 		/*
11942 		 *  Unicode codepoints above U+FFFF are encoded as surrogate
11943 		 *  pairs here.  This ensures that all CESU-8 codepoints are
11944 		 *  16-bit values as expected in ECMAScript.  The surrogate
11945 		 *  pairs always get a 3-byte encoding (each) in CESU-8.
11946 		 *  See: http://en.wikipedia.org/wiki/Surrogate_pair
11947 		 *
11948 		 *  20-bit codepoint, 10 bits (A and B) per surrogate pair:
11949 		 *
11950 		 *    x = 0b00000000 0000AAAA AAAAAABB BBBBBBBB
11951 		 *  sp1 = 0b110110AA AAAAAAAA  (0xd800 + ((x >> 10) & 0x3ff))
11952 		 *  sp2 = 0b110111BB BBBBBBBB  (0xdc00 + (x & 0x3ff))
11953 		 *
11954 		 *  Encoded into CESU-8:
11955 		 *
11956 		 *  sp1 -> 0b11101101  (0xe0 + ((sp1 >> 12) & 0x0f))
11957 		 *      -> 0b1010AAAA  (0x80 + ((sp1 >> 6) & 0x3f))
11958 		 *      -> 0b10AAAAAA  (0x80 + (sp1 & 0x3f))
11959 		 *  sp2 -> 0b11101101  (0xe0 + ((sp2 >> 12) & 0x0f))
11960 		 *      -> 0b1011BBBB  (0x80 + ((sp2 >> 6) & 0x3f))
11961 		 *      -> 0b10BBBBBB  (0x80 + (sp2 & 0x3f))
11962 		 *
11963 		 *  Note that 0x10000 must be subtracted first.  The code below
11964 		 *  avoids the sp1, sp2 temporaries which saves around 20 bytes
11965 		 *  of code.
11966 		 */
11967 
11968 		x -= 0x10000UL;
11969 
11970 		out[0] = (duk_uint8_t) (0xed);
11971 		out[1] = (duk_uint8_t) (0xa0 + ((x >> 16) & 0x0f));
11972 		out[2] = (duk_uint8_t) (0x80 + ((x >> 10) & 0x3f));
11973 		out[3] = (duk_uint8_t) (0xed);
11974 		out[4] = (duk_uint8_t) (0xb0 + ((x >> 6) & 0x0f));
11975 		out[5] = (duk_uint8_t) (0x80 + (x & 0x3f));
11976 		len = 6;
11977 	}
11978 
11979 	return len;
11980 }
11981 
11982 /* 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)11983 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) {
11984 	const duk_uint8_t *p;
11985 	duk_uint32_t res;
11986 	duk_uint_fast8_t ch;
11987 	duk_small_int_t n;
11988 
11989 	DUK_UNREF(thr);
11990 
11991 	p = *ptr;
11992 	if (p < ptr_start || p >= ptr_end) {
11993 		goto fail;
11994 	}
11995 
11996 	/*
11997 	 *  UTF-8 decoder which accepts longer than standard byte sequences.
11998 	 *  This allows full 32-bit code points to be used.
11999 	 */
12000 
12001 	ch = (duk_uint_fast8_t) (*p++);
12002 	if (ch < 0x80) {
12003 		/* 0xxx xxxx   [7 bits] */
12004 		res = (duk_uint32_t) (ch & 0x7f);
12005 		n = 0;
12006 	} else if (ch < 0xc0) {
12007 		/* 10xx xxxx -> invalid */
12008 		goto fail;
12009 	} else if (ch < 0xe0) {
12010 		/* 110x xxxx   10xx xxxx   [11 bits] */
12011 		res = (duk_uint32_t) (ch & 0x1f);
12012 		n = 1;
12013 	} else if (ch < 0xf0) {
12014 		/* 1110 xxxx   10xx xxxx   10xx xxxx   [16 bits] */
12015 		res = (duk_uint32_t) (ch & 0x0f);
12016 		n = 2;
12017 	} else if (ch < 0xf8) {
12018 		/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx   [21 bits] */
12019 		res = (duk_uint32_t) (ch & 0x07);
12020 		n = 3;
12021 	} else if (ch < 0xfc) {
12022 		/* 1111 10xx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [26 bits] */
12023 		res = (duk_uint32_t) (ch & 0x03);
12024 		n = 4;
12025 	} else if (ch < 0xfe) {
12026 		/* 1111 110x   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [31 bits] */
12027 		res = (duk_uint32_t) (ch & 0x01);
12028 		n = 5;
12029 	} else if (ch < 0xff) {
12030 		/* 1111 1110   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [36 bits] */
12031 		res = (duk_uint32_t) (0);
12032 		n = 6;
12033 	} else {
12034 		/* 8-byte format could be:
12035 		 * 1111 1111   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [41 bits]
12036 		 *
12037 		 * However, this format would not have a zero bit following the
12038 		 * leading one bits and would not allow 0xFF to be used as an
12039 		 * "invalid xutf-8" marker for internal keys.  Further, 8-byte
12040 		 * encodings (up to 41 bit code points) are not currently needed.
12041 		 */
12042 		goto fail;
12043 	}
12044 
12045 	DUK_ASSERT(p >= ptr_start);  /* verified at beginning */
12046 	if (p + n > ptr_end) {
12047 		/* check pointer at end */
12048 		goto fail;
12049 	}
12050 
12051 	while (n > 0) {
12052 		DUK_ASSERT(p >= ptr_start && p < ptr_end);
12053 		ch = (duk_uint_fast8_t) (*p++);
12054 #if 0
12055 		if (ch & 0xc0 != 0x80) {
12056 			/* not a continuation byte */
12057 			p--;
12058 			*ptr = p;
12059 			*out_cp = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
12060 			return 1;
12061 		}
12062 #endif
12063 		res = (res << 6) + (duk_uint32_t) (ch & 0x3f);
12064 		n--;
12065 	}
12066 
12067 	*ptr = p;
12068 	*out_cp = res;
12069 	return 1;
12070 
12071  fail:
12072 	return 0;
12073 }
12074 
12075 /* 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)12076 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) {
12077 	duk_ucodepoint_t cp;
12078 
12079 	if (duk_unicode_decode_xutf8(thr, ptr, ptr_start, ptr_end, &cp)) {
12080 		return cp;
12081 	}
12082 	DUK_ERROR_INTERNAL(thr);
12083 	DUK_WO_NORETURN(return 0;);
12084 }
12085 
12086 /* Compute (extended) utf-8 length without codepoint encoding validation,
12087  * used for string interning.
12088  *
12089  * NOTE: This algorithm is performance critical, more so than string hashing
12090  * in some cases.  It is needed when interning a string and needs to scan
12091  * every byte of the string with no skipping.  Having an ASCII fast path
12092  * is useful if possible in the algorithm.  The current algorithms were
12093  * chosen from several variants, based on x64 gcc -O2 testing.  See:
12094  * https://github.com/svaarala/duktape/pull/422
12095  *
12096  * NOTE: must match tools/dukutil.py:duk_unicode_unvalidated_utf8_length().
12097  */
12098 
12099 #if defined(DUK_USE_PREFER_SIZE)
12100 /* Small variant; roughly 150 bytes smaller than the fast variant. */
duk_unicode_unvalidated_utf8_length(const duk_uint8_t * data,duk_size_t blen)12101 DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
12102 	const duk_uint8_t *p;
12103 	const duk_uint8_t *p_end;
12104 	duk_size_t ncont;
12105 	duk_size_t clen;
12106 
12107 	p = data;
12108 	p_end = data + blen;
12109 	ncont = 0;
12110 	while (p != p_end) {
12111 		duk_uint8_t x;
12112 		x = *p++;
12113 		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
12114 			ncont++;
12115 		}
12116 	}
12117 
12118 	DUK_ASSERT(ncont <= blen);
12119 	clen = blen - ncont;
12120 	DUK_ASSERT(clen <= blen);
12121 	return clen;
12122 }
12123 #else  /* DUK_USE_PREFER_SIZE */
12124 /* This seems like a good overall approach.  Fast path for ASCII in 4 byte
12125  * blocks.
12126  */
duk_unicode_unvalidated_utf8_length(const duk_uint8_t * data,duk_size_t blen)12127 DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
12128 	const duk_uint8_t *p;
12129 	const duk_uint8_t *p_end;
12130 	const duk_uint32_t *p32_end;
12131 	const duk_uint32_t *p32;
12132 	duk_size_t ncont;
12133 	duk_size_t clen;
12134 
12135 	ncont = 0;  /* number of continuation (non-initial) bytes in [0x80,0xbf] */
12136 	p = data;
12137 	p_end = data + blen;
12138 	if (blen < 16) {
12139 		goto skip_fastpath;
12140 	}
12141 
12142 	/* Align 'p' to 4; the input data may have arbitrary alignment.
12143 	 * End of string check not needed because blen >= 16.
12144 	 */
12145 	while (((duk_size_t) (const void *) p) & 0x03U) {
12146 		duk_uint8_t x;
12147 		x = *p++;
12148 		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
12149 			ncont++;
12150 		}
12151 	}
12152 
12153 	/* Full, aligned 4-byte reads. */
12154 	p32_end = (const duk_uint32_t *) (const void *) (p + ((duk_size_t) (p_end - p) & (duk_size_t) (~0x03)));
12155 	p32 = (const duk_uint32_t *) (const void *) p;
12156 	while (p32 != (const duk_uint32_t *) p32_end) {
12157 		duk_uint32_t x;
12158 		x = *p32++;
12159 		if (DUK_LIKELY((x & 0x80808080UL) == 0)) {
12160 			;  /* ASCII fast path */
12161 		} else {
12162 			/* Flip highest bit of each byte which changes
12163 			 * the bit pattern 10xxxxxx into 00xxxxxx which
12164 			 * allows an easy bit mask test.
12165 			 */
12166 			x ^= 0x80808080UL;
12167 			if (DUK_UNLIKELY(!(x & 0xc0000000UL))) {
12168 				ncont++;
12169 			}
12170 			if (DUK_UNLIKELY(!(x & 0x00c00000UL))) {
12171 				ncont++;
12172 			}
12173 			if (DUK_UNLIKELY(!(x & 0x0000c000UL))) {
12174 				ncont++;
12175 			}
12176 			if (DUK_UNLIKELY(!(x & 0x000000c0UL))) {
12177 				ncont++;
12178 			}
12179 		}
12180 	}
12181 	p = (const duk_uint8_t *) p32;
12182 	/* Fall through to handle the rest. */
12183 
12184  skip_fastpath:
12185 	while (p != p_end) {
12186 		duk_uint8_t x;
12187 		x = *p++;
12188 		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
12189 			ncont++;
12190 		}
12191 	}
12192 
12193 	DUK_ASSERT(ncont <= blen);
12194 	clen = blen - ncont;
12195 	DUK_ASSERT(clen <= blen);
12196 	return clen;
12197 }
12198 #endif  /* DUK_USE_PREFER_SIZE */
12199 
12200 /*
12201  *  Unicode range matcher
12202  *
12203  *  Matches a codepoint against a packed bitstream of character ranges.
12204  *  Used for slow path Unicode matching.
12205  */
12206 
12207 /* Must match tools/extract_chars.py, generate_match_table3(). */
duk__uni_decode_value(duk_bitdecoder_ctx * bd_ctx)12208 DUK_LOCAL duk_uint32_t duk__uni_decode_value(duk_bitdecoder_ctx *bd_ctx) {
12209 	duk_uint32_t t;
12210 
12211 	t = (duk_uint32_t) duk_bd_decode(bd_ctx, 4);
12212 	if (t <= 0x0eU) {
12213 		return t;
12214 	}
12215 	t = (duk_uint32_t) duk_bd_decode(bd_ctx, 8);
12216 	if (t <= 0xfdU) {
12217 		return t + 0x0f;
12218 	}
12219 	if (t == 0xfeU) {
12220 		t = (duk_uint32_t) duk_bd_decode(bd_ctx, 12);
12221 		return t + 0x0fU + 0xfeU;
12222 	} else {
12223 		t = (duk_uint32_t) duk_bd_decode(bd_ctx, 24);
12224 		return t + 0x0fU + 0xfeU + 0x1000UL;
12225 	}
12226 }
12227 
duk__uni_range_match(const duk_uint8_t * unitab,duk_size_t unilen,duk_codepoint_t cp)12228 DUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_size_t unilen, duk_codepoint_t cp) {
12229 	duk_bitdecoder_ctx bd_ctx;
12230 	duk_codepoint_t prev_re;
12231 
12232 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
12233 	bd_ctx.data = (const duk_uint8_t *) unitab;
12234 	bd_ctx.length = (duk_size_t) unilen;
12235 
12236 	prev_re = 0;
12237 	for (;;) {
12238 		duk_codepoint_t r1, r2;
12239 		r1 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
12240 		if (r1 == 0) {
12241 			break;
12242 		}
12243 		r2 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
12244 
12245 		r1 = prev_re + r1;
12246 		r2 = r1 + r2;
12247 		prev_re = r2;
12248 
12249 		/* [r1,r2] is the range */
12250 
12251 		DUK_DDD(DUK_DDDPRINT("duk__uni_range_match: cp=%06lx range=[0x%06lx,0x%06lx]",
12252 		                     (unsigned long) cp, (unsigned long) r1, (unsigned long) r2));
12253 		if (cp >= r1 && cp <= r2) {
12254 			return 1;
12255 		}
12256 	}
12257 
12258 	return 0;
12259 }
12260 
12261 /*
12262  *  "WhiteSpace" production check.
12263  */
12264 
duk_unicode_is_whitespace(duk_codepoint_t cp)12265 DUK_INTERNAL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp) {
12266 	/*
12267 	 *  E5 Section 7.2 specifies six characters specifically as
12268 	 *  white space:
12269 	 *
12270 	 *    0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATION;;;;
12271 	 *    000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;;
12272 	 *    000C;<control>;Cc;0;WS;;;;;N;FORM FEED (FF);;;;
12273 	 *    0020;SPACE;Zs;0;WS;;;;;N;;;;;
12274 	 *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
12275 	 *    FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;;
12276 	 *
12277 	 *  It also specifies any Unicode category 'Zs' characters as white
12278 	 *  space.  These can be extracted with the "tools/extract_chars.py" script.
12279 	 *  Current result:
12280 	 *
12281 	 *    RAW OUTPUT:
12282 	 *    ===========
12283 	 *    0020;SPACE;Zs;0;WS;;;;;N;;;;;
12284 	 *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
12285 	 *    1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;;
12286 	 *    180E;MONGOLIAN VOWEL SEPARATOR;Zs;0;WS;;;;;N;;;;;
12287 	 *    2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;;
12288 	 *    2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;;
12289 	 *    2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12290 	 *    2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12291 	 *    2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12292 	 *    2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12293 	 *    2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12294 	 *    2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;;
12295 	 *    2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12296 	 *    2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12297 	 *    200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12298 	 *    202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;;
12299 	 *    205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12300 	 *    3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;
12301 	 *
12302 	 *    RANGES:
12303 	 *    =======
12304 	 *    0x0020
12305 	 *    0x00a0
12306 	 *    0x1680
12307 	 *    0x180e
12308 	 *    0x2000 ... 0x200a
12309 	 *    0x202f
12310 	 *    0x205f
12311 	 *    0x3000
12312 	 *
12313 	 *  A manual decoder (below) is probably most compact for this.
12314 	 */
12315 
12316 	duk_uint_fast8_t lo;
12317 	duk_uint_fast32_t hi;
12318 
12319 	/* cp == -1 (EOF) never matches and causes return value 0 */
12320 
12321 	lo = (duk_uint_fast8_t) (cp & 0xff);
12322 	hi = (duk_uint_fast32_t) (cp >> 8);  /* does not fit into an uchar */
12323 
12324 	if (hi == 0x0000UL) {
12325 		if (lo == 0x09U || lo == 0x0bU || lo == 0x0cU ||
12326 		    lo == 0x20U || lo == 0xa0U) {
12327 			return 1;
12328 		}
12329 	} else if (hi == 0x0020UL) {
12330 		if (lo <= 0x0aU || lo == 0x2fU || lo == 0x5fU) {
12331 			return 1;
12332 		}
12333 	} else if (cp == 0x1680L || cp == 0x180eL || cp == 0x3000L ||
12334 	           cp == 0xfeffL) {
12335 		return 1;
12336 	}
12337 
12338 	return 0;
12339 }
12340 
12341 /*
12342  *  "LineTerminator" production check.
12343  */
12344 
duk_unicode_is_line_terminator(duk_codepoint_t cp)12345 DUK_INTERNAL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp) {
12346 	/*
12347 	 *  E5 Section 7.3
12348 	 *
12349 	 *  A LineTerminatorSequence essentially merges <CR> <LF> sequences
12350 	 *  into a single line terminator.  This must be handled by the caller.
12351 	 */
12352 
12353 	if (cp == 0x000aL || cp == 0x000dL || cp == 0x2028L ||
12354 	    cp == 0x2029L) {
12355 		return 1;
12356 	}
12357 
12358 	return 0;
12359 }
12360 
12361 /*
12362  *  "IdentifierStart" production check.
12363  */
12364 
duk_unicode_is_identifier_start(duk_codepoint_t cp)12365 DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp) {
12366 	/*
12367 	 *  E5 Section 7.6:
12368 	 *
12369 	 *    IdentifierStart:
12370 	 *      UnicodeLetter
12371 	 *      $
12372 	 *      _
12373 	 *      \ UnicodeEscapeSequence
12374 	 *
12375 	 *  IdentifierStart production has one multi-character production:
12376 	 *
12377 	 *    \ UnicodeEscapeSequence
12378 	 *
12379 	 *  The '\' character is -not- matched by this function.  Rather, the caller
12380 	 *  should decode the escape and then call this function to check whether the
12381 	 *  decoded character is acceptable (see discussion in E5 Section 7.6).
12382 	 *
12383 	 *  The "UnicodeLetter" alternative of the production allows letters
12384 	 *  from various Unicode categories.  These can be extracted with the
12385 	 *  "tools/extract_chars.py" script.
12386 	 *
12387 	 *  Because the result has hundreds of Unicode codepoint ranges, matching
12388 	 *  for any values >= 0x80 are done using a very slow range-by-range scan
12389 	 *  and a packed range format.
12390 	 *
12391 	 *  The ASCII portion (codepoints 0x00 ... 0x7f) is fast-pathed below because
12392 	 *  it matters the most.  The ASCII related ranges of IdentifierStart are:
12393 	 *
12394 	 *    0x0041 ... 0x005a     ['A' ... 'Z']
12395 	 *    0x0061 ... 0x007a     ['a' ... 'z']
12396 	 *    0x0024                ['$']
12397 	 *    0x005f                ['_']
12398 	 */
12399 
12400 	/* ASCII (and EOF) fast path -- quick accept and reject */
12401 	if (cp <= 0x7fL) {
12402 #if defined(DUK_USE_IDCHAR_FASTPATH)
12403 		return (cp >= 0) && (duk_is_idchar_tab[cp] > 0);
12404 #else
12405 		if ((cp >= 'a' && cp <= 'z') ||
12406 		    (cp >= 'A' && cp <= 'Z') ||
12407 		    cp == '_' || cp == '$') {
12408 			return 1;
12409 		}
12410 		return 0;
12411 #endif
12412 	}
12413 
12414 	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
12415 
12416 #if defined(DUK_USE_SOURCE_NONBMP)
12417 	if (duk__uni_range_match(duk_unicode_ids_noa,
12418 	                         (duk_size_t) sizeof(duk_unicode_ids_noa),
12419 	                         (duk_codepoint_t) cp)) {
12420 		return 1;
12421 	}
12422 	return 0;
12423 #else
12424 	if (cp < 0x10000L) {
12425 		if (duk__uni_range_match(duk_unicode_ids_noabmp,
12426 		                         sizeof(duk_unicode_ids_noabmp),
12427 		                         (duk_codepoint_t) cp)) {
12428 			return 1;
12429 		}
12430 		return 0;
12431 	} else {
12432 		/* without explicit non-BMP support, assume non-BMP characters
12433 		 * are always accepted as identifier characters.
12434 		 */
12435 		return 1;
12436 	}
12437 #endif
12438 }
12439 
12440 /*
12441  *  "IdentifierPart" production check.
12442  */
12443 
duk_unicode_is_identifier_part(duk_codepoint_t cp)12444 DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp) {
12445 	/*
12446 	 *  E5 Section 7.6:
12447 	 *
12448 	 *    IdentifierPart:
12449 	 *      IdentifierStart
12450 	 *      UnicodeCombiningMark
12451 	 *      UnicodeDigit
12452 	 *      UnicodeConnectorPunctuation
12453 	 *      <ZWNJ>  [U+200C]
12454 	 *      <ZWJ>   [U+200D]
12455 	 *
12456 	 *  IdentifierPart production has one multi-character production
12457 	 *  as part of its IdentifierStart alternative.  The '\' character
12458 	 *  of an escape sequence is not matched here, see discussion in
12459 	 *  duk_unicode_is_identifier_start().
12460 	 *
12461 	 *  To match non-ASCII characters (codepoints >= 0x80), a very slow
12462 	 *  linear range-by-range scan is used.  The codepoint is first compared
12463 	 *  to the IdentifierStart ranges, and if it doesn't match, then to a
12464 	 *  set consisting of code points in IdentifierPart but not in
12465 	 *  IdentifierStart.  This is done to keep the unicode range data small,
12466 	 *  at the expense of speed.
12467 	 *
12468 	 *  The ASCII fast path consists of:
12469 	 *
12470 	 *    0x0030 ... 0x0039     ['0' ... '9', UnicodeDigit]
12471 	 *    0x0041 ... 0x005a     ['A' ... 'Z', IdentifierStart]
12472 	 *    0x0061 ... 0x007a     ['a' ... 'z', IdentifierStart]
12473 	 *    0x0024                ['$', IdentifierStart]
12474 	 *    0x005f                ['_', IdentifierStart and
12475 	 *                                UnicodeConnectorPunctuation]
12476 	 *
12477 	 *  UnicodeCombiningMark has no code points <= 0x7f.
12478 	 *
12479 	 *  The matching code reuses the "identifier start" tables, and then
12480 	 *  consults a separate range set for characters in "identifier part"
12481 	 *  but not in "identifier start".  These can be extracted with the
12482 	 *  "tools/extract_chars.py" script.
12483 	 *
12484 	 *  UnicodeCombiningMark -> categories Mn, Mc
12485 	 *  UnicodeDigit -> categories Nd
12486 	 *  UnicodeConnectorPunctuation -> categories Pc
12487 	 */
12488 
12489 	/* ASCII (and EOF) fast path -- quick accept and reject */
12490 	if (cp <= 0x7fL) {
12491 #if defined(DUK_USE_IDCHAR_FASTPATH)
12492 		return (cp >= 0) && (duk_is_idchar_tab[cp] != 0);
12493 #else
12494 		if ((cp >= 'a' && cp <= 'z') ||
12495 		    (cp >= 'A' && cp <= 'Z') ||
12496 		    (cp >= '0' && cp <= '9') ||
12497 		    cp == '_' || cp == '$') {
12498 			return 1;
12499 		}
12500 		return 0;
12501 #endif
12502 	}
12503 
12504 	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
12505 
12506 #if defined(DUK_USE_SOURCE_NONBMP)
12507 	if (duk__uni_range_match(duk_unicode_ids_noa,
12508 	                         sizeof(duk_unicode_ids_noa),
12509 	                         (duk_codepoint_t) cp) ||
12510 	    duk__uni_range_match(duk_unicode_idp_m_ids_noa,
12511 	                         sizeof(duk_unicode_idp_m_ids_noa),
12512 	                         (duk_codepoint_t) cp)) {
12513 		return 1;
12514 	}
12515 	return 0;
12516 #else
12517 	if (cp < 0x10000L) {
12518 		if (duk__uni_range_match(duk_unicode_ids_noabmp,
12519 		                         sizeof(duk_unicode_ids_noabmp),
12520 		                         (duk_codepoint_t) cp) ||
12521 		    duk__uni_range_match(duk_unicode_idp_m_ids_noabmp,
12522 		                         sizeof(duk_unicode_idp_m_ids_noabmp),
12523 		                         (duk_codepoint_t) cp)) {
12524 			return 1;
12525 		}
12526 		return 0;
12527 	} else {
12528 		/* without explicit non-BMP support, assume non-BMP characters
12529 		 * are always accepted as identifier characters.
12530 		 */
12531 		return 1;
12532 	}
12533 #endif
12534 }
12535 
12536 /*
12537  *  Unicode letter check.
12538  */
12539 
duk_unicode_is_letter(duk_codepoint_t cp)12540 DUK_INTERNAL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp) {
12541 	/*
12542 	 *  Unicode letter is now taken to be the categories:
12543 	 *
12544 	 *    Lu, Ll, Lt, Lm, Lo
12545 	 *
12546 	 *  (Not sure if this is exactly correct.)
12547 	 *
12548 	 *  The ASCII fast path consists of:
12549 	 *
12550 	 *    0x0041 ... 0x005a     ['A' ... 'Z']
12551 	 *    0x0061 ... 0x007a     ['a' ... 'z']
12552 	 */
12553 
12554 	/* ASCII (and EOF) fast path -- quick accept and reject */
12555 	if (cp <= 0x7fL) {
12556 		if ((cp >= 'a' && cp <= 'z') ||
12557 		    (cp >= 'A' && cp <= 'Z')) {
12558 			return 1;
12559 		}
12560 		return 0;
12561 	}
12562 
12563 	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
12564 
12565 #if defined(DUK_USE_SOURCE_NONBMP)
12566 	if (duk__uni_range_match(duk_unicode_ids_noa,
12567 	                         sizeof(duk_unicode_ids_noa),
12568 	                         (duk_codepoint_t) cp) &&
12569 	    !duk__uni_range_match(duk_unicode_ids_m_let_noa,
12570 	                          sizeof(duk_unicode_ids_m_let_noa),
12571 	                          (duk_codepoint_t) cp)) {
12572 		return 1;
12573 	}
12574 	return 0;
12575 #else
12576 	if (cp < 0x10000L) {
12577 		if (duk__uni_range_match(duk_unicode_ids_noabmp,
12578 		                         sizeof(duk_unicode_ids_noabmp),
12579 		                         (duk_codepoint_t) cp) &&
12580 		    !duk__uni_range_match(duk_unicode_ids_m_let_noabmp,
12581 		                          sizeof(duk_unicode_ids_m_let_noabmp),
12582 		                          (duk_codepoint_t) cp)) {
12583 			return 1;
12584 		}
12585 		return 0;
12586 	} else {
12587 		/* without explicit non-BMP support, assume non-BMP characters
12588 		 * are always accepted as letters.
12589 		 */
12590 		return 1;
12591 	}
12592 #endif
12593 }
12594 
12595 /*
12596  *  Complex case conversion helper which decodes a bit-packed conversion
12597  *  control stream generated by tools/extract_caseconv.py.  The conversion
12598  *  is very slow because it runs through the conversion data in a linear
12599  *  fashion to save space (which is why ASCII characters have a special
12600  *  fast path before arriving here).
12601  *
12602  *  The particular bit counts etc have been determined experimentally to
12603  *  be small but still sufficient, and must match the Python script
12604  *  (tools/extract_caseconv.py).
12605  *
12606  *  The return value is the case converted codepoint or -1 if the conversion
12607  *  results in multiple characters (this is useful for regexp Canonicalization
12608  *  operation).  If 'buf' is not NULL, the result codepoint(s) are also
12609  *  appended to the hbuffer.
12610  *
12611  *  Context and locale specific rules must be checked before consulting
12612  *  this function.
12613  */
12614 
12615 DUK_LOCAL
duk__slow_case_conversion(duk_hthread * thr,duk_bufwriter_ctx * bw,duk_codepoint_t cp,duk_bitdecoder_ctx * bd_ctx)12616 duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr,
12617                                           duk_bufwriter_ctx *bw,
12618                                           duk_codepoint_t cp,
12619                                           duk_bitdecoder_ctx *bd_ctx) {
12620 	duk_small_int_t skip = 0;
12621 	duk_small_int_t n;
12622 	duk_small_int_t t;
12623 	duk_small_int_t count;
12624 	duk_codepoint_t tmp_cp;
12625 	duk_codepoint_t start_i;
12626 	duk_codepoint_t start_o;
12627 
12628 	DUK_ASSERT(bd_ctx != NULL);
12629 	DUK_UNREF(thr);
12630 
12631 	DUK_DDD(DUK_DDDPRINT("slow case conversion for codepoint: %ld", (long) cp));
12632 
12633 	/* range conversion with a "skip" */
12634 	DUK_DDD(DUK_DDDPRINT("checking ranges"));
12635 	for (;;) {
12636 		skip++;
12637 		n = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);
12638 		if (n == 0x3f) {
12639 			/* end marker */
12640 			break;
12641 		}
12642 		DUK_DDD(DUK_DDDPRINT("skip=%ld, n=%ld", (long) skip, (long) n));
12643 
12644 		while (n--) {
12645 			start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12646 			start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12647 			count = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
12648 			DUK_DDD(DUK_DDDPRINT("range: start_i=%ld, start_o=%ld, count=%ld, skip=%ld",
12649 			                     (long) start_i, (long) start_o, (long) count, (long) skip));
12650 
12651 			if (cp >= start_i) {
12652 				tmp_cp = cp - start_i;  /* always >= 0 */
12653 				if (tmp_cp < (duk_codepoint_t) count * (duk_codepoint_t) skip &&
12654 				    (tmp_cp % (duk_codepoint_t) skip) == 0) {
12655 					DUK_DDD(DUK_DDDPRINT("range matches input codepoint"));
12656 					cp = start_o + tmp_cp;
12657 					goto single;
12658 				}
12659 			}
12660 		}
12661 	}
12662 
12663 	/* 1:1 conversion */
12664 	n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
12665 	DUK_DDD(DUK_DDDPRINT("checking 1:1 conversions (count %ld)", (long) n));
12666 	while (n--) {
12667 		start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12668 		start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12669 		DUK_DDD(DUK_DDDPRINT("1:1 conversion %ld -> %ld", (long) start_i, (long) start_o));
12670 		if (cp == start_i) {
12671 			DUK_DDD(DUK_DDDPRINT("1:1 matches input codepoint"));
12672 			cp = start_o;
12673 			goto single;
12674 		}
12675 	}
12676 
12677 	/* complex, multicharacter conversion */
12678 	n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
12679 	DUK_DDD(DUK_DDDPRINT("checking 1:n conversions (count %ld)", (long) n));
12680 	while (n--) {
12681 		start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12682 		t = (duk_small_int_t) duk_bd_decode(bd_ctx, 2);
12683 		DUK_DDD(DUK_DDDPRINT("1:n conversion %ld -> %ld chars", (long) start_i, (long) t));
12684 		if (cp == start_i) {
12685 			DUK_DDD(DUK_DDDPRINT("1:n matches input codepoint"));
12686 			if (bw != NULL) {
12687 				while (t--) {
12688 					tmp_cp = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12689 					DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) tmp_cp);
12690 				}
12691 			}
12692 			return -1;
12693 		} else {
12694 			while (t--) {
12695 				(void) duk_bd_decode(bd_ctx, 16);
12696 			}
12697 		}
12698 	}
12699 
12700 	/* default: no change */
12701 	DUK_DDD(DUK_DDDPRINT("no rule matches, output is same as input"));
12702 	/* fall through */
12703 
12704  single:
12705 	if (bw != NULL) {
12706 		DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
12707 	}
12708 	return cp;
12709 }
12710 
12711 /*
12712  *  Case conversion helper, with context/local sensitivity.
12713  *  For proper case conversion, one needs to know the character
12714  *  and the preceding and following characters, as well as
12715  *  locale/language.
12716  */
12717 
12718 /* XXX: add 'language' argument when locale/language sensitive rule
12719  * support added.
12720  */
12721 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)12722 duk_codepoint_t duk__case_transform_helper(duk_hthread *thr,
12723                                            duk_bufwriter_ctx *bw,
12724                                            duk_codepoint_t cp,
12725                                            duk_codepoint_t prev,
12726                                            duk_codepoint_t next,
12727                                            duk_bool_t uppercase) {
12728 	duk_bitdecoder_ctx bd_ctx;
12729 
12730 	/* fast path for ASCII */
12731 	if (cp < 0x80L) {
12732 		/* XXX: there are language sensitive rules for the ASCII range.
12733 		 * If/when language/locale support is implemented, they need to
12734 		 * be implemented here for the fast path.  There are no context
12735 		 * sensitive rules for ASCII range.
12736 		 */
12737 
12738 		if (uppercase) {
12739 			if (cp >= 'a' && cp <= 'z') {
12740 				cp = cp - 'a' + 'A';
12741 			}
12742 		} else {
12743 			if (cp >= 'A' && cp <= 'Z') {
12744 				cp = cp - 'A' + 'a';
12745 			}
12746 		}
12747 
12748 		if (bw != NULL) {
12749 			DUK_BW_WRITE_RAW_U8(thr, bw, (duk_uint8_t) cp);
12750 		}
12751 		return cp;
12752 	}
12753 
12754 	/* context and locale specific rules which cannot currently be represented
12755 	 * in the caseconv bitstream: hardcoded rules in C
12756 	 */
12757 	if (uppercase) {
12758 		/* XXX: turkish / azeri */
12759 	} else {
12760 		/*
12761 		 *  Final sigma context specific rule.  This is a rather tricky
12762 		 *  rule and this handling is probably not 100% correct now.
12763 		 *  The rule is not locale/language specific so it is supported.
12764 		 */
12765 
12766 		if (cp == 0x03a3L &&    /* U+03A3 = GREEK CAPITAL LETTER SIGMA */
12767 		    duk_unicode_is_letter(prev) &&        /* prev exists and is not a letter */
12768 		    !duk_unicode_is_letter(next)) {       /* next does not exist or next is not a letter */
12769 			/* Capital sigma occurred at "end of word", lowercase to
12770 			 * U+03C2 = GREEK SMALL LETTER FINAL SIGMA.  Otherwise
12771 			 * fall through and let the normal rules lowercase it to
12772 			 * U+03C3 = GREEK SMALL LETTER SIGMA.
12773 			 */
12774 			cp = 0x03c2L;
12775 			goto singlechar;
12776 		}
12777 
12778 		/* XXX: lithuanian not implemented */
12779 		/* XXX: lithuanian, explicit dot rules */
12780 		/* XXX: turkish / azeri, lowercase rules */
12781 	}
12782 
12783 	/* 1:1 or special conversions, but not locale/context specific: script generated rules */
12784 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
12785 	if (uppercase) {
12786 		bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_uc;
12787 		bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_uc);
12788 	} else {
12789 		bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_lc;
12790 		bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_lc);
12791 	}
12792 	return duk__slow_case_conversion(thr, bw, cp, &bd_ctx);
12793 
12794  singlechar:
12795 	if (bw != NULL) {
12796 		DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
12797 	}
12798 	return cp;
12799 
12800  /* unused now, not needed until Turkish/Azeri */
12801 #if 0
12802  nochar:
12803 	return -1;
12804 #endif
12805 }
12806 
12807 /*
12808  *  Replace valstack top with case converted version.
12809  */
12810 
duk_unicode_case_convert_string(duk_hthread * thr,duk_bool_t uppercase)12811 DUK_INTERNAL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase) {
12812 	duk_hstring *h_input;
12813 	duk_bufwriter_ctx bw_alloc;
12814 	duk_bufwriter_ctx *bw;
12815 	const duk_uint8_t *p, *p_start, *p_end;
12816 	duk_codepoint_t prev, curr, next;
12817 
12818 	h_input = duk_require_hstring(thr, -1);  /* Accept symbols. */
12819 	DUK_ASSERT(h_input != NULL);
12820 
12821 	bw = &bw_alloc;
12822 	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));
12823 
12824 	/* [ ... input buffer ] */
12825 
12826 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
12827 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
12828 	p = p_start;
12829 
12830 	prev = -1; DUK_UNREF(prev);
12831 	curr = -1;
12832 	next = -1;
12833 	for (;;) {
12834 		prev = curr;
12835 		curr = next;
12836 		next = -1;
12837 		if (p < p_end) {
12838 			next = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
12839 		} else {
12840 			/* end of input and last char has been processed */
12841 			if (curr < 0) {
12842 				break;
12843 			}
12844 		}
12845 
12846 		/* on first round, skip */
12847 		if (curr >= 0) {
12848 			/* XXX: could add a fast path to process chunks of input codepoints,
12849 			 * but relative benefit would be quite small.
12850 			 */
12851 
12852 			/* Ensure space for maximum multi-character result; estimate is overkill. */
12853 			DUK_BW_ENSURE(thr, bw, 8 * DUK_UNICODE_MAX_XUTF8_LENGTH);
12854 
12855 			duk__case_transform_helper(thr,
12856 			                           bw,
12857 			                           (duk_codepoint_t) curr,
12858 			                           prev,
12859 			                           next,
12860 			                           uppercase);
12861 		}
12862 	}
12863 
12864 	DUK_BW_COMPACT(thr, bw);
12865 	(void) duk_buffer_to_string(thr, -1);  /* Safe, output is encoded. */
12866 	/* invalidates h_buf pointer */
12867 	duk_remove_m2(thr);
12868 }
12869 
12870 #if defined(DUK_USE_REGEXP_SUPPORT)
12871 
12872 /*
12873  *  Canonicalize() abstract operation needed for canonicalization of individual
12874  *  codepoints during regexp compilation and execution, see E5 Section 15.10.2.8.
12875  *  Note that codepoints are canonicalized one character at a time, so no context
12876  *  specific rules can apply.  Locale specific rules can apply, though.
12877  */
12878 
duk_unicode_re_canonicalize_char(duk_hthread * thr,duk_codepoint_t cp)12879 DUK_INTERNAL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp) {
12880 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
12881 	/* Fast canonicalization lookup at the cost of 128kB footprint. */
12882 	DUK_ASSERT(cp >= 0);
12883 	DUK_UNREF(thr);
12884 	if (DUK_LIKELY(cp < 0x10000L)) {
12885 		return (duk_codepoint_t) duk_unicode_re_canon_lookup[cp];
12886 	}
12887 	return cp;
12888 #else  /* DUK_USE_REGEXP_CANON_WORKAROUND */
12889 	duk_codepoint_t y;
12890 
12891 	y = duk__case_transform_helper(thr,
12892 	                               NULL,    /* NULL is allowed, no output */
12893 	                               cp,      /* curr char */
12894 	                               -1,      /* prev char */
12895 	                               -1,      /* next char */
12896 	                               1);      /* uppercase */
12897 
12898 	if ((y < 0) || (cp >= 0x80 && y < 0x80)) {
12899 		/* multiple codepoint conversion or non-ASCII mapped to ASCII
12900 		 * --> leave as is.
12901 		 */
12902 		return cp;
12903 	}
12904 
12905 	return y;
12906 #endif  /* DUK_USE_REGEXP_CANON_WORKAROUND */
12907 }
12908 
12909 /*
12910  *  E5 Section 15.10.2.6 "IsWordChar" abstract operation.  Assume
12911  *  x < 0 for characters read outside the string.
12912  */
12913 
duk_unicode_re_is_wordchar(duk_codepoint_t x)12914 DUK_INTERNAL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t x) {
12915 	/*
12916 	 *  Note: the description in E5 Section 15.10.2.6 has a typo, it
12917 	 *  contains 'A' twice and lacks 'a'; the intent is [0-9a-zA-Z_].
12918 	 */
12919 	if ((x >= '0' && x <= '9') ||
12920 	    (x >= 'a' && x <= 'z') ||
12921 	    (x >= 'A' && x <= 'Z') ||
12922 	    (x == '_')) {
12923 		return 1;
12924 	}
12925 	return 0;
12926 }
12927 
12928 /*
12929  *  Regexp range tables
12930  */
12931 
12932 /* exposed because lexer needs these too */
12933 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_digit[2] = {
12934 	(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
12935 };
12936 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_white[22] = {
12937 	(duk_uint16_t) 0x0009UL, (duk_uint16_t) 0x000DUL,
12938 	(duk_uint16_t) 0x0020UL, (duk_uint16_t) 0x0020UL,
12939 	(duk_uint16_t) 0x00A0UL, (duk_uint16_t) 0x00A0UL,
12940 	(duk_uint16_t) 0x1680UL, (duk_uint16_t) 0x1680UL,
12941 	(duk_uint16_t) 0x180EUL, (duk_uint16_t) 0x180EUL,
12942 	(duk_uint16_t) 0x2000UL, (duk_uint16_t) 0x200AUL,
12943 	(duk_uint16_t) 0x2028UL, (duk_uint16_t) 0x2029UL,
12944 	(duk_uint16_t) 0x202FUL, (duk_uint16_t) 0x202FUL,
12945 	(duk_uint16_t) 0x205FUL, (duk_uint16_t) 0x205FUL,
12946 	(duk_uint16_t) 0x3000UL, (duk_uint16_t) 0x3000UL,
12947 	(duk_uint16_t) 0xFEFFUL, (duk_uint16_t) 0xFEFFUL,
12948 };
12949 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_wordchar[8] = {
12950 	(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
12951 	(duk_uint16_t) 0x0041UL, (duk_uint16_t) 0x005AUL,
12952 	(duk_uint16_t) 0x005FUL, (duk_uint16_t) 0x005FUL,
12953 	(duk_uint16_t) 0x0061UL, (duk_uint16_t) 0x007AUL,
12954 };
12955 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_digit[4] = {
12956 	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
12957 	(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0xFFFFUL,
12958 };
12959 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_white[24] = {
12960 	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x0008UL,
12961 	(duk_uint16_t) 0x000EUL, (duk_uint16_t) 0x001FUL,
12962 	(duk_uint16_t) 0x0021UL, (duk_uint16_t) 0x009FUL,
12963 	(duk_uint16_t) 0x00A1UL, (duk_uint16_t) 0x167FUL,
12964 	(duk_uint16_t) 0x1681UL, (duk_uint16_t) 0x180DUL,
12965 	(duk_uint16_t) 0x180FUL, (duk_uint16_t) 0x1FFFUL,
12966 	(duk_uint16_t) 0x200BUL, (duk_uint16_t) 0x2027UL,
12967 	(duk_uint16_t) 0x202AUL, (duk_uint16_t) 0x202EUL,
12968 	(duk_uint16_t) 0x2030UL, (duk_uint16_t) 0x205EUL,
12969 	(duk_uint16_t) 0x2060UL, (duk_uint16_t) 0x2FFFUL,
12970 	(duk_uint16_t) 0x3001UL, (duk_uint16_t) 0xFEFEUL,
12971 	(duk_uint16_t) 0xFF00UL, (duk_uint16_t) 0xFFFFUL,
12972 };
12973 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = {
12974 	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
12975 	(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0x0040UL,
12976 	(duk_uint16_t) 0x005BUL, (duk_uint16_t) 0x005EUL,
12977 	(duk_uint16_t) 0x0060UL, (duk_uint16_t) 0x0060UL,
12978 	(duk_uint16_t) 0x007BUL, (duk_uint16_t) 0xFFFFUL,
12979 };
12980 
12981 #endif  /* DUK_USE_REGEXP_SUPPORT */
12982 /*
12983  *  Misc util stuff.
12984  */
12985 
12986 /* #include duk_internal.h -> already included */
12987 
12988 /*
12989  *  Lowercase digits for radix values 2 to 36.  Also doubles as lowercase
12990  *  hex nybble table.
12991  */
12992 
12993 DUK_INTERNAL const duk_uint8_t duk_lc_digits[36] = {
12994 	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
12995 	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
12996 	DUK_ASC_8, DUK_ASC_9, DUK_ASC_LC_A, DUK_ASC_LC_B,
12997 	DUK_ASC_LC_C, DUK_ASC_LC_D, DUK_ASC_LC_E, DUK_ASC_LC_F,
12998 	DUK_ASC_LC_G, DUK_ASC_LC_H, DUK_ASC_LC_I, DUK_ASC_LC_J,
12999 	DUK_ASC_LC_K, DUK_ASC_LC_L, DUK_ASC_LC_M, DUK_ASC_LC_N,
13000 	DUK_ASC_LC_O, DUK_ASC_LC_P, DUK_ASC_LC_Q, DUK_ASC_LC_R,
13001 	DUK_ASC_LC_S, DUK_ASC_LC_T, DUK_ASC_LC_U, DUK_ASC_LC_V,
13002 	DUK_ASC_LC_W, DUK_ASC_LC_X, DUK_ASC_LC_Y, DUK_ASC_LC_Z
13003 };
13004 
13005 DUK_INTERNAL const duk_uint8_t duk_uc_nybbles[16] = {
13006 	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
13007 	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
13008 	DUK_ASC_8, DUK_ASC_9, DUK_ASC_UC_A, DUK_ASC_UC_B,
13009 	DUK_ASC_UC_C, DUK_ASC_UC_D, DUK_ASC_UC_E, DUK_ASC_UC_F
13010 };
13011 
13012 /*
13013  *  Table for hex decoding ASCII hex digits
13014  */
13015 
13016 DUK_INTERNAL const duk_int8_t duk_hex_dectab[256] = {
13017 	/* -1 if invalid */
13018 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x00-0x0f */
13019 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x10-0x1f */
13020 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x20-0x2f */
13021 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,  /* 0x30-0x3f */
13022 	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x40-0x4f */
13023 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x50-0x5f */
13024 	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x60-0x6f */
13025 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x70-0x7f */
13026 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x80-0x8f */
13027 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x90-0x9f */
13028 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xa0-0xaf */
13029 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xb0-0xbf */
13030 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xc0-0xcf */
13031 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xd0-0xdf */
13032 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xe0-0xef */
13033 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1   /* 0xf0-0xff */
13034 };
13035 
13036 #if defined(DUK_USE_HEX_FASTPATH)
13037 /* Preshifted << 4.  Must use 16-bit entry to allow negative value signaling. */
13038 DUK_INTERNAL const duk_int16_t duk_hex_dectab_shift4[256] = {
13039 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x00-0x0f */
13040 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x10-0x1f */
13041 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x20-0x2f */
13042 	0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x30-0x3f */
13043 	  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x40-0x4f */
13044 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x50-0x5f */
13045 	  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x60-0x6f */
13046 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x70-0x7f */
13047 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x80-0x8f */
13048 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x90-0x9f */
13049 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xa0-0xaf */
13050 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xb0-0xbf */
13051 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xc0-0xcf */
13052 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xd0-0xdf */
13053 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xe0-0xef */
13054 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1   /* 0xf0-0xff */
13055 };
13056 #endif
13057 
13058 /*
13059  *  Table for hex encoding bytes
13060  */
13061 
13062 #if defined(DUK_USE_HEX_FASTPATH)
13063 /* Lookup to encode one byte directly into 2 characters:
13064  *
13065  *   def genhextab(bswap):
13066  *       for i in xrange(256):
13067  *           t = chr(i).encode('hex')
13068  *           if bswap:
13069  *               t = t[1] + t[0]
13070  *           print('0x' + t.encode('hex') + 'U')
13071  *   print('big endian'); genhextab(False)
13072  *   print('little endian'); genhextab(True)
13073 */
13074 DUK_INTERNAL const duk_uint16_t duk_hex_enctab[256] = {
13075 #if defined(DUK_USE_INTEGER_BE)
13076 	0x3030U, 0x3031U, 0x3032U, 0x3033U, 0x3034U, 0x3035U, 0x3036U, 0x3037U,
13077 	0x3038U, 0x3039U, 0x3061U, 0x3062U, 0x3063U, 0x3064U, 0x3065U, 0x3066U,
13078 	0x3130U, 0x3131U, 0x3132U, 0x3133U, 0x3134U, 0x3135U, 0x3136U, 0x3137U,
13079 	0x3138U, 0x3139U, 0x3161U, 0x3162U, 0x3163U, 0x3164U, 0x3165U, 0x3166U,
13080 	0x3230U, 0x3231U, 0x3232U, 0x3233U, 0x3234U, 0x3235U, 0x3236U, 0x3237U,
13081 	0x3238U, 0x3239U, 0x3261U, 0x3262U, 0x3263U, 0x3264U, 0x3265U, 0x3266U,
13082 	0x3330U, 0x3331U, 0x3332U, 0x3333U, 0x3334U, 0x3335U, 0x3336U, 0x3337U,
13083 	0x3338U, 0x3339U, 0x3361U, 0x3362U, 0x3363U, 0x3364U, 0x3365U, 0x3366U,
13084 	0x3430U, 0x3431U, 0x3432U, 0x3433U, 0x3434U, 0x3435U, 0x3436U, 0x3437U,
13085 	0x3438U, 0x3439U, 0x3461U, 0x3462U, 0x3463U, 0x3464U, 0x3465U, 0x3466U,
13086 	0x3530U, 0x3531U, 0x3532U, 0x3533U, 0x3534U, 0x3535U, 0x3536U, 0x3537U,
13087 	0x3538U, 0x3539U, 0x3561U, 0x3562U, 0x3563U, 0x3564U, 0x3565U, 0x3566U,
13088 	0x3630U, 0x3631U, 0x3632U, 0x3633U, 0x3634U, 0x3635U, 0x3636U, 0x3637U,
13089 	0x3638U, 0x3639U, 0x3661U, 0x3662U, 0x3663U, 0x3664U, 0x3665U, 0x3666U,
13090 	0x3730U, 0x3731U, 0x3732U, 0x3733U, 0x3734U, 0x3735U, 0x3736U, 0x3737U,
13091 	0x3738U, 0x3739U, 0x3761U, 0x3762U, 0x3763U, 0x3764U, 0x3765U, 0x3766U,
13092 	0x3830U, 0x3831U, 0x3832U, 0x3833U, 0x3834U, 0x3835U, 0x3836U, 0x3837U,
13093 	0x3838U, 0x3839U, 0x3861U, 0x3862U, 0x3863U, 0x3864U, 0x3865U, 0x3866U,
13094 	0x3930U, 0x3931U, 0x3932U, 0x3933U, 0x3934U, 0x3935U, 0x3936U, 0x3937U,
13095 	0x3938U, 0x3939U, 0x3961U, 0x3962U, 0x3963U, 0x3964U, 0x3965U, 0x3966U,
13096 	0x6130U, 0x6131U, 0x6132U, 0x6133U, 0x6134U, 0x6135U, 0x6136U, 0x6137U,
13097 	0x6138U, 0x6139U, 0x6161U, 0x6162U, 0x6163U, 0x6164U, 0x6165U, 0x6166U,
13098 	0x6230U, 0x6231U, 0x6232U, 0x6233U, 0x6234U, 0x6235U, 0x6236U, 0x6237U,
13099 	0x6238U, 0x6239U, 0x6261U, 0x6262U, 0x6263U, 0x6264U, 0x6265U, 0x6266U,
13100 	0x6330U, 0x6331U, 0x6332U, 0x6333U, 0x6334U, 0x6335U, 0x6336U, 0x6337U,
13101 	0x6338U, 0x6339U, 0x6361U, 0x6362U, 0x6363U, 0x6364U, 0x6365U, 0x6366U,
13102 	0x6430U, 0x6431U, 0x6432U, 0x6433U, 0x6434U, 0x6435U, 0x6436U, 0x6437U,
13103 	0x6438U, 0x6439U, 0x6461U, 0x6462U, 0x6463U, 0x6464U, 0x6465U, 0x6466U,
13104 	0x6530U, 0x6531U, 0x6532U, 0x6533U, 0x6534U, 0x6535U, 0x6536U, 0x6537U,
13105 	0x6538U, 0x6539U, 0x6561U, 0x6562U, 0x6563U, 0x6564U, 0x6565U, 0x6566U,
13106 	0x6630U, 0x6631U, 0x6632U, 0x6633U, 0x6634U, 0x6635U, 0x6636U, 0x6637U,
13107 	0x6638U, 0x6639U, 0x6661U, 0x6662U, 0x6663U, 0x6664U, 0x6665U, 0x6666U
13108 #else  /* DUK_USE_INTEGER_BE */
13109 	0x3030U, 0x3130U, 0x3230U, 0x3330U, 0x3430U, 0x3530U, 0x3630U, 0x3730U,
13110 	0x3830U, 0x3930U, 0x6130U, 0x6230U, 0x6330U, 0x6430U, 0x6530U, 0x6630U,
13111 	0x3031U, 0x3131U, 0x3231U, 0x3331U, 0x3431U, 0x3531U, 0x3631U, 0x3731U,
13112 	0x3831U, 0x3931U, 0x6131U, 0x6231U, 0x6331U, 0x6431U, 0x6531U, 0x6631U,
13113 	0x3032U, 0x3132U, 0x3232U, 0x3332U, 0x3432U, 0x3532U, 0x3632U, 0x3732U,
13114 	0x3832U, 0x3932U, 0x6132U, 0x6232U, 0x6332U, 0x6432U, 0x6532U, 0x6632U,
13115 	0x3033U, 0x3133U, 0x3233U, 0x3333U, 0x3433U, 0x3533U, 0x3633U, 0x3733U,
13116 	0x3833U, 0x3933U, 0x6133U, 0x6233U, 0x6333U, 0x6433U, 0x6533U, 0x6633U,
13117 	0x3034U, 0x3134U, 0x3234U, 0x3334U, 0x3434U, 0x3534U, 0x3634U, 0x3734U,
13118 	0x3834U, 0x3934U, 0x6134U, 0x6234U, 0x6334U, 0x6434U, 0x6534U, 0x6634U,
13119 	0x3035U, 0x3135U, 0x3235U, 0x3335U, 0x3435U, 0x3535U, 0x3635U, 0x3735U,
13120 	0x3835U, 0x3935U, 0x6135U, 0x6235U, 0x6335U, 0x6435U, 0x6535U, 0x6635U,
13121 	0x3036U, 0x3136U, 0x3236U, 0x3336U, 0x3436U, 0x3536U, 0x3636U, 0x3736U,
13122 	0x3836U, 0x3936U, 0x6136U, 0x6236U, 0x6336U, 0x6436U, 0x6536U, 0x6636U,
13123 	0x3037U, 0x3137U, 0x3237U, 0x3337U, 0x3437U, 0x3537U, 0x3637U, 0x3737U,
13124 	0x3837U, 0x3937U, 0x6137U, 0x6237U, 0x6337U, 0x6437U, 0x6537U, 0x6637U,
13125 	0x3038U, 0x3138U, 0x3238U, 0x3338U, 0x3438U, 0x3538U, 0x3638U, 0x3738U,
13126 	0x3838U, 0x3938U, 0x6138U, 0x6238U, 0x6338U, 0x6438U, 0x6538U, 0x6638U,
13127 	0x3039U, 0x3139U, 0x3239U, 0x3339U, 0x3439U, 0x3539U, 0x3639U, 0x3739U,
13128 	0x3839U, 0x3939U, 0x6139U, 0x6239U, 0x6339U, 0x6439U, 0x6539U, 0x6639U,
13129 	0x3061U, 0x3161U, 0x3261U, 0x3361U, 0x3461U, 0x3561U, 0x3661U, 0x3761U,
13130 	0x3861U, 0x3961U, 0x6161U, 0x6261U, 0x6361U, 0x6461U, 0x6561U, 0x6661U,
13131 	0x3062U, 0x3162U, 0x3262U, 0x3362U, 0x3462U, 0x3562U, 0x3662U, 0x3762U,
13132 	0x3862U, 0x3962U, 0x6162U, 0x6262U, 0x6362U, 0x6462U, 0x6562U, 0x6662U,
13133 	0x3063U, 0x3163U, 0x3263U, 0x3363U, 0x3463U, 0x3563U, 0x3663U, 0x3763U,
13134 	0x3863U, 0x3963U, 0x6163U, 0x6263U, 0x6363U, 0x6463U, 0x6563U, 0x6663U,
13135 	0x3064U, 0x3164U, 0x3264U, 0x3364U, 0x3464U, 0x3564U, 0x3664U, 0x3764U,
13136 	0x3864U, 0x3964U, 0x6164U, 0x6264U, 0x6364U, 0x6464U, 0x6564U, 0x6664U,
13137 	0x3065U, 0x3165U, 0x3265U, 0x3365U, 0x3465U, 0x3565U, 0x3665U, 0x3765U,
13138 	0x3865U, 0x3965U, 0x6165U, 0x6265U, 0x6365U, 0x6465U, 0x6565U, 0x6665U,
13139 	0x3066U, 0x3166U, 0x3266U, 0x3366U, 0x3466U, 0x3566U, 0x3666U, 0x3766U,
13140 	0x3866U, 0x3966U, 0x6166U, 0x6266U, 0x6366U, 0x6466U, 0x6566U, 0x6666U
13141 #endif  /* DUK_USE_INTEGER_BE */
13142 };
13143 #endif  /* DUK_USE_HEX_FASTPATH */
13144 
13145 /*
13146  *  Arbitrary byteswap for potentially unaligned values
13147  *
13148  *  Used to byteswap pointers e.g. in debugger code.
13149  */
13150 
13151 #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)13152 DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) {
13153 	duk_uint8_t tmp;
13154 	duk_uint8_t *q = p + len - 1;
13155 
13156 	while (p - q < 0) {
13157 		tmp = *p;
13158 		*p = *q;
13159 		*q = tmp;
13160 		p++;
13161 		q--;
13162 	}
13163 }
13164 #endif
13165 /*
13166  *  Hobject ECMAScript [[Class]].
13167  */
13168 
13169 /* #include duk_internal.h -> already included */
13170 
13171 #if (DUK_STRIDX_UC_ARGUMENTS > 255)
13172 #error constant too large
13173 #endif
13174 #if (DUK_STRIDX_ARRAY > 255)
13175 #error constant too large
13176 #endif
13177 #if (DUK_STRIDX_UC_BOOLEAN > 255)
13178 #error constant too large
13179 #endif
13180 #if (DUK_STRIDX_DATE > 255)
13181 #error constant too large
13182 #endif
13183 #if (DUK_STRIDX_UC_ERROR > 255)
13184 #error constant too large
13185 #endif
13186 #if (DUK_STRIDX_UC_FUNCTION > 255)
13187 #error constant too large
13188 #endif
13189 #if (DUK_STRIDX_JSON > 255)
13190 #error constant too large
13191 #endif
13192 #if (DUK_STRIDX_MATH > 255)
13193 #error constant too large
13194 #endif
13195 #if (DUK_STRIDX_UC_NUMBER > 255)
13196 #error constant too large
13197 #endif
13198 #if (DUK_STRIDX_UC_OBJECT > 255)
13199 #error constant too large
13200 #endif
13201 #if (DUK_STRIDX_REG_EXP > 255)
13202 #error constant too large
13203 #endif
13204 #if (DUK_STRIDX_UC_STRING > 255)
13205 #error constant too large
13206 #endif
13207 #if (DUK_STRIDX_GLOBAL > 255)
13208 #error constant too large
13209 #endif
13210 #if (DUK_STRIDX_OBJ_ENV > 255)
13211 #error constant too large
13212 #endif
13213 #if (DUK_STRIDX_DEC_ENV > 255)
13214 #error constant too large
13215 #endif
13216 #if (DUK_STRIDX_UC_POINTER > 255)
13217 #error constant too large
13218 #endif
13219 #if (DUK_STRIDX_UC_THREAD > 255)
13220 #error constant too large
13221 #endif
13222 #if (DUK_STRIDX_ARRAY_BUFFER > 255)
13223 #error constant too large
13224 #endif
13225 #if (DUK_STRIDX_DATA_VIEW > 255)
13226 #error constant too large
13227 #endif
13228 #if (DUK_STRIDX_INT8_ARRAY > 255)
13229 #error constant too large
13230 #endif
13231 #if (DUK_STRIDX_UINT8_ARRAY > 255)
13232 #error constant too large
13233 #endif
13234 #if (DUK_STRIDX_UINT8_CLAMPED_ARRAY > 255)
13235 #error constant too large
13236 #endif
13237 #if (DUK_STRIDX_INT16_ARRAY > 255)
13238 #error constant too large
13239 #endif
13240 #if (DUK_STRIDX_UINT16_ARRAY > 255)
13241 #error constant too large
13242 #endif
13243 #if (DUK_STRIDX_INT32_ARRAY > 255)
13244 #error constant too large
13245 #endif
13246 #if (DUK_STRIDX_UINT32_ARRAY > 255)
13247 #error constant too large
13248 #endif
13249 #if (DUK_STRIDX_FLOAT32_ARRAY > 255)
13250 #error constant too large
13251 #endif
13252 #if (DUK_STRIDX_FLOAT64_ARRAY > 255)
13253 #error constant too large
13254 #endif
13255 #if (DUK_STRIDX_EMPTY_STRING > 255)
13256 #error constant too large
13257 #endif
13258 
13259 /* Note: assumes that these string indexes are 8-bit, genstrings.py must ensure that */
13260 DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32] = {
13261 	DUK_STRIDX_EMPTY_STRING,  /* NONE, intentionally empty */
13262 	DUK_STRIDX_UC_OBJECT,
13263 	DUK_STRIDX_ARRAY,
13264 	DUK_STRIDX_UC_FUNCTION,
13265 	DUK_STRIDX_UC_ARGUMENTS,
13266 	DUK_STRIDX_UC_BOOLEAN,
13267 	DUK_STRIDX_DATE,
13268 	DUK_STRIDX_UC_ERROR,
13269 	DUK_STRIDX_JSON,
13270 	DUK_STRIDX_MATH,
13271 	DUK_STRIDX_UC_NUMBER,
13272 	DUK_STRIDX_REG_EXP,
13273 	DUK_STRIDX_UC_STRING,
13274 	DUK_STRIDX_GLOBAL,
13275 	DUK_STRIDX_UC_SYMBOL,
13276 	DUK_STRIDX_OBJ_ENV,
13277 	DUK_STRIDX_DEC_ENV,
13278 	DUK_STRIDX_UC_POINTER,
13279 	DUK_STRIDX_UC_THREAD,
13280 	DUK_STRIDX_ARRAY_BUFFER,
13281 	DUK_STRIDX_DATA_VIEW,
13282 	DUK_STRIDX_INT8_ARRAY,
13283 	DUK_STRIDX_UINT8_ARRAY,
13284 	DUK_STRIDX_UINT8_CLAMPED_ARRAY,
13285 	DUK_STRIDX_INT16_ARRAY,
13286 	DUK_STRIDX_UINT16_ARRAY,
13287 	DUK_STRIDX_INT32_ARRAY,
13288 	DUK_STRIDX_UINT32_ARRAY,
13289 	DUK_STRIDX_FLOAT32_ARRAY,
13290 	DUK_STRIDX_FLOAT64_ARRAY,
13291 	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
13292 	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
13293 };
13294 /*
13295  *  Default allocation functions.
13296  *
13297  *  Assumes behavior such as malloc allowing zero size, yielding
13298  *  a NULL or a unique pointer which is a no-op for free.
13299  */
13300 
13301 /* #include duk_internal.h -> already included */
13302 
13303 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
duk_default_alloc_function(void * udata,duk_size_t size)13304 DUK_INTERNAL void *duk_default_alloc_function(void *udata, duk_size_t size) {
13305 	void *res;
13306 	DUK_UNREF(udata);
13307 	res = DUK_ANSI_MALLOC(size);
13308 	DUK_DDD(DUK_DDDPRINT("default alloc function: %lu -> %p",
13309 	                     (unsigned long) size, (void *) res));
13310 	return res;
13311 }
13312 
duk_default_realloc_function(void * udata,void * ptr,duk_size_t newsize)13313 DUK_INTERNAL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize) {
13314 	void *res;
13315 	DUK_UNREF(udata);
13316 	res = DUK_ANSI_REALLOC(ptr, newsize);
13317 	DUK_DDD(DUK_DDDPRINT("default realloc function: %p %lu -> %p",
13318 	                     (void *) ptr, (unsigned long) newsize, (void *) res));
13319 	return res;
13320 }
13321 
duk_default_free_function(void * udata,void * ptr)13322 DUK_INTERNAL void duk_default_free_function(void *udata, void *ptr) {
13323 	DUK_DDD(DUK_DDDPRINT("default free function: %p", (void *) ptr));
13324 	DUK_UNREF(udata);
13325 	DUK_ANSI_FREE(ptr);
13326 }
13327 #endif  /* DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS */
13328 /*
13329  *  Buffer
13330  */
13331 
13332 /* #include duk_internal.h -> already included */
13333 
duk_resize_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t new_size)13334 DUK_EXTERNAL void *duk_resize_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t new_size) {
13335 	duk_hbuffer_dynamic *h;
13336 
13337 	DUK_ASSERT_API_ENTRY(thr);
13338 
13339 	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(thr, idx);
13340 	DUK_ASSERT(h != NULL);
13341 
13342 	if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
13343 		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
13344 		DUK_WO_NORETURN(return NULL;);
13345 	}
13346 
13347 	/* Maximum size check is handled by callee. */
13348 	duk_hbuffer_resize(thr, h, new_size);
13349 
13350 	return DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
13351 }
13352 
duk_steal_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)13353 DUK_EXTERNAL void *duk_steal_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
13354 	duk_hbuffer_dynamic *h;
13355 	void *ptr;
13356 	duk_size_t sz;
13357 
13358 	DUK_ASSERT_API_ENTRY(thr);
13359 
13360 	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(thr, idx);
13361 	DUK_ASSERT(h != NULL);
13362 
13363 	if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
13364 		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
13365 		DUK_WO_NORETURN(return NULL;);
13366 	}
13367 
13368 	/* Forget the previous allocation, setting size to 0 and alloc to
13369 	 * NULL.  Caller is responsible for freeing the previous allocation.
13370 	 * Getting the allocation and clearing it is done in the same API
13371 	 * call to avoid any chance of a realloc.
13372 	 */
13373 	ptr = DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
13374 	sz = DUK_HBUFFER_DYNAMIC_GET_SIZE(h);
13375 	if (out_size) {
13376 		*out_size = sz;
13377 	}
13378 	DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(thr->heap, h);
13379 	DUK_HBUFFER_DYNAMIC_SET_SIZE(h, 0);
13380 
13381 	return ptr;
13382 }
13383 
duk_config_buffer(duk_hthread * thr,duk_idx_t idx,void * ptr,duk_size_t len)13384 DUK_EXTERNAL void duk_config_buffer(duk_hthread *thr, duk_idx_t idx, void *ptr, duk_size_t len) {
13385 	duk_hbuffer_external *h;
13386 
13387 	DUK_ASSERT_API_ENTRY(thr);
13388 
13389 	h = (duk_hbuffer_external *) duk_require_hbuffer(thr, idx);
13390 	DUK_ASSERT(h != NULL);
13391 
13392 	if (!DUK_HBUFFER_HAS_EXTERNAL(h)) {
13393 		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
13394 		DUK_WO_NORETURN(return;);
13395 	}
13396 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h));
13397 
13398 	DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(thr->heap, h, ptr);
13399 	DUK_HBUFFER_EXTERNAL_SET_SIZE(h, len);
13400 }
13401 /*
13402  *  Bytecode dump/load
13403  *
13404  *  The bytecode load primitive is more important performance-wise than the
13405  *  dump primitive.
13406  *
13407  *  Unlike most Duktape API calls, bytecode dump/load is not guaranteed to be
13408  *  memory safe for invalid arguments - caller beware!  There's little point
13409  *  in trying to achieve memory safety unless bytecode instructions are also
13410  *  validated which is not easy to do with indirect register references etc.
13411  */
13412 
13413 /* #include duk_internal.h -> already included */
13414 
13415 #if defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
13416 
13417 #define DUK__SER_MARKER  0xbf
13418 #define DUK__SER_STRING  0x00
13419 #define DUK__SER_NUMBER  0x01
13420 #define DUK__BYTECODE_INITIAL_ALLOC 256
13421 #define DUK__NO_FORMALS  0xffffffffUL
13422 
13423 /*
13424  *  Dump/load helpers, xxx_raw() helpers do no buffer checks
13425  */
13426 
duk__load_string_raw(duk_hthread * thr,duk_uint8_t * p)13427 DUK_LOCAL duk_uint8_t *duk__load_string_raw(duk_hthread *thr, duk_uint8_t *p) {
13428 	duk_uint32_t len;
13429 
13430 	len = DUK_RAW_READ_U32_BE(p);
13431 	duk_push_lstring(thr, (const char *) p, len);
13432 	p += len;
13433 	return p;
13434 }
13435 
duk__load_buffer_raw(duk_hthread * thr,duk_uint8_t * p)13436 DUK_LOCAL duk_uint8_t *duk__load_buffer_raw(duk_hthread *thr, duk_uint8_t *p) {
13437 	duk_uint32_t len;
13438 	duk_uint8_t *buf;
13439 
13440 	len = DUK_RAW_READ_U32_BE(p);
13441 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len);
13442 	DUK_ASSERT(buf != NULL);
13443 	duk_memcpy((void *) buf, (const void *) p, (size_t) len);
13444 	p += len;
13445 	return p;
13446 }
13447 
duk__dump_hstring_raw(duk_uint8_t * p,duk_hstring * h)13448 DUK_LOCAL duk_uint8_t *duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h) {
13449 	duk_size_t len;
13450 	duk_uint32_t tmp32;
13451 
13452 	DUK_ASSERT(h != NULL);
13453 
13454 	len = DUK_HSTRING_GET_BYTELEN(h);
13455 	DUK_ASSERT(len <= 0xffffffffUL);  /* string limits */
13456 	tmp32 = (duk_uint32_t) len;
13457 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13458 	duk_memcpy((void *) p,
13459 	           (const void *) DUK_HSTRING_GET_DATA(h),
13460 	           len);
13461 	p += len;
13462 	return p;
13463 }
13464 
duk__dump_hbuffer_raw(duk_hthread * thr,duk_uint8_t * p,duk_hbuffer * h)13465 DUK_LOCAL duk_uint8_t *duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, duk_hbuffer *h) {
13466 	duk_size_t len;
13467 	duk_uint32_t tmp32;
13468 
13469 	DUK_ASSERT(thr != NULL);
13470 	DUK_ASSERT(h != NULL);
13471 	DUK_UNREF(thr);
13472 
13473 	len = DUK_HBUFFER_GET_SIZE(h);
13474 	DUK_ASSERT(len <= 0xffffffffUL);  /* buffer limits */
13475 	tmp32 = (duk_uint32_t) len;
13476 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13477 	/* When len == 0, buffer data pointer may be NULL. */
13478 	duk_memcpy_unsafe((void *) p,
13479 	                  (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),
13480 	                  len);
13481 	p += len;
13482 	return p;
13483 }
13484 
duk__dump_string_prop(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func,duk_small_uint_t stridx)13485 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) {
13486 	duk_hstring *h_str;
13487 	duk_tval *tv;
13488 
13489 	tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
13490 	if (tv != NULL && DUK_TVAL_IS_STRING(tv)) {
13491 		h_str = DUK_TVAL_GET_STRING(tv);
13492 		DUK_ASSERT(h_str != NULL);
13493 	} else {
13494 		h_str = DUK_HTHREAD_STRING_EMPTY_STRING(thr);
13495 		DUK_ASSERT(h_str != NULL);
13496 	}
13497 	DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13498 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(h_str), p);
13499 	p = duk__dump_hstring_raw(p, h_str);
13500 	return p;
13501 }
13502 
duk__dump_buffer_prop(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func,duk_small_uint_t stridx)13503 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) {
13504 	duk_tval *tv;
13505 
13506 	tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
13507 	if (tv != NULL && DUK_TVAL_IS_BUFFER(tv)) {
13508 		duk_hbuffer *h_buf;
13509 		h_buf = DUK_TVAL_GET_BUFFER(tv);
13510 		DUK_ASSERT(h_buf != NULL);
13511 		DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13512 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HBUFFER_GET_SIZE(h_buf), p);
13513 		p = duk__dump_hbuffer_raw(thr, p, h_buf);
13514 	} else {
13515 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13516 		DUK_RAW_WRITE_U32_BE(p, 0);
13517 	}
13518 	return p;
13519 }
13520 
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)13521 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) {
13522 	duk_tval *tv;
13523 	duk_uint32_t val;
13524 
13525 	tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
13526 	if (tv != NULL && DUK_TVAL_IS_NUMBER(tv)) {
13527 		val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
13528 	} else {
13529 		val = def_value;
13530 	}
13531 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13532 	DUK_RAW_WRITE_U32_BE(p, val);
13533 	return p;
13534 }
13535 
duk__dump_varmap(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func)13536 DUK_LOCAL duk_uint8_t *duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
13537 	duk_hobject *h;
13538 
13539 	h = duk_hobject_get_varmap(thr, (duk_hobject *) func);
13540 	if (h != NULL) {
13541 		duk_uint_fast32_t i;
13542 
13543 		/* We know _Varmap only has own properties so walk property
13544 		 * table directly.  We also know _Varmap is dense and all
13545 		 * values are numbers; assert for these.  GC and finalizers
13546 		 * shouldn't affect _Varmap so side effects should be fine.
13547 		 */
13548 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
13549 			duk_hstring *key;
13550 			duk_tval *tv_val;
13551 			duk_uint32_t val;
13552 
13553 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
13554 			DUK_ASSERT(key != NULL);  /* _Varmap is dense */
13555 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i));
13556 			tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i);
13557 			DUK_ASSERT(tv_val != NULL);
13558 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_val));  /* known to be number; in fact an integer */
13559 #if defined(DUK_USE_FASTINT)
13560 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_val));
13561 			DUK_ASSERT(DUK_TVAL_GET_FASTINT(tv_val) == (duk_int64_t) DUK_TVAL_GET_FASTINT_U32(tv_val));  /* known to be 32-bit */
13562 			val = DUK_TVAL_GET_FASTINT_U32(tv_val);
13563 #else
13564 			val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv_val);
13565 #endif
13566 
13567 			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13568 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(key) + 4U, p);
13569 			p = duk__dump_hstring_raw(p, key);
13570 			DUK_RAW_WRITE_U32_BE(p, val);
13571 		}
13572 	}
13573 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13574 	DUK_RAW_WRITE_U32_BE(p, 0);  /* end of _Varmap */
13575 	return p;
13576 }
13577 
duk__dump_formals(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func)13578 DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
13579 	duk_harray *h;
13580 
13581 	h = duk_hobject_get_formals(thr, (duk_hobject *) func);
13582 	if (h != NULL) {
13583 		duk_uint32_t i;
13584 
13585 		/* Here we rely on _Formals being a dense array containing
13586 		 * strings.  This should be the case unless _Formals has been
13587 		 * tweaked by the application (which we don't support right
13588 		 * now).
13589 		 */
13590 
13591 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13592 		DUK_ASSERT(h->length != DUK__NO_FORMALS);  /* limits */
13593 		DUK_RAW_WRITE_U32_BE(p, h->length);
13594 
13595 		for (i = 0; i < h->length; i++) {
13596 			duk_tval *tv_val;
13597 			duk_hstring *varname;
13598 
13599 			tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, (duk_hobject *) h, i);
13600 			DUK_ASSERT(tv_val != NULL);
13601 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv_val));
13602 
13603 			varname = DUK_TVAL_GET_STRING(tv_val);
13604 			DUK_ASSERT(varname != NULL);
13605 			DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(varname) >= 1);
13606 
13607 			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13608 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(varname), p);
13609 			p = duk__dump_hstring_raw(p, varname);
13610 		}
13611 	} else {
13612 		DUK_DD(DUK_DDPRINT("dumping function without _Formals, emit marker to indicate missing _Formals"));
13613 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13614 		DUK_RAW_WRITE_U32_BE(p, DUK__NO_FORMALS);  /* marker: no formals */
13615 	}
13616 	return p;
13617 }
13618 
duk__dump_func(duk_hthread * thr,duk_hcompfunc * func,duk_bufwriter_ctx * bw_ctx,duk_uint8_t * p)13619 static duk_uint8_t *duk__dump_func(duk_hthread *thr, duk_hcompfunc *func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p) {
13620 	duk_tval *tv, *tv_end;
13621 	duk_instr_t *ins, *ins_end;
13622 	duk_hobject **fn, **fn_end;
13623 	duk_hstring *h_str;
13624 	duk_uint32_t count_instr;
13625 	duk_uint32_t tmp32;
13626 	duk_uint16_t tmp16;
13627 	duk_double_t d;
13628 
13629 	DUK_DD(DUK_DDPRINT("dumping function %p to %p: "
13630 	                   "consts=[%p,%p[ (%ld bytes, %ld items), "
13631 	                   "funcs=[%p,%p[ (%ld bytes, %ld items), "
13632 	                   "code=[%p,%p[ (%ld bytes, %ld items)",
13633 	                   (void *) func,
13634 	                   (void *) p,
13635 	                   (void *) DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, func),
13636 	                   (void *) DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func),
13637 	                   (long) DUK_HCOMPFUNC_GET_CONSTS_SIZE(thr->heap, func),
13638 	                   (long) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func),
13639 	                   (void *) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, func),
13640 	                   (void *) DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, func),
13641 	                   (long) DUK_HCOMPFUNC_GET_FUNCS_SIZE(thr->heap, func),
13642 	                   (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func),
13643 	                   (void *) DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, func),
13644 	                   (void *) DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func),
13645 	                   (long) DUK_HCOMPFUNC_GET_CODE_SIZE(thr->heap, func),
13646 	                   (long) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func)));
13647 
13648 	DUK_ASSERT(DUK_USE_ESBC_MAX_BYTES <= 0x7fffffffUL);  /* ensures no overflow */
13649 	count_instr = (duk_uint32_t) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func);
13650 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 3U * 4U + 2U * 2U + 3U * 4U + count_instr * 4U, p);
13651 
13652 	/* Fixed header info. */
13653 	tmp32 = count_instr;
13654 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13655 	tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func);
13656 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13657 	tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func);
13658 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13659 	tmp16 = func->nregs;
13660 	DUK_RAW_WRITE_U16_BE(p, tmp16);
13661 	tmp16 = func->nargs;
13662 	DUK_RAW_WRITE_U16_BE(p, tmp16);
13663 #if defined(DUK_USE_DEBUGGER_SUPPORT)
13664 	tmp32 = func->start_line;
13665 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13666 	tmp32 = func->end_line;
13667 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13668 #else
13669 	DUK_RAW_WRITE_U32_BE(p, 0);
13670 	DUK_RAW_WRITE_U32_BE(p, 0);
13671 #endif
13672 	tmp32 = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) func);  /* masks flags, only duk_hobject flags */
13673 	tmp32 &= ~(DUK_HOBJECT_FLAG_HAVE_FINALIZER);  /* finalizer flag is lost */
13674 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13675 
13676 	/* Bytecode instructions: endian conversion needed unless
13677 	 * platform is big endian.
13678 	 */
13679 	ins = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, func);
13680 	ins_end = DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func);
13681 	DUK_ASSERT((duk_size_t) (ins_end - ins) == (duk_size_t) count_instr);
13682 #if defined(DUK_USE_INTEGER_BE)
13683 	duk_memcpy_unsafe((void *) p, (const void *) ins, (size_t) (ins_end - ins));
13684 	p += (size_t) (ins_end - ins);
13685 #else
13686 	while (ins != ins_end) {
13687 		tmp32 = (duk_uint32_t) (*ins);
13688 		DUK_RAW_WRITE_U32_BE(p, tmp32);
13689 		ins++;
13690 	}
13691 #endif
13692 
13693 	/* Constants: variable size encoding. */
13694 	tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, func);
13695 	tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func);
13696 	while (tv != tv_end) {
13697 		/* constants are strings or numbers now */
13698 		DUK_ASSERT(DUK_TVAL_IS_STRING(tv) ||
13699 		           DUK_TVAL_IS_NUMBER(tv));
13700 
13701 		if (DUK_TVAL_IS_STRING(tv)) {
13702 			h_str = DUK_TVAL_GET_STRING(tv);
13703 			DUK_ASSERT(h_str != NULL);
13704 			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13705 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 4U + DUK_HSTRING_GET_BYTELEN(h_str), p);
13706 			*p++ = DUK__SER_STRING;
13707 			p = duk__dump_hstring_raw(p, h_str);
13708 		} else {
13709 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
13710 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 8U, p);
13711 			*p++ = DUK__SER_NUMBER;
13712 			d = DUK_TVAL_GET_NUMBER(tv);
13713 			DUK_RAW_WRITE_DOUBLE_BE(p, d);
13714 		}
13715 		tv++;
13716 	}
13717 
13718 	/* Inner functions recursively. */
13719 	fn = (duk_hobject **) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, func);
13720 	fn_end = (duk_hobject **) DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, func);
13721 	while (fn != fn_end) {
13722 		/* XXX: This causes recursion up to inner function depth
13723 		 * which is normally not an issue, e.g. mark-and-sweep uses
13724 		 * a recursion limiter to avoid C stack issues.  Avoiding
13725 		 * this would mean some sort of a work list or just refusing
13726 		 * to serialize deep functions.
13727 		 */
13728 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(*fn));
13729 		p = duk__dump_func(thr, (duk_hcompfunc *) *fn, bw_ctx, p);
13730 		fn++;
13731 	}
13732 
13733 	/* Lexenv and varenv are not dumped. */
13734 
13735 	/* Object extra properties.
13736 	 *
13737 	 * There are some difference between function templates and functions.
13738 	 * For example, function templates don't have .length and nargs is
13739 	 * normally used to instantiate the functions.
13740 	 */
13741 
13742 	p = duk__dump_uint32_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_LENGTH, (duk_uint32_t) func->nargs);
13743 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
13744 	p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_NAME);
13745 #endif
13746 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
13747 	p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_FILE_NAME);
13748 #endif
13749 #if defined(DUK_USE_PC2LINE)
13750 	p = duk__dump_buffer_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_INT_PC2LINE);
13751 #endif
13752 	p = duk__dump_varmap(thr, p, bw_ctx, (duk_hobject *) func);
13753 	p = duk__dump_formals(thr, p, bw_ctx, (duk_hobject *) func);
13754 
13755 	DUK_DD(DUK_DDPRINT("serialized function %p -> final pointer %p", (void *) func, (void *) p));
13756 
13757 	return p;
13758 }
13759 
13760 /* Load a function from bytecode.  The function object returned here must
13761  * match what is created by duk_js_push_closure() with respect to its flags,
13762  * properties, etc.
13763  *
13764  * NOTE: there are intentionally no input buffer length / bound checks.
13765  * Adding them would be easy but wouldn't ensure memory safety as untrusted
13766  * or broken bytecode is unsafe during execution unless the opcodes themselves
13767  * are validated (which is quite complex, especially for indirect opcodes).
13768  */
13769 
13770 #define DUK__ASSERT_LEFT(n) do { \
13771 		DUK_ASSERT((duk_size_t) (p_end - p) >= (duk_size_t) (n)); \
13772 	} while (0)
13773 
duk__load_func(duk_hthread * thr,duk_uint8_t * p,duk_uint8_t * p_end)13774 static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t *p_end) {
13775 	duk_hcompfunc *h_fun;
13776 	duk_hbuffer *h_data;
13777 	duk_size_t data_size;
13778 	duk_uint32_t count_instr, count_const, count_funcs;
13779 	duk_uint32_t n;
13780 	duk_uint32_t tmp32;
13781 	duk_small_uint_t const_type;
13782 	duk_uint8_t *fun_data;
13783 	duk_uint8_t *q;
13784 	duk_idx_t idx_base;
13785 	duk_tval *tv1;
13786 	duk_uarridx_t arr_idx;
13787 	duk_uarridx_t arr_limit;
13788 	duk_hobject *func_env;
13789 	duk_bool_t need_pop;
13790 
13791 	/* XXX: There's some overlap with duk_js_closure() here, but
13792 	 * seems difficult to share code.  Ensure that the final function
13793 	 * looks the same as created by duk_js_closure().
13794 	 */
13795 
13796 	DUK_ASSERT(thr != NULL);
13797 
13798 	DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (void *) p, (void *) p_end));
13799 
13800 	DUK__ASSERT_LEFT(3 * 4);
13801 	count_instr = DUK_RAW_READ_U32_BE(p);
13802 	count_const = DUK_RAW_READ_U32_BE(p);
13803 	count_funcs = DUK_RAW_READ_U32_BE(p);
13804 
13805 	data_size = sizeof(duk_tval) * count_const +
13806 	            sizeof(duk_hobject *) * count_funcs +
13807 	            sizeof(duk_instr_t) * count_instr;
13808 
13809 	DUK_DD(DUK_DDPRINT("instr=%ld, const=%ld, funcs=%ld, data_size=%ld",
13810 	                   (long) count_instr, (long) count_const,
13811 	                   (long) count_const, (long) data_size));
13812 
13813 	/* Value stack is used to ensure reachability of constants and
13814 	 * inner functions being loaded.  Require enough space to handle
13815 	 * large functions correctly.
13816 	 */
13817 	duk_require_stack(thr, (duk_idx_t) (2 + count_const + count_funcs));
13818 	idx_base = duk_get_top(thr);
13819 
13820 	/* Push function object, init flags etc.  This must match
13821 	 * duk_js_push_closure() quite carefully.
13822 	 */
13823 	h_fun = duk_push_hcompfunc(thr);
13824 	DUK_ASSERT(h_fun != NULL);
13825 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) h_fun));
13826 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, h_fun) == NULL);
13827 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, h_fun) == NULL);
13828 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, h_fun) == NULL);
13829 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_fun) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
13830 
13831 	h_fun->nregs = DUK_RAW_READ_U16_BE(p);
13832 	h_fun->nargs = DUK_RAW_READ_U16_BE(p);
13833 #if defined(DUK_USE_DEBUGGER_SUPPORT)
13834 	h_fun->start_line = DUK_RAW_READ_U32_BE(p);
13835 	h_fun->end_line = DUK_RAW_READ_U32_BE(p);
13836 #else
13837 	p += 8;  /* skip line info */
13838 #endif
13839 
13840 	/* duk_hcompfunc flags; quite version specific */
13841 	tmp32 = DUK_RAW_READ_U32_BE(p);
13842 	DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32);  /* masks flags to only change duk_hobject flags */
13843 
13844 	/* standard prototype (no need to set here, already set) */
13845 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_fun) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
13846 #if 0
13847 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &h_fun->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
13848 #endif
13849 
13850 	/* assert just a few critical flags */
13851 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h_fun) == DUK_HTYPE_OBJECT);
13852 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&h_fun->obj));
13853 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&h_fun->obj));
13854 	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&h_fun->obj));
13855 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(&h_fun->obj));
13856 	DUK_ASSERT(!DUK_HOBJECT_IS_PROXY(&h_fun->obj));
13857 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&h_fun->obj));
13858 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&h_fun->obj));
13859 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&h_fun->obj));
13860 
13861 	/* Create function 'data' buffer but don't attach it yet. */
13862 	fun_data = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, data_size);
13863 	DUK_ASSERT(fun_data != NULL);
13864 
13865 	/* Load bytecode instructions. */
13866 	DUK_ASSERT(sizeof(duk_instr_t) == 4);
13867 	DUK__ASSERT_LEFT(count_instr * sizeof(duk_instr_t));
13868 #if defined(DUK_USE_INTEGER_BE)
13869 	q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
13870 	duk_memcpy((void *) q,
13871 	           (const void *) p,
13872 	           sizeof(duk_instr_t) * count_instr);
13873 	p += sizeof(duk_instr_t) * count_instr;
13874 #else
13875 	q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
13876 	for (n = count_instr; n > 0; n--) {
13877 		*((duk_instr_t *) (void *) q) = DUK_RAW_READ_U32_BE(p);
13878 		q += sizeof(duk_instr_t);
13879 	}
13880 #endif
13881 
13882 	/* Load constants onto value stack but don't yet copy to buffer. */
13883 	for (n = count_const; n > 0; n--) {
13884 		DUK__ASSERT_LEFT(1);
13885 		const_type = DUK_RAW_READ_U8(p);
13886 		switch (const_type) {
13887 		case DUK__SER_STRING: {
13888 			p = duk__load_string_raw(thr, p);
13889 			break;
13890 		}
13891 		case DUK__SER_NUMBER: {
13892 			/* Important to do a fastint check so that constants are
13893 			 * properly read back as fastints.
13894 			 */
13895 			duk_tval tv_tmp;
13896 			duk_double_t val;
13897 			DUK__ASSERT_LEFT(8);
13898 			val = DUK_RAW_READ_DOUBLE_BE(p);
13899 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(&tv_tmp, val);
13900 			duk_push_tval(thr, &tv_tmp);
13901 			break;
13902 		}
13903 		default: {
13904 			goto format_error;
13905 		}
13906 		}
13907 	}
13908 
13909 	/* Load inner functions to value stack, but don't yet copy to buffer. */
13910 	for (n = count_funcs; n > 0; n--) {
13911 		p = duk__load_func(thr, p, p_end);
13912 		if (p == NULL) {
13913 			goto format_error;
13914 		}
13915 	}
13916 
13917 	/* With constants and inner functions on value stack, we can now
13918 	 * atomically finish the function 'data' buffer, bump refcounts,
13919 	 * etc.
13920 	 *
13921 	 * Here we take advantage of the value stack being just a duk_tval
13922 	 * array: we can just memcpy() the constants as long as we incref
13923 	 * them afterwards.
13924 	 */
13925 
13926 	h_data = (duk_hbuffer *) duk_known_hbuffer(thr, idx_base + 1);
13927 	DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC(h_data));
13928 	DUK_HCOMPFUNC_SET_DATA(thr->heap, h_fun, h_data);
13929 	DUK_HBUFFER_INCREF(thr, h_data);
13930 
13931 	tv1 = duk_get_tval(thr, idx_base + 2);  /* may be NULL if no constants or inner funcs */
13932 	DUK_ASSERT((count_const == 0 && count_funcs == 0) || tv1 != NULL);
13933 
13934 	q = fun_data;
13935 	duk_memcpy_unsafe((void *) q, (const void *) tv1, sizeof(duk_tval) * count_const);
13936 	for (n = count_const; n > 0; n--) {
13937 		DUK_TVAL_INCREF_FAST(thr, (duk_tval *) (void *) q);  /* no side effects */
13938 		q += sizeof(duk_tval);
13939 	}
13940 	tv1 += count_const;
13941 
13942 	DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_fun, (duk_hobject **) (void *) q);
13943 	for (n = count_funcs; n > 0; n--) {
13944 		duk_hobject *h_obj;
13945 
13946 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
13947 		h_obj = DUK_TVAL_GET_OBJECT(tv1);
13948 		DUK_ASSERT(h_obj != NULL);
13949 		tv1++;
13950 		DUK_HOBJECT_INCREF(thr, h_obj);
13951 
13952 		*((duk_hobject **) (void *) q) = h_obj;
13953 		q += sizeof(duk_hobject *);
13954 	}
13955 
13956 	DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, h_fun, (duk_instr_t *) (void *) q);
13957 
13958 	/* The function object is now reachable and refcounts are fine,
13959 	 * so we can pop off all the temporaries.
13960 	 */
13961 	DUK_DDD(DUK_DDDPRINT("function is reachable, reset top; func: %!iT", duk_get_tval(thr, idx_base)));
13962 	duk_set_top(thr, idx_base + 1);
13963 
13964 	/* Setup function properties. */
13965 	tmp32 = DUK_RAW_READ_U32_BE(p);
13966 	duk_push_u32(thr, tmp32);
13967 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
13968 
13969 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
13970 	p = duk__load_string_raw(thr, p);  /* -> [ func funcname ] */
13971 	func_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
13972 	DUK_ASSERT(func_env != NULL);
13973 	need_pop = 0;
13974 	if (DUK_HOBJECT_HAS_NAMEBINDING((duk_hobject *) h_fun)) {
13975 		/* Original function instance/template had NAMEBINDING.
13976 		 * Must create a lexical environment on loading to allow
13977 		 * recursive functions like 'function foo() { foo(); }'.
13978 		 */
13979 		duk_hdecenv *new_env;
13980 
13981 		new_env = duk_hdecenv_alloc(thr,
13982 		                            DUK_HOBJECT_FLAG_EXTENSIBLE |
13983 		                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
13984 		DUK_ASSERT(new_env != NULL);
13985 		DUK_ASSERT(new_env->thread == NULL);  /* Closed. */
13986 		DUK_ASSERT(new_env->varmap == NULL);
13987 		DUK_ASSERT(new_env->regbase_byteoff == 0);
13988 		DUK_HDECENV_ASSERT_VALID(new_env);
13989 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
13990 		DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, func_env);
13991 		DUK_HOBJECT_INCREF(thr, func_env);
13992 
13993 		func_env = (duk_hobject *) new_env;
13994 
13995 		duk_push_hobject(thr, (duk_hobject *) new_env);
13996 
13997 		duk_dup_m2(thr);                                  /* -> [ func funcname env funcname ] */
13998 		duk_dup(thr, idx_base);                           /* -> [ func funcname env funcname func ] */
13999 		duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE);  /* -> [ func funcname env ] */
14000 
14001 		need_pop = 1;  /* Need to pop env, but -after- updating h_fun and increfs. */
14002 	}
14003 	DUK_ASSERT(func_env != NULL);
14004 	DUK_HCOMPFUNC_SET_LEXENV(thr->heap, h_fun, func_env);
14005 	DUK_HCOMPFUNC_SET_VARENV(thr->heap, h_fun, func_env);
14006 	DUK_HOBJECT_INCREF(thr, func_env);
14007 	DUK_HOBJECT_INCREF(thr, func_env);
14008 	if (need_pop) {
14009 		duk_pop(thr);
14010 	}
14011 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
14012 #endif  /* DUK_USE_FUNC_NAME_PROPERTY */
14013 
14014 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
14015 	p = duk__load_string_raw(thr, p);
14016 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C);
14017 #endif  /* DUK_USE_FUNC_FILENAME_PROPERTY */
14018 
14019 	if (DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_fun)) {
14020 		/* Restore empty external .prototype only for constructable
14021 		 * functions.  The prototype object should inherit from
14022 		 * Object.prototype.
14023 		 */
14024 		duk_push_object(thr);
14025 		DUK_ASSERT(!duk_is_bare_object(thr, -1));
14026 		duk_dup_m2(thr);
14027 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* func.prototype.constructor = func */
14028 		duk_compact_m1(thr);
14029 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);
14030 	}
14031 
14032 #if defined(DUK_USE_PC2LINE)
14033 	p = duk__load_buffer_raw(thr, p);
14034 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_WC);
14035 #endif  /* DUK_USE_PC2LINE */
14036 
14037 	duk_push_bare_object(thr);  /* _Varmap */
14038 	for (;;) {
14039 		/* XXX: awkward */
14040 		p = duk__load_string_raw(thr, p);
14041 		if (duk_get_length(thr, -1) == 0) {
14042 			duk_pop(thr);
14043 			break;
14044 		}
14045 		tmp32 = DUK_RAW_READ_U32_BE(p);
14046 		duk_push_u32(thr, tmp32);
14047 		duk_put_prop(thr, -3);
14048 	}
14049 	duk_compact_m1(thr);
14050 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
14051 
14052 	/* _Formals may have been missing in the original function, which is
14053 	 * handled using a marker length.
14054 	 */
14055 	arr_limit = DUK_RAW_READ_U32_BE(p);
14056 	if (arr_limit != DUK__NO_FORMALS) {
14057 		duk_push_bare_array(thr);  /* _Formals */
14058 		for (arr_idx = 0; arr_idx < arr_limit; arr_idx++) {
14059 			p = duk__load_string_raw(thr, p);
14060 			duk_put_prop_index(thr, -2, arr_idx);
14061 		}
14062 		duk_compact_m1(thr);
14063 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
14064 	} else {
14065 		DUK_DD(DUK_DDPRINT("no _Formals in dumped function"));
14066 	}
14067 
14068 	/* Return with final function pushed on stack top. */
14069 	DUK_DD(DUK_DDPRINT("final loaded function: %!iT", duk_get_tval(thr, -1)));
14070 	DUK_ASSERT_TOP(thr, idx_base + 1);
14071 	return p;
14072 
14073  format_error:
14074 	return NULL;
14075 }
14076 
duk_dump_function(duk_hthread * thr)14077 DUK_EXTERNAL void duk_dump_function(duk_hthread *thr) {
14078 	duk_hcompfunc *func;
14079 	duk_bufwriter_ctx bw_ctx_alloc;
14080 	duk_bufwriter_ctx *bw_ctx = &bw_ctx_alloc;
14081 	duk_uint8_t *p;
14082 
14083 	DUK_ASSERT_API_ENTRY(thr);
14084 
14085 	/* Bound functions don't have all properties so we'd either need to
14086 	 * lookup the non-bound target function or reject bound functions.
14087 	 * For now, bound functions are rejected with TypeError.
14088 	 */
14089 	func = duk_require_hcompfunc(thr, -1);
14090 	DUK_ASSERT(func != NULL);
14091 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&func->obj));
14092 
14093 	/* Estimating the result size beforehand would be costly, so
14094 	 * start with a reasonable size and extend as needed.
14095 	 */
14096 	DUK_BW_INIT_PUSHBUF(thr, bw_ctx, DUK__BYTECODE_INITIAL_ALLOC);
14097 	p = DUK_BW_GET_PTR(thr, bw_ctx);
14098 	*p++ = DUK__SER_MARKER;
14099 	p = duk__dump_func(thr, func, bw_ctx, p);
14100 	DUK_BW_SET_PTR(thr, bw_ctx, p);
14101 	DUK_BW_COMPACT(thr, bw_ctx);
14102 
14103 	DUK_DD(DUK_DDPRINT("serialized result: %!T", duk_get_tval(thr, -1)));
14104 
14105 	duk_remove_m2(thr);  /* [ ... func buf ] -> [ ... buf ] */
14106 }
14107 
duk_load_function(duk_hthread * thr)14108 DUK_EXTERNAL void duk_load_function(duk_hthread *thr) {
14109 	duk_uint8_t *p_buf, *p, *p_end;
14110 	duk_size_t sz;
14111 
14112 	DUK_ASSERT_API_ENTRY(thr);
14113 
14114 	p_buf = (duk_uint8_t *) duk_require_buffer(thr, -1, &sz);
14115 	DUK_ASSERT(p_buf != NULL);
14116 
14117 	/* The caller is responsible for being sure that bytecode being loaded
14118 	 * is valid and trusted.  Invalid bytecode can cause memory unsafe
14119 	 * behavior directly during loading or later during bytecode execution
14120 	 * (instruction validation would be quite complex to implement).
14121 	 *
14122 	 * This signature check is the only sanity check for detecting
14123 	 * accidental invalid inputs.  The initial byte ensures no ordinary
14124 	 * string or Symbol will be accepted by accident.
14125 	 */
14126 	p = p_buf;
14127 	p_end = p_buf + sz;
14128 	if (sz < 1 || p[0] != DUK__SER_MARKER) {
14129 		goto format_error;
14130 	}
14131 	p++;
14132 
14133 	p = duk__load_func(thr, p, p_end);
14134 	if (p == NULL) {
14135 		goto format_error;
14136 	}
14137 
14138 	duk_remove_m2(thr);  /* [ ... buf func ] -> [ ... func ] */
14139 	return;
14140 
14141  format_error:
14142 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BYTECODE);
14143 	DUK_WO_NORETURN(return;);
14144 }
14145 
14146 #else  /* DUK_USE_BYTECODE_DUMP_SUPPORT */
14147 
duk_dump_function(duk_hthread * thr)14148 DUK_EXTERNAL void duk_dump_function(duk_hthread *thr) {
14149 	DUK_ASSERT_API_ENTRY(thr);
14150 	DUK_ERROR_UNSUPPORTED(thr);
14151 	DUK_WO_NORETURN(return;);
14152 }
14153 
duk_load_function(duk_hthread * thr)14154 DUK_EXTERNAL void duk_load_function(duk_hthread *thr) {
14155 	DUK_ASSERT_API_ENTRY(thr);
14156 	DUK_ERROR_UNSUPPORTED(thr);
14157 	DUK_WO_NORETURN(return;);
14158 }
14159 
14160 #endif  /* DUK_USE_BYTECODE_DUMP_SUPPORT */
14161 
14162 /* automatic undefs */
14163 #undef DUK__ASSERT_LEFT
14164 #undef DUK__BYTECODE_INITIAL_ALLOC
14165 #undef DUK__NO_FORMALS
14166 #undef DUK__SER_MARKER
14167 #undef DUK__SER_NUMBER
14168 #undef DUK__SER_STRING
14169 /*
14170  *  Calls.
14171  *
14172  *  Protected variants should avoid ever throwing an error.  Must be careful
14173  *  to catch errors related to value stack manipulation and property lookup,
14174  *  not just the call itself.
14175  *
14176  *  The only exception is when arguments are insane, e.g. nargs/nrets are out
14177  *  of bounds; in such cases an error is thrown for two reasons.  First, we
14178  *  can't always respect the value stack input/output guarantees in such cases
14179  *  so the caller would end up with the value stack in an unexpected state.
14180  *  Second, an attempt to create an error might itself fail (although this
14181  *  could be avoided by pushing a preallocated object/string or a primitive
14182  *  value).
14183  */
14184 
14185 /* #include duk_internal.h -> already included */
14186 
14187 /*
14188  *  Helpers
14189  */
14190 
14191 struct duk__pcall_prop_args {
14192 	duk_idx_t obj_idx;
14193 	duk_idx_t nargs;
14194 	duk_small_uint_t call_flags;
14195 };
14196 typedef struct duk__pcall_prop_args duk__pcall_prop_args;
14197 
14198 struct duk__pcall_method_args {
14199 	duk_idx_t nargs;
14200 	duk_small_uint_t call_flags;
14201 };
14202 typedef struct duk__pcall_method_args duk__pcall_method_args;
14203 
14204 struct duk__pcall_args {
14205 	duk_idx_t nargs;
14206 	duk_small_uint_t call_flags;
14207 };
14208 typedef struct duk__pcall_args duk__pcall_args;
14209 
14210 /* Compute and validate idx_func for a certain 'nargs' and 'other'
14211  * parameter count (1 or 2, depending on whether 'this' binding is
14212  * present).
14213  */
duk__call_get_idx_func(duk_hthread * thr,duk_idx_t nargs,duk_idx_t other)14214 DUK_LOCAL duk_idx_t duk__call_get_idx_func(duk_hthread *thr, duk_idx_t nargs, duk_idx_t other) {
14215 	duk_idx_t idx_func;
14216 
14217 	/* XXX: byte arithmetic? */
14218 
14219 	DUK_ASSERT(other >= 0);
14220 
14221 	idx_func = duk_get_top(thr) - nargs - other;
14222 	if (DUK_UNLIKELY((idx_func | nargs) < 0)) {  /* idx_func < 0 || nargs < 0; OR sign bits */
14223 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14224 		DUK_WO_NORETURN(return 0;);
14225 	}
14226 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14227 	return idx_func;
14228 }
14229 
14230 /* Compute idx_func, assume index will be valid.  This is a valid assumption
14231  * for protected calls: nargs < 0 is checked explicitly and duk_safe_call()
14232  * validates the argument count.
14233  */
duk__call_get_idx_func_unvalidated(duk_hthread * thr,duk_idx_t nargs,duk_idx_t other)14234 DUK_LOCAL duk_idx_t duk__call_get_idx_func_unvalidated(duk_hthread *thr, duk_idx_t nargs, duk_idx_t other) {
14235 	duk_idx_t idx_func;
14236 
14237 	/* XXX: byte arithmetic? */
14238 
14239 	DUK_ASSERT(nargs >= 0);
14240 	DUK_ASSERT(other >= 0);
14241 
14242 	idx_func = duk_get_top(thr) - nargs - other;
14243 	DUK_ASSERT(idx_func >= 0);
14244 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14245 	return idx_func;
14246 }
14247 
14248 /* Prepare value stack for a method call through an object property.
14249  * May currently throw an error e.g. when getting the property.
14250  */
duk__call_prop_prep_stack(duk_hthread * thr,duk_idx_t normalized_obj_idx,duk_idx_t nargs)14251 DUK_LOCAL void duk__call_prop_prep_stack(duk_hthread *thr, duk_idx_t normalized_obj_idx, duk_idx_t nargs) {
14252 	DUK_CTX_ASSERT_VALID(thr);
14253 	DUK_ASSERT(nargs >= 0);
14254 
14255 	DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_idx=%ld, nargs=%ld, stacktop=%ld",
14256 	                     (long) normalized_obj_idx, (long) nargs, (long) duk_get_top(thr)));
14257 
14258 	/* [... key arg1 ... argN] */
14259 
14260 	/* duplicate key */
14261 	duk_dup(thr, -nargs - 1);  /* Note: -nargs alone would fail for nargs == 0, this is OK */
14262 	(void) duk_get_prop(thr, normalized_obj_idx);
14263 
14264 	DUK_DDD(DUK_DDDPRINT("func: %!T", (duk_tval *) duk_get_tval(thr, -1)));
14265 
14266 #if defined(DUK_USE_VERBOSE_ERRORS)
14267 	if (DUK_UNLIKELY(!duk_is_callable(thr, -1))) {
14268 		duk_tval *tv_base;
14269 		duk_tval *tv_key;
14270 
14271 		/* tv_targ is passed on stack top (at index -1). */
14272 		tv_base = DUK_GET_TVAL_POSIDX(thr, normalized_obj_idx);
14273 		tv_key = DUK_GET_TVAL_NEGIDX(thr, -nargs - 2);
14274 		DUK_ASSERT(tv_base >= thr->valstack_bottom && tv_base < thr->valstack_top);
14275 		DUK_ASSERT(tv_key >= thr->valstack_bottom && tv_key < thr->valstack_top);
14276 
14277 		duk_call_setup_propcall_error(thr, tv_base, tv_key);
14278 	}
14279 #endif
14280 
14281 	/* [... key arg1 ... argN func] */
14282 
14283 	duk_replace(thr, -nargs - 2);
14284 
14285 	/* [... func arg1 ... argN] */
14286 
14287 	duk_dup(thr, normalized_obj_idx);
14288 	duk_insert(thr, -nargs - 1);
14289 
14290 	/* [... func this arg1 ... argN] */
14291 }
14292 
duk_call(duk_hthread * thr,duk_idx_t nargs)14293 DUK_EXTERNAL void duk_call(duk_hthread *thr, duk_idx_t nargs) {
14294 	duk_small_uint_t call_flags;
14295 	duk_idx_t idx_func;
14296 
14297 	DUK_ASSERT_API_ENTRY(thr);
14298 
14299 	idx_func = duk__call_get_idx_func(thr, nargs, 1);
14300 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14301 
14302 	duk_insert_undefined(thr, idx_func + 1);
14303 
14304 	call_flags = 0;  /* not protected, respect reclimit, not constructor */
14305 	duk_handle_call_unprotected(thr, idx_func, call_flags);
14306 }
14307 
duk_call_method(duk_hthread * thr,duk_idx_t nargs)14308 DUK_EXTERNAL void duk_call_method(duk_hthread *thr, duk_idx_t nargs) {
14309 	duk_small_uint_t call_flags;
14310 	duk_idx_t idx_func;
14311 
14312 	DUK_ASSERT_API_ENTRY(thr);
14313 
14314 	idx_func = duk__call_get_idx_func(thr, nargs, 2);
14315 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14316 
14317 	call_flags = 0;  /* not protected, respect reclimit, not constructor */
14318 	duk_handle_call_unprotected(thr, idx_func, call_flags);
14319 }
14320 
duk_call_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_idx_t nargs)14321 DUK_EXTERNAL void duk_call_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t nargs) {
14322 	/*
14323 	 *  XXX: if duk_handle_call() took values through indices, this could be
14324 	 *  made much more sensible.  However, duk_handle_call() needs to fudge
14325 	 *  the 'this' and 'func' values to handle bound functions, which is now
14326 	 *  done "in-place", so this is not a trivial change.
14327 	 */
14328 
14329 	DUK_ASSERT_API_ENTRY(thr);
14330 
14331 	obj_idx = duk_require_normalize_index(thr, obj_idx);  /* make absolute */
14332 	if (DUK_UNLIKELY(nargs < 0)) {
14333 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14334 		DUK_WO_NORETURN(return;);
14335 	}
14336 
14337 	duk__call_prop_prep_stack(thr, obj_idx, nargs);
14338 
14339 	duk_call_method(thr, nargs);
14340 }
14341 
duk__pcall_raw(duk_hthread * thr,void * udata)14342 DUK_LOCAL duk_ret_t duk__pcall_raw(duk_hthread *thr, void *udata) {
14343 	duk__pcall_args *args;
14344 	duk_idx_t idx_func;
14345 	duk_int_t ret;
14346 
14347 	DUK_CTX_ASSERT_VALID(thr);
14348 	DUK_ASSERT(udata != NULL);
14349 
14350 	args = (duk__pcall_args *) udata;
14351 	idx_func = duk__call_get_idx_func_unvalidated(thr, args->nargs, 1);
14352 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14353 
14354 	duk_insert_undefined(thr, idx_func + 1);
14355 
14356 	ret = duk_handle_call_unprotected(thr, idx_func, args->call_flags);
14357 	DUK_ASSERT(ret == 0);
14358 	DUK_UNREF(ret);
14359 
14360 	return 1;
14361 }
14362 
duk_pcall(duk_hthread * thr,duk_idx_t nargs)14363 DUK_EXTERNAL duk_int_t duk_pcall(duk_hthread *thr, duk_idx_t nargs) {
14364 	duk__pcall_args args;
14365 
14366 	DUK_ASSERT_API_ENTRY(thr);
14367 
14368 	args.nargs = nargs;
14369 	if (DUK_UNLIKELY(nargs < 0)) {
14370 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14371 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14372 	}
14373 	args.call_flags = 0;
14374 
14375 	return duk_safe_call(thr, duk__pcall_raw, (void *) &args /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
14376 }
14377 
duk__pcall_method_raw(duk_hthread * thr,void * udata)14378 DUK_LOCAL duk_ret_t duk__pcall_method_raw(duk_hthread *thr, void *udata) {
14379 	duk__pcall_method_args *args;
14380 	duk_idx_t idx_func;
14381 	duk_int_t ret;
14382 
14383 	DUK_CTX_ASSERT_VALID(thr);
14384 	DUK_ASSERT(udata != NULL);
14385 
14386 	args = (duk__pcall_method_args *) udata;
14387 
14388 	idx_func = duk__call_get_idx_func_unvalidated(thr, args->nargs, 2);
14389 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14390 
14391 	ret = duk_handle_call_unprotected(thr, idx_func, args->call_flags);
14392 	DUK_ASSERT(ret == 0);
14393 	DUK_UNREF(ret);
14394 
14395 	return 1;
14396 }
14397 
duk_pcall_method_flags(duk_hthread * thr,duk_idx_t nargs,duk_small_uint_t call_flags)14398 DUK_INTERNAL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags) {
14399 	duk__pcall_method_args args;
14400 
14401 	DUK_ASSERT_API_ENTRY(thr);
14402 
14403 	args.nargs = nargs;
14404 	if (DUK_UNLIKELY(nargs < 0)) {
14405 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14406 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14407 	}
14408 	args.call_flags = call_flags;
14409 
14410 	return duk_safe_call(thr, duk__pcall_method_raw, (void *) &args /*udata*/, nargs + 2 /*nargs*/, 1 /*nrets*/);
14411 }
14412 
duk_pcall_method(duk_hthread * thr,duk_idx_t nargs)14413 DUK_EXTERNAL duk_int_t duk_pcall_method(duk_hthread *thr, duk_idx_t nargs) {
14414 	DUK_ASSERT_API_ENTRY(thr);
14415 
14416 	return duk_pcall_method_flags(thr, nargs, 0);
14417 }
14418 
duk__pcall_prop_raw(duk_hthread * thr,void * udata)14419 DUK_LOCAL duk_ret_t duk__pcall_prop_raw(duk_hthread *thr, void *udata) {
14420 	duk__pcall_prop_args *args;
14421 	duk_idx_t obj_idx;
14422 	duk_int_t ret;
14423 
14424 	DUK_CTX_ASSERT_VALID(thr);
14425 	DUK_ASSERT(udata != NULL);
14426 
14427 	args = (duk__pcall_prop_args *) udata;
14428 
14429 	obj_idx = duk_require_normalize_index(thr, args->obj_idx);  /* make absolute */
14430 	duk__call_prop_prep_stack(thr, obj_idx, args->nargs);
14431 
14432 	ret = duk_handle_call_unprotected_nargs(thr, args->nargs, args->call_flags);
14433 	DUK_ASSERT(ret == 0);
14434 	DUK_UNREF(ret);
14435 	return 1;
14436 }
14437 
duk_pcall_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_idx_t nargs)14438 DUK_EXTERNAL duk_int_t duk_pcall_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t nargs) {
14439 	duk__pcall_prop_args args;
14440 
14441 	DUK_ASSERT_API_ENTRY(thr);
14442 
14443 	args.obj_idx = obj_idx;
14444 	args.nargs = nargs;
14445 	if (DUK_UNLIKELY(nargs < 0)) {
14446 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14447 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14448 	}
14449 	args.call_flags = 0;
14450 
14451 	return duk_safe_call(thr, duk__pcall_prop_raw, (void *) &args /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
14452 }
14453 
duk_safe_call(duk_hthread * thr,duk_safe_call_function func,void * udata,duk_idx_t nargs,duk_idx_t nrets)14454 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) {
14455 	duk_int_t rc;
14456 
14457 	DUK_ASSERT_API_ENTRY(thr);
14458 
14459 	/* nargs condition; fail if: top - bottom < nargs
14460 	 *                      <=>  top < bottom + nargs
14461 	 * nrets condition; fail if: end - (top - nargs) < nrets
14462 	 *                      <=>  end - top + nargs < nrets
14463 	 *                      <=>  end + nargs < top + nrets
14464 	 */
14465 	/* XXX: check for any reserve? */
14466 
14467 	if (DUK_UNLIKELY((nargs | nrets) < 0 ||  /* nargs < 0 || nrets < 0; OR sign bits */
14468 	                 thr->valstack_top < thr->valstack_bottom + nargs ||        /* nargs too large compared to top */
14469 	                 thr->valstack_end + nargs < thr->valstack_top + nrets)) {  /* nrets too large compared to reserve */
14470 		DUK_D(DUK_DPRINT("not enough stack reserve for safe call or invalid arguments: "
14471 		                 "nargs=%ld < 0 (?), nrets=%ld < 0 (?), top=%ld < bottom=%ld + nargs=%ld (?), "
14472 		                 "end=%ld + nargs=%ld < top=%ld + nrets=%ld (?)",
14473 		                  (long) nargs,
14474 		                  (long) nrets,
14475 		                  (long) (thr->valstack_top - thr->valstack),
14476 		                  (long) (thr->valstack_bottom - thr->valstack),
14477 		                  (long) nargs,
14478 		                  (long) (thr->valstack_end - thr->valstack),
14479 		                  (long) nargs,
14480 		                  (long) (thr->valstack_top - thr->valstack),
14481 		                  (long) nrets));
14482 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14483 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14484 	}
14485 
14486 	rc = duk_handle_safe_call(thr,           /* thread */
14487 	                          func,          /* func */
14488 	                          udata,         /* udata */
14489 	                          nargs,         /* num_stack_args */
14490 	                          nrets);        /* num_stack_res */
14491 
14492 	return rc;
14493 }
14494 
duk_new(duk_hthread * thr,duk_idx_t nargs)14495 DUK_EXTERNAL void duk_new(duk_hthread *thr, duk_idx_t nargs) {
14496 	duk_idx_t idx_func;
14497 
14498 	DUK_ASSERT_API_ENTRY(thr);
14499 
14500 	idx_func = duk__call_get_idx_func(thr, nargs, 1);
14501 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14502 
14503 	duk_push_object(thr);  /* default instance; internal proto updated by call handling */
14504 	duk_insert(thr, idx_func + 1);
14505 
14506 	duk_handle_call_unprotected(thr, idx_func, DUK_CALL_FLAG_CONSTRUCT);
14507 }
14508 
duk__pnew_helper(duk_hthread * thr,void * udata)14509 DUK_LOCAL duk_ret_t duk__pnew_helper(duk_hthread *thr, void *udata) {
14510 	duk_idx_t nargs;
14511 
14512 	DUK_ASSERT(udata != NULL);
14513 	nargs = *((duk_idx_t *) udata);
14514 
14515 	duk_new(thr, nargs);
14516 	return 1;
14517 }
14518 
duk_pnew(duk_hthread * thr,duk_idx_t nargs)14519 DUK_EXTERNAL duk_int_t duk_pnew(duk_hthread *thr, duk_idx_t nargs) {
14520 	duk_int_t rc;
14521 
14522 	DUK_ASSERT_API_ENTRY(thr);
14523 
14524 	/* For now, just use duk_safe_call() to wrap duk_new().  We can't
14525 	 * simply use a protected duk_handle_call() because pushing the
14526 	 * default instance might throw.
14527 	 */
14528 
14529 	if (DUK_UNLIKELY(nargs < 0)) {
14530 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14531 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14532 	}
14533 
14534 	rc = duk_safe_call(thr, duk__pnew_helper, (void *) &nargs /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
14535 	return rc;
14536 }
14537 
duk_is_constructor_call(duk_hthread * thr)14538 DUK_EXTERNAL duk_bool_t duk_is_constructor_call(duk_hthread *thr) {
14539 	duk_activation *act;
14540 
14541 	DUK_ASSERT_API_ENTRY(thr);
14542 
14543 	act = thr->callstack_curr;
14544 	if (act != NULL) {
14545 		return ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);
14546 	}
14547 	return 0;
14548 }
14549 
duk_require_constructor_call(duk_hthread * thr)14550 DUK_EXTERNAL void duk_require_constructor_call(duk_hthread *thr) {
14551 	DUK_ASSERT_API_ENTRY(thr);
14552 
14553 	if (!duk_is_constructor_call(thr)) {
14554 		DUK_ERROR_TYPE(thr, DUK_STR_CONSTRUCT_ONLY);
14555 		DUK_WO_NORETURN(return;);
14556 	}
14557 }
14558 
duk_is_strict_call(duk_hthread * thr)14559 DUK_EXTERNAL duk_bool_t duk_is_strict_call(duk_hthread *thr) {
14560 	duk_activation *act;
14561 
14562 	/* For user code this could just return 1 (strict) always
14563 	 * because all Duktape/C functions are considered strict,
14564 	 * and strict is also the default when nothing is running.
14565 	 * However, Duktape may call this function internally when
14566 	 * the current activation is an ECMAScript function, so
14567 	 * this cannot be replaced by a 'return 1' without fixing
14568 	 * the internal call sites.
14569 	 */
14570 
14571 	DUK_ASSERT_API_ENTRY(thr);
14572 
14573 	act = thr->callstack_curr;
14574 	if (act != NULL) {
14575 		return ((act->flags & DUK_ACT_FLAG_STRICT) != 0 ? 1 : 0);
14576 	} else {
14577 		/* Strict by default. */
14578 		return 1;
14579 	}
14580 }
14581 
14582 /*
14583  *  Duktape/C function magic
14584  */
14585 
duk_get_current_magic(duk_hthread * thr)14586 DUK_EXTERNAL duk_int_t duk_get_current_magic(duk_hthread *thr) {
14587 	duk_activation *act;
14588 	duk_hobject *func;
14589 
14590 	DUK_ASSERT_API_ENTRY(thr);
14591 
14592 	act = thr->callstack_curr;
14593 	if (act) {
14594 		func = DUK_ACT_GET_FUNC(act);
14595 		if (!func) {
14596 			duk_tval *tv = &act->tv_func;
14597 			duk_small_uint_t lf_flags;
14598 			lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
14599 			return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
14600 		}
14601 		DUK_ASSERT(func != NULL);
14602 
14603 		if (DUK_HOBJECT_IS_NATFUNC(func)) {
14604 			duk_hnatfunc *nf = (duk_hnatfunc *) func;
14605 			return (duk_int_t) nf->magic;
14606 		}
14607 	}
14608 	return 0;
14609 }
14610 
duk_get_magic(duk_hthread * thr,duk_idx_t idx)14611 DUK_EXTERNAL duk_int_t duk_get_magic(duk_hthread *thr, duk_idx_t idx) {
14612 	duk_tval *tv;
14613 	duk_hobject *h;
14614 
14615 	DUK_ASSERT_API_ENTRY(thr);
14616 
14617 	tv = duk_require_tval(thr, idx);
14618 	if (DUK_TVAL_IS_OBJECT(tv)) {
14619 		h = DUK_TVAL_GET_OBJECT(tv);
14620 		DUK_ASSERT(h != NULL);
14621 		if (!DUK_HOBJECT_HAS_NATFUNC(h)) {
14622 			goto type_error;
14623 		}
14624 		return (duk_int_t) ((duk_hnatfunc *) h)->magic;
14625 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
14626 		duk_small_uint_t lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
14627 		return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
14628 	}
14629 
14630 	/* fall through */
14631  type_error:
14632 	DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
14633 	DUK_WO_NORETURN(return 0;);
14634 }
14635 
duk_set_magic(duk_hthread * thr,duk_idx_t idx,duk_int_t magic)14636 DUK_EXTERNAL void duk_set_magic(duk_hthread *thr, duk_idx_t idx, duk_int_t magic) {
14637 	duk_hnatfunc *nf;
14638 
14639 	DUK_ASSERT_API_ENTRY(thr);
14640 
14641 	nf = duk_require_hnatfunc(thr, idx);
14642 	DUK_ASSERT(nf != NULL);
14643 	nf->magic = (duk_int16_t) magic;
14644 }
14645 
14646 /*
14647  *  Misc helpers
14648  */
14649 
14650 /* Resolve a bound function on value stack top to a non-bound target
14651  * (leave other values as is).
14652  */
duk_resolve_nonbound_function(duk_hthread * thr)14653 DUK_INTERNAL void duk_resolve_nonbound_function(duk_hthread *thr) {
14654 	duk_tval *tv;
14655 
14656 	DUK_HTHREAD_ASSERT_VALID(thr);
14657 
14658 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
14659 	if (DUK_TVAL_IS_OBJECT(tv)) {
14660 		duk_hobject *h;
14661 
14662 		h = DUK_TVAL_GET_OBJECT(tv);
14663 		DUK_ASSERT(h != NULL);
14664 		if (DUK_HOBJECT_HAS_BOUNDFUNC(h)) {
14665 			duk_push_tval(thr, &((duk_hboundfunc *) (void *) h)->target);
14666 			duk_replace(thr, -2);
14667 #if 0
14668 			DUK_TVAL_SET_TVAL(tv, &((duk_hboundfunc *) h)->target);
14669 			DUK_TVAL_INCREF(thr, tv);
14670 			DUK_HOBJECT_DECREF_NORZ(thr, h);
14671 #endif
14672 			/* Rely on Function.prototype.bind() on never creating a bound
14673 			 * function whose target is not proper.  This is now safe
14674 			 * because the target is not even an internal property but a
14675 			 * struct member.
14676 			 */
14677 			DUK_ASSERT(duk_is_lightfunc(thr, -1) || duk_is_callable(thr, -1));
14678 		}
14679 	}
14680 
14681 	/* Lightfuncs cannot be bound but are always callable and
14682 	 * constructable.
14683 	 */
14684 }
14685 /*
14686  *  Encoding and decoding basic formats: hex, base64.
14687  *
14688  *  These are in-place operations which may allow an optimized implementation.
14689  *
14690  *  Base-64: https://tools.ietf.org/html/rfc4648#section-4
14691  */
14692 
14693 /* #include duk_internal.h -> already included */
14694 
14695 /*
14696  *  Misc helpers
14697  */
14698 
14699 /* Shared handling for encode/decode argument.  Fast path handling for
14700  * buffer and string values because they're the most common.  In particular,
14701  * avoid creating a temporary string or buffer when possible.  Return value
14702  * is guaranteed to be non-NULL, even for zero length input.
14703  */
duk__prep_codec_arg(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)14704 DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
14705 	const void *def_ptr = (const void *) out_len;  /* Any non-NULL pointer will do. */
14706 	const void *ptr;
14707 	duk_bool_t isbuffer;
14708 
14709 	DUK_ASSERT(out_len != NULL);
14710 	DUK_ASSERT(def_ptr != NULL);
14711 	DUK_ASSERT(duk_is_valid_index(thr, idx));  /* checked by caller */
14712 
14713 	ptr = (const void *) duk_get_buffer_data_raw(thr, idx, out_len, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, &isbuffer);
14714 	if (isbuffer) {
14715 		DUK_ASSERT(ptr != NULL || *out_len == 0U);
14716 		if (DUK_UNLIKELY(ptr == NULL)) {
14717 			ptr = def_ptr;
14718 		}
14719 		DUK_ASSERT(ptr != NULL);
14720 	} else {
14721 		/* For strings a non-NULL pointer is always guaranteed because
14722 		 * at least a NUL will be present.
14723 		 */
14724 		ptr = (const void *) duk_to_lstring(thr, idx, out_len);
14725 		DUK_ASSERT(ptr != NULL);
14726 	}
14727 	DUK_ASSERT(ptr != NULL);
14728 	return (const duk_uint8_t *) ptr;
14729 }
14730 
14731 /*
14732  *  Base64
14733  */
14734 
14735 #if defined(DUK_USE_BASE64_SUPPORT)
14736 /* Bytes emitted for number of padding characters in range [0,4]. */
14737 DUK_LOCAL const duk_int8_t duk__base64_decode_nequal_step[5] = {
14738 	3,   /* #### -> 24 bits, emit 3 bytes */
14739 	2,   /* ###= -> 18 bits, emit 2 bytes */
14740 	1,   /* ##== -> 12 bits, emit 1 byte */
14741 	-1,  /* #=== -> 6 bits, error */
14742 	0,   /* ==== -> 0 bits, emit 0 bytes */
14743 };
14744 
14745 #if defined(DUK_USE_BASE64_FASTPATH)
14746 DUK_LOCAL const duk_uint8_t duk__base64_enctab_fast[64] = {
14747 	0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, 0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, 0x50U,  /* A...P */
14748 	0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U, 0x58U, 0x59U, 0x5aU, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U,  /* Q...f */
14749 	0x67U, 0x68U, 0x69U, 0x6aU, 0x6bU, 0x6cU, 0x6dU, 0x6eU, 0x6fU, 0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U,  /* g...v */
14750 	0x77U, 0x78U, 0x79U, 0x7aU, 0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U, 0x38U, 0x39U, 0x2bU, 0x2fU   /* w.../ */
14751 };
14752 #endif  /* DUK_USE_BASE64_FASTPATH */
14753 
14754 #if defined(DUK_USE_BASE64_FASTPATH)
14755 /* Decode table for one byte of input:
14756  *   -1 = allowed whitespace
14757  *   -2 = padding
14758  *   -3 = error
14759  *    0...63 decoded bytes
14760  */
14761 DUK_LOCAL const duk_int8_t duk__base64_dectab_fast[256] = {
14762 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -1, -1, -3, -3, -1, -3, -3,  /* 0x00...0x0f */
14763 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0x10...0x1f */
14764 	-1, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, 62, -3, -3, -3, 63,  /* 0x20...0x2f */
14765 	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -3, -3, -3, -2, -3, -3,  /* 0x30...0x3f */
14766 	-3,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,  /* 0x40...0x4f */
14767 	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -3, -3, -3, -3, -3,  /* 0x50...0x5f */
14768 	-3, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,  /* 0x60...0x6f */
14769 	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -3, -3, -3, -3, -3,  /* 0x70...0x7f */
14770 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0x80...0x8f */
14771 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0x90...0x9f */
14772 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xa0...0xaf */
14773 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xb0...0xbf */
14774 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xc0...0xcf */
14775 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xd0...0xdf */
14776 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xe0...0xef */
14777 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3   /* 0xf0...0xff */
14778 };
14779 #endif  /* DUK_USE_BASE64_FASTPATH */
14780 
14781 #if defined(DUK_USE_BASE64_FASTPATH)
duk__base64_encode_fast_3(const duk_uint8_t * src,duk_uint8_t * dst)14782 DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_3(const duk_uint8_t *src, duk_uint8_t *dst) {
14783 	duk_uint_t t;
14784 
14785 	t = (duk_uint_t) src[0];
14786 	t = (t << 8) + (duk_uint_t) src[1];
14787 	t = (t << 8) + (duk_uint_t) src[2];
14788 
14789 	dst[0] = duk__base64_enctab_fast[t >> 18];
14790 	dst[1] = duk__base64_enctab_fast[(t >> 12) & 0x3fU];
14791 	dst[2] = duk__base64_enctab_fast[(t >> 6) & 0x3fU];
14792 	dst[3] = duk__base64_enctab_fast[t & 0x3fU];
14793 
14794 #if 0
14795 	/* Tested: not faster on x64, most likely due to aliasing between
14796 	 * output and input index computation.
14797 	 */
14798 	/* aaaaaabb bbbbcccc ccdddddd */
14799 	dst[0] = duk__base64_enctab_fast[(src[0] >> 2) & 0x3fU];
14800 	dst[1] = duk__base64_enctab_fast[((src[0] << 4) & 0x30U) | ((src[1] >> 4) & 0x0fU)];
14801 	dst[2] = duk__base64_enctab_fast[((src[1] << 2) & 0x3fU) | ((src[2] >> 6) & 0x03U)];
14802 	dst[3] = duk__base64_enctab_fast[src[2] & 0x3fU];
14803 #endif
14804 }
14805 
duk__base64_encode_fast_2(const duk_uint8_t * src,duk_uint8_t * dst)14806 DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_2(const duk_uint8_t *src, duk_uint8_t *dst) {
14807 	duk_uint_t t;
14808 
14809 	t = (duk_uint_t) src[0];
14810 	t = (t << 8) + (duk_uint_t) src[1];
14811 	dst[0] = duk__base64_enctab_fast[t >> 10];           /* XXXXXX-- -------- */
14812 	dst[1] = duk__base64_enctab_fast[(t >> 4) & 0x3fU];  /* ------XX XXXX---- */
14813 	dst[2] = duk__base64_enctab_fast[(t << 2) & 0x3fU];  /* -------- ----XXXX */
14814 	dst[3] = DUK_ASC_EQUALS;
14815 }
14816 
duk__base64_encode_fast_1(const duk_uint8_t * src,duk_uint8_t * dst)14817 DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_1(const duk_uint8_t *src, duk_uint8_t *dst) {
14818 	duk_uint_t t;
14819 
14820 	t = (duk_uint_t) src[0];
14821 	dst[0] = duk__base64_enctab_fast[t >> 2];            /* XXXXXX-- */
14822 	dst[1] = duk__base64_enctab_fast[(t << 4) & 0x3fU];  /* ------XX */
14823 	dst[2] = DUK_ASC_EQUALS;
14824 	dst[3] = DUK_ASC_EQUALS;
14825 }
14826 
duk__base64_encode_helper(const duk_uint8_t * src,duk_size_t srclen,duk_uint8_t * dst)14827 DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
14828 	duk_size_t n;
14829 	const duk_uint8_t *p;
14830 	duk_uint8_t *q;
14831 
14832 	n = srclen;
14833 	p = src;
14834 	q = dst;
14835 
14836 	if (n >= 16U) {
14837 		/* Fast path, unrolled by 4, allows interleaving.  Process
14838 		 * 12-byte input chunks which encode to 16-char output chunks.
14839 		 * Only enter when at least one block is emitted (avoids div+mul
14840 		 * for short inputs too).
14841 		 */
14842 		const duk_uint8_t *p_end_fast;
14843 
14844 		p_end_fast = p + ((n / 12U) * 12U);
14845 		DUK_ASSERT(p_end_fast >= p + 12);
14846 		do {
14847 			duk__base64_encode_fast_3(p, q);
14848 			duk__base64_encode_fast_3(p + 3, q + 4);
14849 			duk__base64_encode_fast_3(p + 6, q + 8);
14850 			duk__base64_encode_fast_3(p + 9, q + 12);
14851 			p += 12;
14852 			q += 16;
14853 		} while (DUK_LIKELY(p != p_end_fast));
14854 
14855 		DUK_ASSERT(src + srclen >= p);
14856 		n = (duk_size_t) (src + srclen - p);
14857 		DUK_ASSERT(n < 12U);
14858 	}
14859 
14860 	/* Remainder. */
14861 	while (n >= 3U) {
14862 		duk__base64_encode_fast_3(p, q);
14863 		p += 3;
14864 		q += 4;
14865 		n -= 3U;
14866 	}
14867 	DUK_ASSERT(n == 0U || n == 1U || n == 2U);
14868 	if (n == 1U) {
14869 		duk__base64_encode_fast_1(p, q);
14870 #if 0  /* Unnecessary. */
14871 		p += 1;
14872 		q += 4;
14873 		n -= 1U;
14874 #endif
14875 	} else if (n == 2U) {
14876 		duk__base64_encode_fast_2(p, q);
14877 #if 0  /* Unnecessary. */
14878 		p += 2;
14879 		q += 4;
14880 		n -= 2U;
14881 #endif
14882 	} else {
14883 		DUK_ASSERT(n == 0U);  /* nothing to do */
14884 		;
14885 	}
14886 }
14887 #else  /* DUK_USE_BASE64_FASTPATH */
duk__base64_encode_helper(const duk_uint8_t * src,duk_size_t srclen,duk_uint8_t * dst)14888 DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
14889 	duk_small_uint_t i, npad;
14890 	duk_uint_t t, x, y;
14891 	const duk_uint8_t *p;
14892 	const duk_uint8_t *p_end;
14893 	duk_uint8_t *q;
14894 
14895 	p = src;
14896 	p_end = src + srclen;
14897 	q = dst;
14898 	npad = 0U;
14899 
14900 	while (p < p_end) {
14901 		/* Read 3 bytes into 't', padded by zero. */
14902 		t = 0;
14903 		for (i = 0; i < 3; i++) {
14904 			t = t << 8;
14905 			if (p < p_end) {
14906 				t += (duk_uint_t) (*p++);
14907 			} else {
14908 				/* This only happens on the last loop and we're
14909 				 * guaranteed to exit on the next loop.
14910 				 */
14911 				npad++;
14912 			}
14913 		}
14914 		DUK_ASSERT(npad <= 2U);
14915 
14916 		/* Emit 4 encoded characters.  If npad > 0, some of the
14917 		 * chars will be incorrect (zero bits) but we fix up the
14918 		 * padding after the loop.  A straightforward 64-byte
14919 		 * lookup would be faster and cleaner, but this is shorter.
14920 		 */
14921 		for (i = 0; i < 4; i++) {
14922 			x = ((t >> 18) & 0x3fU);
14923 			t = t << 6;
14924 
14925 			if (x <= 51U) {
14926 				if (x <= 25) {
14927 					y = x + DUK_ASC_UC_A;
14928 				} else {
14929 					y = x - 26 + DUK_ASC_LC_A;
14930 				}
14931 			} else {
14932 				if (x <= 61U) {
14933 					y = x - 52 + DUK_ASC_0;
14934 				} else if (x == 62) {
14935 					y = DUK_ASC_PLUS;
14936 				} else {
14937 					DUK_ASSERT(x == 63);
14938 					y = DUK_ASC_SLASH;
14939 				}
14940 			}
14941 
14942 			*q++ = (duk_uint8_t) y;
14943 		}
14944 	}
14945 
14946 	/* Handle padding by rewriting 0-2 bogus characters at the end.
14947 	 *
14948 	 *  Missing bytes    npad     base64 example
14949 	 *    0               0         ####
14950 	 *    1               1         ###=
14951 	 *    2               2         ##==
14952 	 */
14953 	DUK_ASSERT(npad <= 2U);
14954 	while (npad > 0U) {
14955 		*(q - npad) = DUK_ASC_EQUALS;
14956 		npad--;
14957 	}
14958 }
14959 #endif  /* DUK_USE_BASE64_FASTPATH */
14960 
14961 #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)14962 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) {
14963 	duk_int_t x;
14964 	duk_uint_t t;
14965 	duk_small_uint_t n_equal;
14966 	duk_int8_t step;
14967 	const duk_uint8_t *p;
14968 	const duk_uint8_t *p_end;
14969 	const duk_uint8_t *p_end_safe;
14970 	duk_uint8_t *q;
14971 
14972 	DUK_ASSERT(src != NULL);  /* Required by pointer arithmetic below, which fails for NULL. */
14973 
14974 	p = src;
14975 	p_end = src + srclen;
14976 	p_end_safe = p_end - 8;  /* If 'src <= src_end_safe', safe to read 8 bytes. */
14977 	q = dst;
14978 
14979 	/* Alternate between a fast path which processes clean groups with no
14980 	 * padding or whitespace, and a slow path which processes one arbitrary
14981 	 * group and then re-enters the fast path.  This handles e.g. base64
14982 	 * with newlines reasonably well because the majority of a line is in
14983 	 * the fast path.
14984 	 */
14985 	for (;;) {
14986 		/* Fast path, on each loop handle two 4-char input groups.
14987 		 * If both are clean, emit 6 bytes and continue.  If first
14988 		 * is clean, emit 3 bytes and drop out; otherwise emit
14989 		 * nothing and drop out.  This approach could be extended to
14990 		 * more groups per loop, but for inputs with e.g. periodic
14991 		 * newlines (which are common) it might not be an improvement.
14992 		 */
14993 		while (DUK_LIKELY(p <= p_end_safe)) {
14994 			duk_int_t t1, t2;
14995 
14996 			/* The lookup byte is intentionally sign extended to
14997 			 * (at least) 32 bits and then ORed.  This ensures
14998 			 * that is at least 1 byte is negative, the highest
14999 			 * bit of the accumulator will be set at the end and
15000 			 * we don't need to check every byte.
15001 			 *
15002 			 * Read all input bytes first before writing output
15003 			 * bytes to minimize aliasing.
15004 			 */
15005 			DUK_DDD(DUK_DDDPRINT("fast loop: p=%p, p_end_safe=%p, p_end=%p",
15006 			                     (const void *) p, (const void *) p_end_safe, (const void *) p_end));
15007 
15008 			t1 = (duk_int_t) duk__base64_dectab_fast[p[0]];
15009 			t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[1]];
15010 			t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[2]];
15011 			t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[3]];
15012 
15013 			t2 = (duk_int_t) duk__base64_dectab_fast[p[4]];
15014 			t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[5]];
15015 			t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[6]];
15016 			t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[7]];
15017 
15018 			q[0] = (duk_uint8_t) (((duk_uint_t) t1 >> 16) & 0xffU);
15019 			q[1] = (duk_uint8_t) (((duk_uint_t) t1 >> 8) & 0xffU);
15020 			q[2] = (duk_uint8_t) ((duk_uint_t) t1 & 0xffU);
15021 
15022 			q[3] = (duk_uint8_t) (((duk_uint_t) t2 >> 16) & 0xffU);
15023 			q[4] = (duk_uint8_t) (((duk_uint_t) t2 >> 8) & 0xffU);
15024 			q[5] = (duk_uint8_t) ((duk_uint_t) t2 & 0xffU);
15025 
15026 			/* Optimistic check using one branch. */
15027 			if (DUK_LIKELY((t1 | t2) >= 0)) {
15028 				p += 8;
15029 				q += 6;
15030 			} else if (t1 >= 0) {
15031 				DUK_DDD(DUK_DDDPRINT("fast loop first group was clean, second was not, process one slow path group"));
15032 				DUK_ASSERT(t2 < 0);
15033 				p += 4;
15034 				q += 3;
15035 				break;
15036 			} else {
15037 				DUK_DDD(DUK_DDDPRINT("fast loop first group was not clean, second does not matter, process one slow path group"));
15038 				DUK_ASSERT(t1 < 0);
15039 				break;
15040 			}
15041 		}  /* fast path */
15042 
15043 		/* Slow path step 1: try to scan a 4-character encoded group,
15044 		 * end-of-input, or start-of-padding.  We exit with:
15045 		 *   1. n_chars == 4: full group, no padding, no end-of-input.
15046 		 *   2. n_chars < 4: partial group (may also be 0), encountered
15047 		 *      padding or end of input.
15048 		 *
15049 		 * The accumulator is initialized to 1; this allows us to detect
15050 		 * a full group by comparing >= 0x1000000 without an extra
15051 		 * counter variable.
15052 		 */
15053 		t = 1UL;
15054 		for (;;) {
15055 			DUK_DDD(DUK_DDDPRINT("slow loop: p=%p, p_end=%p, t=%lu",
15056 			                     (const void *) p, (const void *) p_end, (unsigned long) t));
15057 
15058 			if (DUK_LIKELY(p < p_end)) {
15059 				x = duk__base64_dectab_fast[*p++];
15060 				if (DUK_LIKELY(x >= 0)) {
15061 					DUK_ASSERT(x >= 0 && x <= 63);
15062 					t = (t << 6) + (duk_uint_t) x;
15063 					if (t >= 0x1000000UL) {
15064 						break;
15065 					}
15066 				} else if (x == -1) {
15067 					continue;  /* allowed ascii whitespace */
15068 				} else if (x == -2) {
15069 					p--;
15070 					break;  /* start of padding */
15071 				} else {
15072 					DUK_ASSERT(x == -3);
15073 					goto decode_error;
15074 				}
15075 			} else {
15076 				break;  /* end of input */
15077 			}
15078 		}  /* slow path step 1 */
15079 
15080 		/* Complete the padding by simulating pad characters,
15081 		 * regardless of actual input padding chars.
15082 		 */
15083 		n_equal = 0;
15084 		while (t < 0x1000000UL) {
15085 			t = (t << 6) + 0U;
15086 			n_equal++;
15087 		}
15088 
15089 		/* Slow path step 2: deal with full/partial group, padding,
15090 		 * etc.  Note that for num chars in [0,3] we intentionally emit
15091 		 * 3 bytes but don't step forward that much, buffer space is
15092 		 * guaranteed in setup.
15093 		 *
15094 		 *  num chars:
15095 		 *   0      ####   no output (= step 0)
15096 		 *   1      #===   reject, 6 bits of data
15097 		 *   2      ##==   12 bits of data, output 1 byte (= step 1)
15098 		 *   3      ###=   18 bits of data, output 2 bytes (= step 2)
15099 		 *   4      ####   24 bits of data, output 3 bytes (= step 3)
15100 		 */
15101 		q[0] = (duk_uint8_t) ((t >> 16) & 0xffU);
15102 		q[1] = (duk_uint8_t) ((t >> 8) & 0xffU);
15103 		q[2] = (duk_uint8_t) (t & 0xffU);
15104 
15105 		DUK_ASSERT(n_equal <= 4);
15106 		step = duk__base64_decode_nequal_step[n_equal];
15107 		if (DUK_UNLIKELY(step < 0)) {
15108 			goto decode_error;
15109 		}
15110 		q += step;
15111 
15112 		/* Slow path step 3: read and ignore padding and whitespace
15113 		 * until (a) next non-padding and non-whitespace character
15114 		 * after which we resume the fast path, or (b) end of input.
15115 		 * This allows us to accept missing, partial, full, and extra
15116 		 * padding cases uniformly.  We also support concatenated
15117 		 * base-64 documents because we resume scanning afterwards.
15118 		 *
15119 		 * Note that to support concatenated documents well, the '='
15120 		 * padding found inside the input must also allow for 'extra'
15121 		 * padding.  For example, 'Zm===' decodes to 'f' and has one
15122 		 * extra padding char.  So, 'Zm===Zm' should decode 'ff', even
15123 		 * though the standard break-up would be 'Zm==' + '=Zm' which
15124 		 * doesn't make sense.
15125 		 *
15126 		 * We also accept prepended padding like '==Zm9', because it
15127 		 * is equivalent to an empty document with extra padding ('==')
15128 		 * followed by a valid document.
15129 		 */
15130 
15131 		for (;;) {
15132 			if (DUK_UNLIKELY(p >= p_end)) {
15133 				goto done;
15134 			}
15135 			x = duk__base64_dectab_fast[*p++];
15136 			if (x == -1 || x == -2) {
15137 				;  /* padding or whitespace, keep eating */
15138 			} else {
15139 				p--;
15140 				break;  /* backtrack and go back to fast path, even for -1 */
15141 			}
15142 		}  /* slow path step 3 */
15143 	}  /* outer fast+slow path loop */
15144 
15145  done:
15146 	DUK_DDD(DUK_DDDPRINT("done; p=%p, p_end=%p",
15147 	                     (const void *) p, (const void *) p_end));
15148 
15149 	DUK_ASSERT(p == p_end);
15150 
15151 	*out_dst_final = q;
15152 	return 1;
15153 
15154  decode_error:
15155 	return 0;
15156 }
15157 #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)15158 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) {
15159 	duk_uint_t t, x;
15160 	duk_int_t y;
15161 	duk_int8_t step;
15162 	const duk_uint8_t *p;
15163 	const duk_uint8_t *p_end;
15164 	duk_uint8_t *q;
15165 	/* 0x09, 0x0a, or 0x0d */
15166 	duk_uint32_t mask_white = (1U << 9) | (1U << 10) | (1U << 13);
15167 
15168 	/* 't' tracks progress of the decoded group:
15169 	 *
15170 	 *  t == 1             no valid chars yet
15171 	 *  t >= 0x40          1x6 = 6 bits shifted in
15172 	 *  t >= 0x1000        2x6 = 12 bits shifted in
15173 	 *  t >= 0x40000       3x6 = 18 bits shifted in
15174 	 *  t >= 0x1000000     4x6 = 24 bits shifted in
15175 	 *
15176 	 * By initializing t=1 there's no need for a separate counter for
15177 	 * the number of characters found so far.
15178 	 */
15179 	p = src;
15180 	p_end = src + srclen;
15181 	q = dst;
15182 	t = 1UL;
15183 
15184 	for (;;) {
15185 		duk_small_uint_t n_equal;
15186 
15187 		DUK_ASSERT(t >= 1U);
15188 		if (p >= p_end) {
15189 			/* End of input: if input exists, treat like
15190 			 * start of padding, finish the block, then
15191 			 * re-enter here to see we're done.
15192 			 */
15193 			if (t == 1U) {
15194 				break;
15195 			} else {
15196 				goto simulate_padding;
15197 			}
15198 		}
15199 
15200 		x = *p++;
15201 
15202 		if (x >= 0x41U) {
15203 			/* Valid: a-z and A-Z. */
15204 			DUK_ASSERT(x >= 0x41U && x <= 0xffU);
15205 			if (x >= 0x61U && x <= 0x7aU) {
15206 				y = (duk_int_t) x - 0x61 + 26;
15207 			} else if (x <= 0x5aU) {
15208 				y = (duk_int_t) x - 0x41;
15209 			} else {
15210 				goto decode_error;
15211 			}
15212 		} else if (x >= 0x30U) {
15213 			/* Valid: 0-9 and =. */
15214 			DUK_ASSERT(x >= 0x30U && x <= 0x40U);
15215 			if (x <= 0x39U) {
15216 				y = (duk_int_t) x - 0x30 + 52;
15217 			} else if (x == 0x3dU) {
15218 				/* Skip padding and whitespace unless we're in the
15219 				 * middle of a block.  Otherwise complete group by
15220 				 * simulating shifting in the correct padding.
15221 				 */
15222 				if (t == 1U) {
15223 					continue;
15224 				}
15225 				goto simulate_padding;
15226 			} else {
15227 				goto decode_error;
15228 			}
15229 		} else if (x >= 0x20U) {
15230 			/* Valid: +, /, and 0x20 whitespace. */
15231 			DUK_ASSERT(x >= 0x20U && x <= 0x2fU);
15232 			if (x == 0x2bU) {
15233 				y = 62;
15234 			} else if (x == 0x2fU) {
15235 				y = 63;
15236 			} else if (x == 0x20U) {
15237 				continue;
15238 			} else {
15239 				goto decode_error;
15240 			}
15241 		} else {
15242 			/* Valid: whitespace. */
15243 			duk_uint32_t m;
15244 			DUK_ASSERT(x < 0x20U);  /* 0x00 to 0x1f */
15245 			m = (1U << x);
15246 			if (mask_white & m) {
15247 				/* Allow basic ASCII whitespace. */
15248 				continue;
15249 			} else {
15250 				goto decode_error;
15251 			}
15252 		}
15253 
15254 		DUK_ASSERT(y >= 0 && y <= 63);
15255 		t = (t << 6) + (duk_uint_t) y;
15256 		if (t < 0x1000000UL) {
15257 			continue;
15258 		}
15259 		/* fall through; no padding will be added */
15260 
15261 	 simulate_padding:
15262 		n_equal = 0;
15263 		while (t < 0x1000000UL) {
15264 			t = (t << 6) + 0U;
15265 			n_equal++;
15266 		}
15267 
15268 		/* Output 3 bytes from 't' and advance as needed. */
15269 		q[0] = (duk_uint8_t) ((t >> 16) & 0xffU);
15270 		q[1] = (duk_uint8_t) ((t >> 8) & 0xffU);
15271 		q[2] = (duk_uint8_t) (t & 0xffU);
15272 
15273 		DUK_ASSERT(n_equal <= 4U);
15274 		step = duk__base64_decode_nequal_step[n_equal];
15275 		if (step < 0) {
15276 			goto decode_error;
15277 		}
15278 		q += step;
15279 
15280 		/* Re-enter loop.  The actual padding characters are skipped
15281 		 * by the main loop.  This handles cases like missing, partial,
15282 		 * full, and extra padding, and allows parsing of concatenated
15283 		 * documents (with extra padding) like: Zm===Zm.  Also extra
15284 		 * prepended padding is accepted: ===Zm9v.
15285 		 */
15286 		t = 1U;
15287 	}
15288 	DUK_ASSERT(t == 1UL);
15289 
15290 	*out_dst_final = q;
15291 	return 1;
15292 
15293  decode_error:
15294 	return 0;
15295 }
15296 #endif  /* DUK_USE_BASE64_FASTPATH */
15297 
duk_base64_encode(duk_hthread * thr,duk_idx_t idx)15298 DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
15299 	const duk_uint8_t *src;
15300 	duk_size_t srclen;
15301 	duk_size_t dstlen;
15302 	duk_uint8_t *dst;
15303 	const char *ret;
15304 
15305 	DUK_ASSERT_API_ENTRY(thr);
15306 
15307 	idx = duk_require_normalize_index(thr, idx);
15308 	src = duk__prep_codec_arg(thr, idx, &srclen);
15309 	DUK_ASSERT(src != NULL);
15310 
15311 	/* Compute exact output length.  Computation must not wrap; this
15312 	 * limit works for 32-bit size_t:
15313 	 * >>> srclen = 3221225469
15314 	 * >>> '%x' % ((srclen + 2) / 3 * 4)
15315 	 * 'fffffffc'
15316 	 */
15317 	if (srclen > 3221225469UL) {
15318 		goto type_error;
15319 	}
15320 	dstlen = (srclen + 2U) / 3U * 4U;
15321 	dst = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, dstlen);
15322 
15323 	duk__base64_encode_helper((const duk_uint8_t *) src, srclen, dst);
15324 
15325 	ret = duk_buffer_to_string(thr, -1);  /* Safe, result is ASCII. */
15326 	duk_replace(thr, idx);
15327 	return ret;
15328 
15329  type_error:
15330 	DUK_ERROR_TYPE(thr, DUK_STR_BASE64_ENCODE_FAILED);
15331 	DUK_WO_NORETURN(return NULL;);
15332 }
15333 
duk_base64_decode(duk_hthread * thr,duk_idx_t idx)15334 DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) {
15335 	const duk_uint8_t *src;
15336 	duk_size_t srclen;
15337 	duk_size_t dstlen;
15338 	duk_uint8_t *dst;
15339 	duk_uint8_t *dst_final;
15340 
15341 	DUK_ASSERT_API_ENTRY(thr);
15342 
15343 	idx = duk_require_normalize_index(thr, idx);
15344 	src = duk__prep_codec_arg(thr, idx, &srclen);
15345 	DUK_ASSERT(src != NULL);
15346 
15347 	/* Round up and add safety margin.  Avoid addition before division to
15348 	 * avoid possibility of wrapping.  Margin includes +3 for rounding up,
15349 	 * and +3 for one extra group: the decoder may emit and then backtrack
15350 	 * a full group (3 bytes) from zero-sized input for technical reasons.
15351 	 * Similarly, 'xx' may ecause 1+3 = bytes to be emitted and then
15352 	 * backtracked.
15353 	 */
15354 	dstlen = (srclen / 4) * 3 + 6;  /* upper limit, assuming no whitespace etc */
15355 	dst = (duk_uint8_t *) duk_push_dynamic_buffer(thr, dstlen);
15356 	/* Note: for dstlen=0, dst may be NULL */
15357 
15358 	if (!duk__base64_decode_helper((const duk_uint8_t *) src, srclen, dst, &dst_final)) {
15359 		goto type_error;
15360 	}
15361 
15362 	/* XXX: convert to fixed buffer? */
15363 	(void) duk_resize_buffer(thr, -1, (duk_size_t) (dst_final - dst));
15364 	duk_replace(thr, idx);
15365 	return;
15366 
15367  type_error:
15368 	DUK_ERROR_TYPE(thr, DUK_STR_BASE64_DECODE_FAILED);
15369 	DUK_WO_NORETURN(return;);
15370 }
15371 #else  /* DUK_USE_BASE64_SUPPORT */
duk_base64_encode(duk_hthread * thr,duk_idx_t idx)15372 DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
15373 	DUK_UNREF(idx);
15374 	DUK_ERROR_UNSUPPORTED(thr);
15375 	DUK_WO_NORETURN(return;);
15376 }
15377 
duk_base64_decode(duk_hthread * thr,duk_idx_t idx)15378 DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) {
15379 	DUK_UNREF(idx);
15380 	DUK_ERROR_UNSUPPORTED(thr);
15381 	DUK_WO_NORETURN(return;);
15382 }
15383 #endif  /* DUK_USE_BASE64_SUPPORT */
15384 
15385 /*
15386  *  Hex
15387  */
15388 
15389 #if defined(DUK_USE_HEX_SUPPORT)
duk_hex_encode(duk_hthread * thr,duk_idx_t idx)15390 DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
15391 	const duk_uint8_t *inp;
15392 	duk_size_t len;
15393 	duk_size_t i;
15394 	duk_uint8_t *buf;
15395 	const char *ret;
15396 #if defined(DUK_USE_HEX_FASTPATH)
15397 	duk_size_t len_safe;
15398 	duk_uint16_t *p16;
15399 #endif
15400 
15401 	DUK_ASSERT_API_ENTRY(thr);
15402 
15403 	idx = duk_require_normalize_index(thr, idx);
15404 	inp = duk__prep_codec_arg(thr, idx, &len);
15405 	DUK_ASSERT(inp != NULL);
15406 
15407 	/* Fixed buffer, no zeroing because we'll fill all the data. */
15408 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len * 2);
15409 	DUK_ASSERT(buf != NULL);
15410 
15411 #if defined(DUK_USE_HEX_FASTPATH)
15412 	DUK_ASSERT((((duk_size_t) buf) & 0x01U) == 0);   /* pointer is aligned, guaranteed for fixed buffer */
15413 	p16 = (duk_uint16_t *) (void *) buf;
15414 	len_safe = len & ~0x03U;
15415 	for (i = 0; i < len_safe; i += 4) {
15416 		p16[0] = duk_hex_enctab[inp[i]];
15417 		p16[1] = duk_hex_enctab[inp[i + 1]];
15418 		p16[2] = duk_hex_enctab[inp[i + 2]];
15419 		p16[3] = duk_hex_enctab[inp[i + 3]];
15420 		p16 += 4;
15421 	}
15422 	for (; i < len; i++) {
15423 		*p16++ = duk_hex_enctab[inp[i]];
15424 	}
15425 #else  /* DUK_USE_HEX_FASTPATH */
15426 	for (i = 0; i < len; i++) {
15427 		duk_small_uint_t t;
15428 		t = (duk_small_uint_t) inp[i];
15429 		buf[i*2 + 0] = duk_lc_digits[t >> 4];
15430 		buf[i*2 + 1] = duk_lc_digits[t & 0x0f];
15431 	}
15432 #endif  /* DUK_USE_HEX_FASTPATH */
15433 
15434 	/* XXX: Using a string return value forces a string intern which is
15435 	 * not always necessary.  As a rough performance measure, hex encode
15436 	 * time for tests/perf/test-hex-encode.js dropped from ~35s to ~15s
15437 	 * without string coercion.  Change to returning a buffer and let the
15438 	 * caller coerce to string if necessary?
15439 	 */
15440 
15441 	ret = duk_buffer_to_string(thr, -1);  /* Safe, result is ASCII. */
15442 	duk_replace(thr, idx);
15443 	return ret;
15444 }
15445 
duk_hex_decode(duk_hthread * thr,duk_idx_t idx)15446 DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) {
15447 	const duk_uint8_t *inp;
15448 	duk_size_t len;
15449 	duk_size_t i;
15450 	duk_int_t t;
15451 	duk_uint8_t *buf;
15452 #if defined(DUK_USE_HEX_FASTPATH)
15453 	duk_int_t chk;
15454 	duk_uint8_t *p;
15455 	duk_size_t len_safe;
15456 #endif
15457 
15458 	DUK_ASSERT_API_ENTRY(thr);
15459 
15460 	idx = duk_require_normalize_index(thr, idx);
15461 	inp = duk__prep_codec_arg(thr, idx, &len);
15462 	DUK_ASSERT(inp != NULL);
15463 
15464 	if (len & 0x01) {
15465 		goto type_error;
15466 	}
15467 
15468 	/* Fixed buffer, no zeroing because we'll fill all the data. */
15469 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len / 2);
15470 	DUK_ASSERT(buf != NULL);
15471 
15472 #if defined(DUK_USE_HEX_FASTPATH)
15473 	p = buf;
15474 	len_safe = len & ~0x07U;
15475 	for (i = 0; i < len_safe; i += 8) {
15476 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i]]) |
15477 		    ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
15478 		chk = t;
15479 		p[0] = (duk_uint8_t) t;
15480 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 2]]) |
15481 		    ((duk_int_t) duk_hex_dectab[inp[i + 3]]);
15482 		chk |= t;
15483 		p[1] = (duk_uint8_t) t;
15484 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 4]]) |
15485 		    ((duk_int_t) duk_hex_dectab[inp[i + 5]]);
15486 		chk |= t;
15487 		p[2] = (duk_uint8_t) t;
15488 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 6]]) |
15489 		    ((duk_int_t) duk_hex_dectab[inp[i + 7]]);
15490 		chk |= t;
15491 		p[3] = (duk_uint8_t) t;
15492 		p += 4;
15493 
15494 		/* Check if any lookup above had a negative result. */
15495 		if (DUK_UNLIKELY(chk < 0)) {
15496 			goto type_error;
15497 		}
15498 	}
15499 	for (; i < len; i += 2) {
15500 		/* First cast to duk_int_t to sign extend, second cast to
15501 		 * duk_uint_t to avoid signed left shift, and final cast to
15502 		 * duk_int_t result type.
15503 		 */
15504 		t = (duk_int_t) ((((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i]]) << 4U) |
15505 		                 ((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i + 1]]));
15506 		if (DUK_UNLIKELY(t < 0)) {
15507 			goto type_error;
15508 		}
15509 		*p++ = (duk_uint8_t) t;
15510 	}
15511 #else  /* DUK_USE_HEX_FASTPATH */
15512 	for (i = 0; i < len; i += 2) {
15513 		/* For invalid characters the value -1 gets extended to
15514 		 * at least 16 bits.  If either nybble is invalid, the
15515 		 * resulting 't' will be < 0.
15516 		 */
15517 		t = (duk_int_t) ((((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i]]) << 4U) |
15518 		                 ((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i + 1]]));
15519 		if (DUK_UNLIKELY(t < 0)) {
15520 			goto type_error;
15521 		}
15522 		buf[i >> 1] = (duk_uint8_t) t;
15523 	}
15524 #endif  /* DUK_USE_HEX_FASTPATH */
15525 
15526 	duk_replace(thr, idx);
15527 	return;
15528 
15529  type_error:
15530 	DUK_ERROR_TYPE(thr, DUK_STR_HEX_DECODE_FAILED);
15531 	DUK_WO_NORETURN(return;);
15532 }
15533 #else  /* DUK_USE_HEX_SUPPORT */
duk_hex_encode(duk_hthread * thr,duk_idx_t idx)15534 DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
15535 	DUK_UNREF(idx);
15536 	DUK_ERROR_UNSUPPORTED(thr);
15537 	DUK_WO_NORETURN(return NULL;);
15538 }
duk_hex_decode(duk_hthread * thr,duk_idx_t idx)15539 DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) {
15540 	DUK_UNREF(idx);
15541 	DUK_ERROR_UNSUPPORTED(thr);
15542 	DUK_WO_NORETURN(return;);
15543 }
15544 #endif  /* DUK_USE_HEX_SUPPORT */
15545 
15546 /*
15547  *  JSON
15548  */
15549 
15550 #if defined(DUK_USE_JSON_SUPPORT)
duk_json_encode(duk_hthread * thr,duk_idx_t idx)15551 DUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) {
15552 #if defined(DUK_USE_ASSERTIONS)
15553 	duk_idx_t top_at_entry;
15554 #endif
15555 	const char *ret;
15556 
15557 	DUK_ASSERT_API_ENTRY(thr);
15558 #if defined(DUK_USE_ASSERTIONS)
15559 	top_at_entry = duk_get_top(thr);
15560 #endif
15561 
15562 	idx = duk_require_normalize_index(thr, idx);
15563 	duk_bi_json_stringify_helper(thr,
15564 	                             idx /*idx_value*/,
15565 	                             DUK_INVALID_INDEX /*idx_replacer*/,
15566 	                             DUK_INVALID_INDEX /*idx_space*/,
15567 	                             0 /*flags*/);
15568 	DUK_ASSERT(duk_is_string(thr, -1));
15569 	duk_replace(thr, idx);
15570 	ret = duk_get_string(thr, idx);
15571 
15572 	DUK_ASSERT(duk_get_top(thr) == top_at_entry);
15573 
15574 	return ret;
15575 }
15576 
duk_json_decode(duk_hthread * thr,duk_idx_t idx)15577 DUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx) {
15578 #if defined(DUK_USE_ASSERTIONS)
15579 	duk_idx_t top_at_entry;
15580 #endif
15581 
15582 	DUK_ASSERT_API_ENTRY(thr);
15583 #if defined(DUK_USE_ASSERTIONS)
15584 	top_at_entry = duk_get_top(thr);
15585 #endif
15586 
15587 	idx = duk_require_normalize_index(thr, idx);
15588 	duk_bi_json_parse_helper(thr,
15589 	                         idx /*idx_value*/,
15590 	                         DUK_INVALID_INDEX /*idx_reviver*/,
15591 	                         0 /*flags*/);
15592 	duk_replace(thr, idx);
15593 
15594 	DUK_ASSERT(duk_get_top(thr) == top_at_entry);
15595 }
15596 #else  /* DUK_USE_JSON_SUPPORT */
duk_json_encode(duk_hthread * thr,duk_idx_t idx)15597 DUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) {
15598 	DUK_ASSERT_API_ENTRY(thr);
15599 	DUK_UNREF(idx);
15600 	DUK_ERROR_UNSUPPORTED(thr);
15601 	DUK_WO_NORETURN(return NULL;);
15602 }
15603 
duk_json_decode(duk_hthread * thr,duk_idx_t idx)15604 DUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx) {
15605 	DUK_ASSERT_API_ENTRY(thr);
15606 	DUK_UNREF(idx);
15607 	DUK_ERROR_UNSUPPORTED(thr);
15608 	DUK_WO_NORETURN(return;);
15609 }
15610 #endif  /* DUK_USE_JSON_SUPPORT */
15611 /*
15612  *  Compilation and evaluation
15613  */
15614 
15615 /* #include duk_internal.h -> already included */
15616 
15617 typedef struct duk__compile_raw_args duk__compile_raw_args;
15618 struct duk__compile_raw_args {
15619 	duk_size_t src_length;  /* should be first on 64-bit platforms */
15620 	const duk_uint8_t *src_buffer;
15621 	duk_uint_t flags;
15622 };
15623 
15624 /* 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)15625 DUK_EXTERNAL duk_int_t duk_eval_raw(duk_hthread *thr, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
15626 	duk_int_t rc;
15627 
15628 	DUK_ASSERT_API_ENTRY(thr);
15629 
15630 	/* Note: strictness is *not* inherited from the current Duktape/C.
15631 	 * This would be confusing because the current strictness state
15632 	 * depends on whether we're running inside a Duktape/C activation
15633 	 * (= strict mode) or outside of any activation (= non-strict mode).
15634 	 * See tests/api/test-eval-strictness.c for more discussion.
15635 	 */
15636 
15637 	/* [ ... source? filename? ] (depends on flags) */
15638 
15639 	rc = duk_compile_raw(thr, src_buffer, src_length, flags | DUK_COMPILE_EVAL);  /* may be safe, or non-safe depending on flags */
15640 
15641 	/* [ ... closure/error ] */
15642 
15643 	if (rc != DUK_EXEC_SUCCESS) {
15644 		rc = DUK_EXEC_ERROR;
15645 		goto got_rc;
15646 	}
15647 
15648 	duk_push_global_object(thr);  /* explicit 'this' binding, see GH-164 */
15649 
15650 	if (flags & DUK_COMPILE_SAFE) {
15651 		rc = duk_pcall_method(thr, 0);
15652 	} else {
15653 		duk_call_method(thr, 0);
15654 		rc = DUK_EXEC_SUCCESS;
15655 	}
15656 
15657 	/* [ ... result/error ] */
15658 
15659  got_rc:
15660 	if (flags & DUK_COMPILE_NORESULT) {
15661 		duk_pop(thr);
15662 	}
15663 
15664 	return rc;
15665 }
15666 
15667 /* Helper which can be called both directly and with duk_safe_call(). */
duk__do_compile(duk_hthread * thr,void * udata)15668 DUK_LOCAL duk_ret_t duk__do_compile(duk_hthread *thr, void *udata) {
15669 	duk__compile_raw_args *comp_args;
15670 	duk_uint_t flags;
15671 	duk_hcompfunc *h_templ;
15672 
15673 	DUK_CTX_ASSERT_VALID(thr);
15674 	DUK_ASSERT(udata != NULL);
15675 
15676 	/* Note: strictness is not inherited from the current Duktape/C
15677 	 * context.  Otherwise it would not be possible to compile
15678 	 * non-strict code inside a Duktape/C activation (which is
15679 	 * always strict now).  See tests/api/test-eval-strictness.c
15680 	 * for discussion.
15681 	 */
15682 
15683 	/* [ ... source? filename? ] (depends on flags) */
15684 
15685 	comp_args = (duk__compile_raw_args *) udata;
15686 	flags = comp_args->flags;
15687 
15688 	if (flags & DUK_COMPILE_NOFILENAME) {
15689 		/* Automatic filename: 'eval' or 'input'. */
15690 		duk_push_hstring_stridx(thr, (flags & DUK_COMPILE_EVAL) ? DUK_STRIDX_EVAL : DUK_STRIDX_INPUT);
15691 	}
15692 
15693 	/* [ ... source? filename ] */
15694 
15695 	if (!comp_args->src_buffer) {
15696 		duk_hstring *h_sourcecode;
15697 
15698 		h_sourcecode = duk_get_hstring(thr, -2);
15699 		if ((flags & DUK_COMPILE_NOSOURCE) ||  /* args incorrect */
15700 		    (h_sourcecode == NULL)) {          /* e.g. duk_push_string_file_raw() pushed undefined */
15701 			DUK_ERROR_TYPE(thr, DUK_STR_NO_SOURCECODE);
15702 			DUK_WO_NORETURN(return 0;);
15703 		}
15704 		DUK_ASSERT(h_sourcecode != NULL);
15705 		comp_args->src_buffer = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode);
15706 		comp_args->src_length = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode);
15707 	}
15708 	DUK_ASSERT(comp_args->src_buffer != NULL);
15709 
15710 	if (flags & DUK_COMPILE_FUNCTION) {
15711 		flags |= DUK_COMPILE_EVAL | DUK_COMPILE_FUNCEXPR;
15712 	}
15713 
15714 	/* [ ... source? filename ] */
15715 
15716 	duk_js_compile(thr, comp_args->src_buffer, comp_args->src_length, flags);
15717 
15718 	/* [ ... source? func_template ] */
15719 
15720 	if (flags & DUK_COMPILE_NOSOURCE) {
15721 		;
15722 	} else {
15723 		duk_remove_m2(thr);
15724 	}
15725 
15726 	/* [ ... func_template ] */
15727 
15728 	h_templ = (duk_hcompfunc *) duk_known_hobject(thr, -1);
15729 	duk_js_push_closure(thr,
15730 	                   h_templ,
15731 	                   thr->builtins[DUK_BIDX_GLOBAL_ENV],
15732 	                   thr->builtins[DUK_BIDX_GLOBAL_ENV],
15733 	                   1 /*add_auto_proto*/);
15734 	duk_remove_m2(thr);   /* -> [ ... closure ] */
15735 
15736 	/* [ ... closure ] */
15737 
15738 	return 1;
15739 }
15740 
duk_compile_raw(duk_hthread * thr,const char * src_buffer,duk_size_t src_length,duk_uint_t flags)15741 DUK_EXTERNAL duk_int_t duk_compile_raw(duk_hthread *thr, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
15742 	duk__compile_raw_args comp_args_alloc;
15743 	duk__compile_raw_args *comp_args = &comp_args_alloc;
15744 
15745 	DUK_ASSERT_API_ENTRY(thr);
15746 
15747 	if ((flags & DUK_COMPILE_STRLEN) && (src_buffer != NULL)) {
15748 		/* String length is computed here to avoid multiple evaluation
15749 		 * of a macro argument in the calling side.
15750 		 */
15751 		src_length = DUK_STRLEN(src_buffer);
15752 	}
15753 
15754 	comp_args->src_buffer = (const duk_uint8_t *) src_buffer;
15755 	comp_args->src_length = src_length;
15756 	comp_args->flags = flags;
15757 
15758 	/* [ ... source? filename? ] (depends on flags) */
15759 
15760 	if (flags & DUK_COMPILE_SAFE) {
15761 		duk_int_t rc;
15762 		duk_int_t nargs;
15763 		duk_int_t nrets = 1;
15764 
15765 		/* Arguments can be: [ source? filename? &comp_args] so that
15766 		 * nargs is 1 to 3.  Call site encodes the correct nargs count
15767 		 * directly into flags.
15768 		 */
15769 		nargs = flags & 0x07;
15770 		DUK_ASSERT(nargs == ((flags & DUK_COMPILE_NOSOURCE) ? 0 : 1) +
15771 		                    ((flags & DUK_COMPILE_NOFILENAME) ? 0 : 1));
15772 		rc = duk_safe_call(thr, duk__do_compile, (void *) comp_args, nargs, nrets);
15773 
15774 		/* [ ... closure ] */
15775 		return rc;
15776 	}
15777 
15778 	(void) duk__do_compile(thr, (void *) comp_args);
15779 
15780 	/* [ ... closure ] */
15781 	return DUK_EXEC_SUCCESS;
15782 }
15783 /*
15784  *  Debugging related API calls
15785  */
15786 
15787 /* #include duk_internal.h -> already included */
15788 
15789 #if defined(DUK_USE_JSON_SUPPORT)
duk_push_context_dump(duk_hthread * thr)15790 DUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) {
15791 	duk_idx_t idx;
15792 	duk_idx_t top;
15793 
15794 	DUK_ASSERT_API_ENTRY(thr);
15795 
15796 	/* We don't duk_require_stack() here now, but rely on the caller having
15797 	 * enough space.
15798 	 */
15799 
15800 	top = duk_get_top(thr);
15801 	duk_push_bare_array(thr);
15802 	for (idx = 0; idx < top; idx++) {
15803 		duk_dup(thr, idx);
15804 		duk_put_prop_index(thr, -2, (duk_uarridx_t) idx);
15805 	}
15806 
15807 	/* XXX: conversion errors should not propagate outwards.
15808 	 * Perhaps values need to be coerced individually?
15809 	 */
15810 	duk_bi_json_stringify_helper(thr,
15811 	                             duk_get_top_index(thr),  /*idx_value*/
15812 	                             DUK_INVALID_INDEX,  /*idx_replacer*/
15813 	                             DUK_INVALID_INDEX,  /*idx_space*/
15814 	                             DUK_JSON_FLAG_EXT_CUSTOM |
15815 	                             DUK_JSON_FLAG_ASCII_ONLY |
15816 	                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
15817 
15818 	duk_push_sprintf(thr, "ctx: top=%ld, stack=%s", (long) top, (const char *) duk_safe_to_string(thr, -1));
15819 	duk_replace(thr, -3);  /* [ ... arr jsonx(arr) res ] -> [ ... res jsonx(arr) ] */
15820 	duk_pop(thr);
15821 	DUK_ASSERT(duk_is_string(thr, -1));
15822 }
15823 #else  /* DUK_USE_JSON_SUPPORT */
duk_push_context_dump(duk_hthread * thr)15824 DUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) {
15825 	DUK_ASSERT_API_ENTRY(thr);
15826 	DUK_ERROR_UNSUPPORTED(thr);
15827 	DUK_WO_NORETURN(return;);
15828 }
15829 #endif  /* DUK_USE_JSON_SUPPORT */
15830 
15831 #if defined(DUK_USE_DEBUGGER_SUPPORT)
15832 
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)15833 DUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr,
15834                                       duk_debug_read_function read_cb,
15835                                       duk_debug_write_function write_cb,
15836                                       duk_debug_peek_function peek_cb,
15837                                       duk_debug_read_flush_function read_flush_cb,
15838                                       duk_debug_write_flush_function write_flush_cb,
15839                                       duk_debug_request_function request_cb,
15840                                       duk_debug_detached_function detached_cb,
15841                                       void *udata) {
15842 	duk_heap *heap;
15843 	const char *str;
15844 	duk_size_t len;
15845 
15846 	/* XXX: should there be an error or an automatic detach if
15847 	 * already attached?
15848 	 */
15849 
15850 	DUK_D(DUK_DPRINT("application called duk_debugger_attach()"));
15851 
15852 	DUK_ASSERT_API_ENTRY(thr);
15853 	DUK_ASSERT(read_cb != NULL);
15854 	DUK_ASSERT(write_cb != NULL);
15855 	/* Other callbacks are optional. */
15856 
15857 	heap = thr->heap;
15858 	heap->dbg_read_cb = read_cb;
15859 	heap->dbg_write_cb = write_cb;
15860 	heap->dbg_peek_cb = peek_cb;
15861 	heap->dbg_read_flush_cb = read_flush_cb;
15862 	heap->dbg_write_flush_cb = write_flush_cb;
15863 	heap->dbg_request_cb = request_cb;
15864 	heap->dbg_detached_cb = detached_cb;
15865 	heap->dbg_udata = udata;
15866 	heap->dbg_have_next_byte = 0;
15867 
15868 	/* Start in paused state. */
15869 	heap->dbg_processing = 0;
15870 	heap->dbg_state_dirty = 0;
15871 	heap->dbg_force_restart = 0;
15872 	heap->dbg_pause_flags = 0;
15873 	heap->dbg_pause_act = NULL;
15874 	heap->dbg_pause_startline = 0;
15875 	heap->dbg_exec_counter = 0;
15876 	heap->dbg_last_counter = 0;
15877 	heap->dbg_last_time = 0.0;
15878 	duk_debug_set_paused(heap);  /* XXX: overlap with fields above */
15879 
15880 	/* Send version identification and flush right afterwards.  Note that
15881 	 * we must write raw, unframed bytes here.
15882 	 */
15883 	duk_push_sprintf(thr, "%ld %ld %s %s\n",
15884 	                 (long) DUK_DEBUG_PROTOCOL_VERSION,
15885 	                 (long) DUK_VERSION,
15886 	                 (const char *) DUK_GIT_DESCRIBE,
15887 	                 (const char *) DUK_USE_TARGET_INFO);
15888 	str = duk_get_lstring(thr, -1, &len);
15889 	DUK_ASSERT(str != NULL);
15890 	duk_debug_write_bytes(thr, (const duk_uint8_t *) str, len);
15891 	duk_debug_write_flush(thr);
15892 	duk_pop(thr);
15893 }
15894 
duk_debugger_detach(duk_hthread * thr)15895 DUK_EXTERNAL void duk_debugger_detach(duk_hthread *thr) {
15896 	DUK_D(DUK_DPRINT("application called duk_debugger_detach()"));
15897 
15898 	DUK_ASSERT_API_ENTRY(thr);
15899 	DUK_ASSERT(thr->heap != NULL);
15900 
15901 	/* Can be called multiple times with no harm. */
15902 	duk_debug_do_detach(thr->heap);
15903 }
15904 
duk_debugger_cooperate(duk_hthread * thr)15905 DUK_EXTERNAL void duk_debugger_cooperate(duk_hthread *thr) {
15906 	duk_bool_t processed_messages;
15907 
15908 	DUK_ASSERT_API_ENTRY(thr);
15909 	DUK_ASSERT(thr->heap != NULL);
15910 
15911 	if (!duk_debug_is_attached(thr->heap)) {
15912 		return;
15913 	}
15914 	if (thr->callstack_curr != NULL || thr->heap->dbg_processing) {
15915 		/* Calling duk_debugger_cooperate() while Duktape is being
15916 		 * called into is not supported.  This is not a 100% check
15917 		 * but prevents any damage in most cases.
15918 		 */
15919 		return;
15920 	}
15921 
15922 	processed_messages = duk_debug_process_messages(thr, 1 /*no_block*/);
15923 	DUK_UNREF(processed_messages);
15924 }
15925 
duk_debugger_notify(duk_hthread * thr,duk_idx_t nvalues)15926 DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues) {
15927 	duk_idx_t top;
15928 	duk_idx_t idx;
15929 	duk_bool_t ret = 0;
15930 
15931 	DUK_ASSERT_API_ENTRY(thr);
15932 	DUK_ASSERT(thr->heap != NULL);
15933 
15934 	DUK_D(DUK_DPRINT("application called duk_debugger_notify() with nvalues=%ld", (long) nvalues));
15935 
15936 	top = duk_get_top(thr);
15937 	if (top < nvalues) {
15938 		DUK_ERROR_RANGE(thr, "not enough stack values for notify");
15939 		DUK_WO_NORETURN(return 0;);
15940 	}
15941 	if (duk_debug_is_attached(thr->heap)) {
15942 		duk_debug_write_notify(thr, DUK_DBG_CMD_APPNOTIFY);
15943 		for (idx = top - nvalues; idx < top; idx++) {
15944 			duk_tval *tv = DUK_GET_TVAL_POSIDX(thr, idx);
15945 			duk_debug_write_tval(thr, tv);
15946 		}
15947 		duk_debug_write_eom(thr);
15948 
15949 		/* Return non-zero (true) if we have a good reason to believe
15950 		 * the notify was delivered; if we're still attached at least
15951 		 * a transport error was not indicated by the transport write
15952 		 * callback.  This is not a 100% guarantee of course.
15953 		 */
15954 		if (duk_debug_is_attached(thr->heap)) {
15955 			ret = 1;
15956 		}
15957 	}
15958 	duk_pop_n(thr, nvalues);
15959 	return ret;
15960 }
15961 
duk_debugger_pause(duk_hthread * thr)15962 DUK_EXTERNAL void duk_debugger_pause(duk_hthread *thr) {
15963 	DUK_ASSERT_API_ENTRY(thr);
15964 	DUK_ASSERT(thr->heap != NULL);
15965 
15966 	DUK_D(DUK_DPRINT("application called duk_debugger_pause()"));
15967 
15968 	/* Treat like a debugger statement: ignore when not attached. */
15969 	if (duk_debug_is_attached(thr->heap)) {
15970 		if (duk_debug_is_paused(thr->heap)) {
15971 			DUK_D(DUK_DPRINT("duk_debugger_pause() called when already paused; ignoring"));
15972 		} else {
15973 			duk_debug_set_paused(thr->heap);
15974 
15975 			/* Pause on the next opcode executed.  This is always safe to do even
15976 			 * inside the debugger message loop: the interrupt counter will be reset
15977 			 * to its proper value when the message loop exits.
15978 			 */
15979 			thr->interrupt_init = 1;
15980 			thr->interrupt_counter = 0;
15981 		}
15982 	}
15983 }
15984 
15985 #else  /* DUK_USE_DEBUGGER_SUPPORT */
15986 
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)15987 DUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr,
15988                                       duk_debug_read_function read_cb,
15989                                       duk_debug_write_function write_cb,
15990                                       duk_debug_peek_function peek_cb,
15991                                       duk_debug_read_flush_function read_flush_cb,
15992                                       duk_debug_write_flush_function write_flush_cb,
15993                                       duk_debug_request_function request_cb,
15994                                       duk_debug_detached_function detached_cb,
15995                                       void *udata) {
15996 	DUK_ASSERT_API_ENTRY(thr);
15997 	DUK_UNREF(read_cb);
15998 	DUK_UNREF(write_cb);
15999 	DUK_UNREF(peek_cb);
16000 	DUK_UNREF(read_flush_cb);
16001 	DUK_UNREF(write_flush_cb);
16002 	DUK_UNREF(request_cb);
16003 	DUK_UNREF(detached_cb);
16004 	DUK_UNREF(udata);
16005 	DUK_ERROR_TYPE(thr, "no debugger support");
16006 	DUK_WO_NORETURN(return;);
16007 }
16008 
duk_debugger_detach(duk_hthread * thr)16009 DUK_EXTERNAL void duk_debugger_detach(duk_hthread *thr) {
16010 	DUK_ASSERT_API_ENTRY(thr);
16011 	DUK_ERROR_TYPE(thr, "no debugger support");
16012 	DUK_WO_NORETURN(return;);
16013 }
16014 
duk_debugger_cooperate(duk_hthread * thr)16015 DUK_EXTERNAL void duk_debugger_cooperate(duk_hthread *thr) {
16016 	/* nop */
16017 	DUK_ASSERT_API_ENTRY(thr);
16018 	DUK_UNREF(thr);
16019 }
16020 
duk_debugger_notify(duk_hthread * thr,duk_idx_t nvalues)16021 DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues) {
16022 	duk_idx_t top;
16023 
16024 	DUK_ASSERT_API_ENTRY(thr);
16025 
16026 	top = duk_get_top(thr);
16027 	if (top < nvalues) {
16028 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
16029 		DUK_WO_NORETURN(return 0;);
16030 	}
16031 
16032 	/* No debugger support, just pop values. */
16033 	duk_pop_n(thr, nvalues);
16034 	return 0;
16035 }
16036 
duk_debugger_pause(duk_hthread * thr)16037 DUK_EXTERNAL void duk_debugger_pause(duk_hthread *thr) {
16038 	/* Treat like debugger statement: nop */
16039 	DUK_ASSERT_API_ENTRY(thr);
16040 	DUK_UNREF(thr);
16041 }
16042 
16043 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
16044 /*
16045  *  Heap creation and destruction
16046  */
16047 
16048 /* #include duk_internal.h -> already included */
16049 
16050 typedef struct duk_internal_thread_state duk_internal_thread_state;
16051 
16052 struct duk_internal_thread_state {
16053 	duk_ljstate lj;
16054 	duk_bool_t creating_error;
16055 	duk_hthread *curr_thread;
16056 	duk_int_t call_recursion_depth;
16057 };
16058 
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)16059 DUK_EXTERNAL duk_hthread *duk_create_heap(duk_alloc_function alloc_func,
16060                                           duk_realloc_function realloc_func,
16061                                           duk_free_function free_func,
16062                                           void *heap_udata,
16063                                           duk_fatal_function fatal_handler) {
16064 	duk_heap *heap = NULL;
16065 	duk_hthread *thr;
16066 
16067 	/* Assume that either all memory funcs are NULL or non-NULL, mixed
16068 	 * cases will now be unsafe.
16069 	 */
16070 
16071 	/* XXX: just assert non-NULL values here and make caller arguments
16072 	 * do the defaulting to the default implementations (smaller code)?
16073 	 */
16074 
16075 	if (!alloc_func) {
16076 		DUK_ASSERT(realloc_func == NULL);
16077 		DUK_ASSERT(free_func == NULL);
16078 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
16079 		alloc_func = duk_default_alloc_function;
16080 		realloc_func = duk_default_realloc_function;
16081 		free_func = duk_default_free_function;
16082 #else
16083 		DUK_D(DUK_DPRINT("no allocation functions given and no default providers"));
16084 		return NULL;
16085 #endif
16086 	} else {
16087 		DUK_ASSERT(realloc_func != NULL);
16088 		DUK_ASSERT(free_func != NULL);
16089 	}
16090 
16091 	if (!fatal_handler) {
16092 		fatal_handler = duk_default_fatal_handler;
16093 	}
16094 
16095 	DUK_ASSERT(alloc_func != NULL);
16096 	DUK_ASSERT(realloc_func != NULL);
16097 	DUK_ASSERT(free_func != NULL);
16098 	DUK_ASSERT(fatal_handler != NULL);
16099 
16100 	heap = duk_heap_alloc(alloc_func, realloc_func, free_func, heap_udata, fatal_handler);
16101 	if (!heap) {
16102 		return NULL;
16103 	}
16104 	thr = heap->heap_thread;
16105 	DUK_ASSERT(thr != NULL);
16106 	DUK_ASSERT(thr->heap != NULL);
16107 	return thr;
16108 }
16109 
duk_destroy_heap(duk_hthread * thr)16110 DUK_EXTERNAL void duk_destroy_heap(duk_hthread *thr) {
16111 	duk_heap *heap;
16112 
16113 	if (!thr) {
16114 		return;
16115 	}
16116 	DUK_ASSERT_API_ENTRY(thr);
16117 	heap = thr->heap;
16118 	DUK_ASSERT(heap != NULL);
16119 
16120 	duk_heap_free(heap);
16121 }
16122 
duk_suspend(duk_hthread * thr,duk_thread_state * state)16123 DUK_EXTERNAL void duk_suspend(duk_hthread *thr, duk_thread_state *state) {
16124 	duk_internal_thread_state *snapshot = (duk_internal_thread_state *) (void *) state;
16125 	duk_heap *heap;
16126 	duk_ljstate *lj;
16127 
16128 	DUK_ASSERT_API_ENTRY(thr);
16129 	DUK_ASSERT(thr->heap != NULL);
16130 	DUK_ASSERT(state != NULL);  /* unvalidated */
16131 
16132 	/* Currently not supported when called from within a finalizer.
16133 	 * If that is done, the finalizer will remain running indefinitely,
16134 	 * preventing other finalizers from executing.  The assert is a bit
16135 	 * wider, checking that it would be OK to run pending finalizers.
16136 	 */
16137 	DUK_ASSERT(thr->heap->pf_prevent_count == 0);
16138 
16139 	/* Currently not supported to duk_suspend() from an errCreate()
16140 	 * call.
16141 	 */
16142 	DUK_ASSERT(thr->heap->creating_error == 0);
16143 
16144 	heap = thr->heap;
16145 	lj = &heap->lj;
16146 
16147 	duk_push_tval(thr, &lj->value1);
16148 	duk_push_tval(thr, &lj->value2);
16149 
16150 	/* XXX: creating_error == 0 is asserted above, so no need to store. */
16151 	duk_memcpy((void *) &snapshot->lj, (const void *) lj, sizeof(duk_ljstate));
16152 	snapshot->creating_error = heap->creating_error;
16153 	snapshot->curr_thread = heap->curr_thread;
16154 	snapshot->call_recursion_depth = heap->call_recursion_depth;
16155 
16156 	lj->jmpbuf_ptr = NULL;
16157 	lj->type = DUK_LJ_TYPE_UNKNOWN;
16158 	DUK_TVAL_SET_UNDEFINED(&lj->value1);
16159 	DUK_TVAL_SET_UNDEFINED(&lj->value2);
16160 	heap->creating_error = 0;
16161 	heap->curr_thread = NULL;
16162 	heap->call_recursion_depth = 0;
16163 }
16164 
duk_resume(duk_hthread * thr,const duk_thread_state * state)16165 DUK_EXTERNAL void duk_resume(duk_hthread *thr, const duk_thread_state *state) {
16166 	const duk_internal_thread_state *snapshot = (const duk_internal_thread_state *) (const void *) state;
16167 	duk_heap *heap;
16168 
16169 	DUK_ASSERT_API_ENTRY(thr);
16170 	DUK_ASSERT(thr->heap != NULL);
16171 	DUK_ASSERT(state != NULL);  /* unvalidated */
16172 
16173 	/* Shouldn't be necessary if duk_suspend() is called before
16174 	 * duk_resume(), but assert in case API sequence is incorrect.
16175 	 */
16176 	DUK_ASSERT(thr->heap->pf_prevent_count == 0);
16177 	DUK_ASSERT(thr->heap->creating_error == 0);
16178 
16179 	heap = thr->heap;
16180 
16181 	duk_memcpy((void *) &heap->lj, (const void *) &snapshot->lj, sizeof(duk_ljstate));
16182 	heap->creating_error = snapshot->creating_error;
16183 	heap->curr_thread = snapshot->curr_thread;
16184 	heap->call_recursion_depth = snapshot->call_recursion_depth;
16185 
16186 	duk_pop_2(thr);
16187 }
16188 
16189 /* XXX: better place for this */
duk_set_global_object(duk_hthread * thr)16190 DUK_EXTERNAL void duk_set_global_object(duk_hthread *thr) {
16191 	duk_hobject *h_glob;
16192 	duk_hobject *h_prev_glob;
16193 	duk_hobjenv *h_env;
16194 	duk_hobject *h_prev_env;
16195 
16196 	DUK_ASSERT_API_ENTRY(thr);
16197 
16198 	DUK_D(DUK_DPRINT("replace global object with: %!T", duk_get_tval(thr, -1)));
16199 
16200 	h_glob = duk_require_hobject(thr, -1);
16201 	DUK_ASSERT(h_glob != NULL);
16202 
16203 	/*
16204 	 *  Replace global object.
16205 	 */
16206 
16207 	h_prev_glob = thr->builtins[DUK_BIDX_GLOBAL];
16208 	DUK_UNREF(h_prev_glob);
16209 	thr->builtins[DUK_BIDX_GLOBAL] = h_glob;
16210 	DUK_HOBJECT_INCREF(thr, h_glob);
16211 	DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_glob);  /* side effects, in theory (referenced by global env) */
16212 
16213 	/*
16214 	 *  Replace lexical environment for global scope
16215 	 *
16216 	 *  Create a new object environment for the global lexical scope.
16217 	 *  We can't just reset the _Target property of the current one,
16218 	 *  because the lexical scope is shared by other threads with the
16219 	 *  same (initial) built-ins.
16220 	 */
16221 
16222 	h_env = duk_hobjenv_alloc(thr,
16223 	                          DUK_HOBJECT_FLAG_EXTENSIBLE |
16224 	                          DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
16225 	DUK_ASSERT(h_env != NULL);
16226 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_env) == NULL);
16227 
16228 	DUK_ASSERT(h_env->target == NULL);
16229 	DUK_ASSERT(h_glob != NULL);
16230 	h_env->target = h_glob;
16231 	DUK_HOBJECT_INCREF(thr, h_glob);
16232 	DUK_ASSERT(h_env->has_this == 0);
16233 
16234 	/* [ ... new_glob ] */
16235 
16236 	h_prev_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
16237 	thr->builtins[DUK_BIDX_GLOBAL_ENV] = (duk_hobject *) h_env;
16238 	DUK_HOBJECT_INCREF(thr, (duk_hobject *) h_env);
16239 	DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_env);  /* side effects */
16240 	DUK_UNREF(h_env);  /* without refcounts */
16241 	DUK_UNREF(h_prev_env);
16242 
16243 	/* [ ... new_glob ] */
16244 
16245 	duk_pop(thr);
16246 
16247 	/* [ ... ] */
16248 }
16249 /*
16250  *  Inspection
16251  */
16252 
16253 /* #include duk_internal.h -> already included */
16254 
16255 /* For footprint efficient multiple value setting: arrays are much better than
16256  * varargs, format string with parsing is often better than string pointer arrays.
16257  */
duk__inspect_multiple_uint(duk_hthread * thr,const char * fmt,duk_int_t * vals)16258 DUK_LOCAL void duk__inspect_multiple_uint(duk_hthread *thr, const char *fmt, duk_int_t *vals) {
16259 	duk_int_t val;
16260 	const char *p;
16261 	const char *p_curr;
16262 	duk_size_t len;
16263 
16264 	for (p = fmt;;) {
16265 		len = DUK_STRLEN(p);
16266 		p_curr = p;
16267 		p += len + 1;
16268 		if (len == 0) {
16269 			/* Double NUL (= empty key) terminates. */
16270 			break;
16271 		}
16272 		val = *vals++;
16273 		if (val >= 0) {
16274 			/* Negative values are markers to skip key. */
16275 			duk_push_string(thr, p_curr);
16276 			duk_push_int(thr, val);
16277 			duk_put_prop(thr, -3);
16278 		}
16279 	}
16280 }
16281 
16282 /* Raw helper to extract internal information / statistics about a value.
16283  * The return value is an object with properties that are version specific.
16284  * The properties must not expose anything that would lead to security
16285  * issues (e.g. exposing compiled function 'data' buffer might be an issue).
16286  * Currently only counts and sizes and such are given so there shouldn't
16287  * be security implications.
16288  */
16289 
16290 #define DUK__IDX_TYPE     0
16291 #define DUK__IDX_ITAG     1
16292 #define DUK__IDX_REFC     2
16293 #define DUK__IDX_HBYTES   3
16294 #define DUK__IDX_CLASS    4
16295 #define DUK__IDX_PBYTES   5
16296 #define DUK__IDX_ESIZE    6
16297 #define DUK__IDX_ENEXT    7
16298 #define DUK__IDX_ASIZE    8
16299 #define DUK__IDX_HSIZE    9
16300 #define DUK__IDX_BCBYTES  10
16301 #define DUK__IDX_DBYTES   11
16302 #define DUK__IDX_TSTATE   12
16303 #define DUK__IDX_VARIANT  13
16304 
duk_inspect_value(duk_hthread * thr,duk_idx_t idx)16305 DUK_EXTERNAL void duk_inspect_value(duk_hthread *thr, duk_idx_t idx) {
16306 	duk_tval *tv;
16307 	duk_heaphdr *h;
16308 	/* The temporary values should be in an array rather than individual
16309 	 * variables which (in practice) ensures that the compiler won't map
16310 	 * them to registers and emit a lot of unnecessary shuffling code.
16311 	 */
16312 	duk_int_t vals[14];
16313 
16314 	DUK_ASSERT_API_ENTRY(thr);
16315 
16316 	/* Assume two's complement and set everything to -1. */
16317 	duk_memset((void *) &vals, (int) 0xff, sizeof(vals));
16318 	DUK_ASSERT(vals[DUK__IDX_TYPE] == -1);  /* spot check one */
16319 
16320 	tv = duk_get_tval_or_unused(thr, idx);
16321 	h = (DUK_TVAL_IS_HEAP_ALLOCATED(tv) ? DUK_TVAL_GET_HEAPHDR(tv) : NULL);
16322 
16323 	vals[DUK__IDX_TYPE] = duk_get_type_tval(tv);
16324 	vals[DUK__IDX_ITAG] = (duk_int_t) DUK_TVAL_GET_TAG(tv);
16325 
16326 	duk_push_bare_object(thr);  /* Invalidates 'tv'. */
16327 	tv = NULL;
16328 
16329 	if (h == NULL) {
16330 		goto finish;
16331 	}
16332 	duk_push_pointer(thr, (void *) h);
16333 	duk_put_prop_literal(thr, -2, "hptr");
16334 
16335 #if 0
16336 	/* Covers a lot of information, e.g. buffer and string variants. */
16337 	duk_push_uint(thr, (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
16338 	duk_put_prop_literal(thr, -2, "hflags");
16339 #endif
16340 
16341 #if defined(DUK_USE_REFERENCE_COUNTING)
16342 	vals[DUK__IDX_REFC] = (duk_int_t) DUK_HEAPHDR_GET_REFCOUNT(h);
16343 #endif
16344 	vals[DUK__IDX_VARIANT] = 0;
16345 
16346 	/* Heaphdr size and additional allocation size, followed by
16347 	 * type specific stuff (with varying value count).
16348 	 */
16349 	switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) {
16350 	case DUK_HTYPE_STRING: {
16351 		duk_hstring *h_str = (duk_hstring *) h;
16352 		vals[DUK__IDX_HBYTES] = (duk_int_t) (sizeof(duk_hstring) + DUK_HSTRING_GET_BYTELEN(h_str) + 1);
16353 #if defined(DUK_USE_HSTRING_EXTDATA)
16354 		if (DUK_HSTRING_HAS_EXTDATA(h_str)) {
16355 			vals[DUK__IDX_VARIANT] = 1;
16356 		}
16357 #endif
16358 		break;
16359 	}
16360 	case DUK_HTYPE_OBJECT: {
16361 		duk_hobject *h_obj = (duk_hobject *) h;
16362 
16363 		/* XXX: variants here are maybe pointless; class is enough? */
16364 		if (DUK_HOBJECT_IS_ARRAY(h_obj)) {
16365 			vals[DUK__IDX_HBYTES] = sizeof(duk_harray);
16366 		} else if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
16367 			vals[DUK__IDX_HBYTES] = sizeof(duk_hcompfunc);
16368 		} else if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
16369 			vals[DUK__IDX_HBYTES] = sizeof(duk_hnatfunc);
16370 		} else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
16371 			vals[DUK__IDX_HBYTES] = sizeof(duk_hthread);
16372 			vals[DUK__IDX_TSTATE] = ((duk_hthread *) h_obj)->state;
16373 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
16374 		} else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
16375 			vals[DUK__IDX_HBYTES] = sizeof(duk_hbufobj);
16376 			/* XXX: some size information */
16377 #endif
16378 		} else {
16379 			vals[DUK__IDX_HBYTES] = (duk_small_uint_t) sizeof(duk_hobject);
16380 		}
16381 
16382 		vals[DUK__IDX_CLASS] = (duk_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
16383 		vals[DUK__IDX_PBYTES] = (duk_int_t) DUK_HOBJECT_P_ALLOC_SIZE(h_obj);
16384 		vals[DUK__IDX_ESIZE] = (duk_int_t) DUK_HOBJECT_GET_ESIZE(h_obj);
16385 		vals[DUK__IDX_ENEXT] = (duk_int_t) DUK_HOBJECT_GET_ENEXT(h_obj);
16386 		vals[DUK__IDX_ASIZE] = (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj);
16387 		vals[DUK__IDX_HSIZE] = (duk_int_t) DUK_HOBJECT_GET_HSIZE(h_obj);
16388 
16389 		/* Note: e_next indicates the number of gc-reachable entries
16390 		 * in the entry part, and also indicates the index where the
16391 		 * next new property would be inserted.  It does *not* indicate
16392 		 * the number of non-NULL keys present in the object.  That
16393 		 * value could be counted separately but requires a pass through
16394 		 * the key list.
16395 		 */
16396 
16397 		if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
16398 			duk_hbuffer *h_data = (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, (duk_hcompfunc *) h_obj);
16399 			vals[DUK__IDX_BCBYTES] = (duk_int_t) (h_data ? DUK_HBUFFER_GET_SIZE(h_data) : 0);
16400 		}
16401 		break;
16402 	}
16403 	case DUK_HTYPE_BUFFER: {
16404 		duk_hbuffer *h_buf = (duk_hbuffer *) h;
16405 
16406 		if (DUK_HBUFFER_HAS_DYNAMIC(h_buf)) {
16407 			if (DUK_HBUFFER_HAS_EXTERNAL(h_buf)) {
16408 				vals[DUK__IDX_VARIANT] = 2;  /* buffer variant 2: external */
16409 				vals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_external));
16410 			} else {
16411 				/* When alloc_size == 0 the second allocation may not
16412 				 * actually exist.
16413 				 */
16414 				vals[DUK__IDX_VARIANT] = 1;  /* buffer variant 1: dynamic */
16415 				vals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_dynamic));
16416 			}
16417 			vals[DUK__IDX_DBYTES] = (duk_int_t) (DUK_HBUFFER_GET_SIZE(h_buf));
16418 		} else {
16419 			DUK_ASSERT(vals[DUK__IDX_VARIANT] == 0);  /* buffer variant 0: fixed */
16420 			vals[DUK__IDX_HBYTES] = (duk_int_t) (sizeof(duk_hbuffer_fixed) + DUK_HBUFFER_GET_SIZE(h_buf));
16421 		}
16422 		break;
16423 	}
16424 	}
16425 
16426  finish:
16427 	duk__inspect_multiple_uint(thr,
16428 	    "type" "\x00" "itag" "\x00" "refc" "\x00" "hbytes" "\x00" "class" "\x00"
16429 	    "pbytes" "\x00" "esize" "\x00" "enext" "\x00" "asize" "\x00" "hsize" "\x00"
16430 	    "bcbytes" "\x00" "dbytes" "\x00" "tstate" "\x00" "variant" "\x00" "\x00",
16431 	    (duk_int_t *) &vals);
16432 }
16433 
duk_inspect_callstack_entry(duk_hthread * thr,duk_int_t level)16434 DUK_EXTERNAL void duk_inspect_callstack_entry(duk_hthread *thr, duk_int_t level) {
16435 	duk_activation *act;
16436 	duk_uint_fast32_t pc;
16437 	duk_uint_fast32_t line;
16438 
16439 	DUK_ASSERT_API_ENTRY(thr);
16440 
16441 	/* -1   = top callstack entry
16442 	 * -2   = caller of level -1
16443 	 * etc
16444 	 */
16445 	act = duk_hthread_get_activation_for_level(thr, level);
16446 	if (act == NULL) {
16447 		duk_push_undefined(thr);
16448 		return;
16449 	}
16450 	duk_push_bare_object(thr);
16451 
16452 	/* Relevant PC is just before current one because PC is
16453 	 * post-incremented.  This should match what error augment
16454 	 * code does.
16455 	 */
16456 	pc = duk_hthread_get_act_prev_pc(thr, act);
16457 
16458 	duk_push_tval(thr, &act->tv_func);
16459 
16460 	duk_push_uint(thr, (duk_uint_t) pc);
16461 	duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_PC);
16462 
16463 #if defined(DUK_USE_PC2LINE)
16464 	line = duk_hobject_pc2line_query(thr, -1, pc);
16465 #else
16466 	line = 0;
16467 #endif
16468 	duk_push_uint(thr, (duk_uint_t) line);
16469 	duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_LINE_NUMBER);
16470 
16471 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_LC_FUNCTION);
16472 	/* Providing access to e.g. act->lex_env would be dangerous: these
16473 	 * internal structures must never be accessible to the application.
16474 	 * Duktape relies on them having consistent data, and this consistency
16475 	 * is only asserted for, not checked for.
16476 	 */
16477 }
16478 
16479 /* automatic undefs */
16480 #undef DUK__IDX_ASIZE
16481 #undef DUK__IDX_BCBYTES
16482 #undef DUK__IDX_CLASS
16483 #undef DUK__IDX_DBYTES
16484 #undef DUK__IDX_ENEXT
16485 #undef DUK__IDX_ESIZE
16486 #undef DUK__IDX_HBYTES
16487 #undef DUK__IDX_HSIZE
16488 #undef DUK__IDX_ITAG
16489 #undef DUK__IDX_PBYTES
16490 #undef DUK__IDX_REFC
16491 #undef DUK__IDX_TSTATE
16492 #undef DUK__IDX_TYPE
16493 #undef DUK__IDX_VARIANT
16494 /*
16495  *  Memory calls.
16496  */
16497 
16498 /* #include duk_internal.h -> already included */
16499 
duk_alloc_raw(duk_hthread * thr,duk_size_t size)16500 DUK_EXTERNAL void *duk_alloc_raw(duk_hthread *thr, duk_size_t size) {
16501 	DUK_ASSERT_API_ENTRY(thr);
16502 
16503 	return DUK_ALLOC_RAW(thr->heap, size);
16504 }
16505 
duk_free_raw(duk_hthread * thr,void * ptr)16506 DUK_EXTERNAL void duk_free_raw(duk_hthread *thr, void *ptr) {
16507 	DUK_ASSERT_API_ENTRY(thr);
16508 
16509 	DUK_FREE_RAW(thr->heap, ptr);
16510 }
16511 
duk_realloc_raw(duk_hthread * thr,void * ptr,duk_size_t size)16512 DUK_EXTERNAL void *duk_realloc_raw(duk_hthread *thr, void *ptr, duk_size_t size) {
16513 	DUK_ASSERT_API_ENTRY(thr);
16514 
16515 	return DUK_REALLOC_RAW(thr->heap, ptr, size);
16516 }
16517 
duk_alloc(duk_hthread * thr,duk_size_t size)16518 DUK_EXTERNAL void *duk_alloc(duk_hthread *thr, duk_size_t size) {
16519 	DUK_ASSERT_API_ENTRY(thr);
16520 
16521 	return DUK_ALLOC(thr->heap, size);
16522 }
16523 
duk_free(duk_hthread * thr,void * ptr)16524 DUK_EXTERNAL void duk_free(duk_hthread *thr, void *ptr) {
16525 	DUK_ASSERT_API_ENTRY(thr);
16526 
16527 	DUK_FREE_CHECKED(thr, ptr);
16528 }
16529 
duk_realloc(duk_hthread * thr,void * ptr,duk_size_t size)16530 DUK_EXTERNAL void *duk_realloc(duk_hthread *thr, void *ptr, duk_size_t size) {
16531 	DUK_ASSERT_API_ENTRY(thr);
16532 
16533 	/*
16534 	 *  Note: since this is an exposed API call, there should be
16535 	 *  no way a mark-and-sweep could have a side effect on the
16536 	 *  memory allocation behind 'ptr'; the pointer should never
16537 	 *  be something that Duktape wants to change.
16538 	 *
16539 	 *  Thus, no need to use DUK_REALLOC_INDIRECT (and we don't
16540 	 *  have the storage location here anyway).
16541 	 */
16542 
16543 	return DUK_REALLOC(thr->heap, ptr, size);
16544 }
16545 
duk_get_memory_functions(duk_hthread * thr,duk_memory_functions * out_funcs)16546 DUK_EXTERNAL void duk_get_memory_functions(duk_hthread *thr, duk_memory_functions *out_funcs) {
16547 	duk_heap *heap;
16548 
16549 	DUK_ASSERT_API_ENTRY(thr);
16550 	DUK_ASSERT(out_funcs != NULL);
16551 	DUK_ASSERT(thr != NULL);
16552 	DUK_ASSERT(thr->heap != NULL);
16553 
16554 	heap = thr->heap;
16555 	out_funcs->alloc_func = heap->alloc_func;
16556 	out_funcs->realloc_func = heap->realloc_func;
16557 	out_funcs->free_func = heap->free_func;
16558 	out_funcs->udata = heap->heap_udata;
16559 }
16560 
duk_gc(duk_hthread * thr,duk_uint_t flags)16561 DUK_EXTERNAL void duk_gc(duk_hthread *thr, duk_uint_t flags) {
16562 	duk_heap *heap;
16563 	duk_small_uint_t ms_flags;
16564 
16565 	DUK_ASSERT_API_ENTRY(thr);
16566 	heap = thr->heap;
16567 	DUK_ASSERT(heap != NULL);
16568 
16569 	DUK_D(DUK_DPRINT("mark-and-sweep requested by application"));
16570 	DUK_ASSERT(DUK_GC_COMPACT == DUK_MS_FLAG_EMERGENCY);  /* Compact flag is 1:1 with emergency flag which forces compaction. */
16571 	ms_flags = (duk_small_uint_t) flags;
16572 	duk_heap_mark_and_sweep(heap, ms_flags);
16573 }
16574 /*
16575  *  Object handling: property access and other support functions.
16576  */
16577 
16578 /* #include duk_internal.h -> already included */
16579 
16580 /*
16581  *  Property handling
16582  *
16583  *  The API exposes only the most common property handling functions.
16584  *  The caller can invoke ECMAScript built-ins for full control (e.g.
16585  *  defineProperty, getOwnPropertyDescriptor).
16586  */
16587 
duk_get_prop(duk_hthread * thr,duk_idx_t obj_idx)16588 DUK_EXTERNAL duk_bool_t duk_get_prop(duk_hthread *thr, duk_idx_t obj_idx) {
16589 	duk_tval *tv_obj;
16590 	duk_tval *tv_key;
16591 	duk_bool_t rc;
16592 
16593 	DUK_ASSERT_API_ENTRY(thr);
16594 
16595 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
16596 	 * resize is not necessary for a property get right now.
16597 	 */
16598 
16599 	tv_obj = duk_require_tval(thr, obj_idx);
16600 	tv_key = duk_require_tval(thr, -1);
16601 
16602 	rc = duk_hobject_getprop(thr, tv_obj, tv_key);
16603 	DUK_ASSERT(rc == 0 || rc == 1);
16604 	/* a value is left on stack regardless of rc */
16605 
16606 	duk_remove_m2(thr);  /* remove key */
16607 	DUK_ASSERT(duk_is_undefined(thr, -1) || rc == 1);
16608 	return rc;  /* 1 if property found, 0 otherwise */
16609 }
16610 
duk_get_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)16611 DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
16612 	DUK_ASSERT_API_ENTRY(thr);
16613 	DUK_ASSERT(key != NULL);
16614 
16615 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16616 	(void) duk_push_string(thr, key);
16617 	return duk_get_prop(thr, obj_idx);
16618 }
16619 
duk_get_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)16620 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) {
16621 	DUK_ASSERT_API_ENTRY(thr);
16622 	DUK_ASSERT(key != NULL);
16623 
16624 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16625 	(void) duk_push_lstring(thr, key, key_len);
16626 	return duk_get_prop(thr, obj_idx);
16627 }
16628 
16629 #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)16630 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) {
16631 	DUK_ASSERT_API_ENTRY(thr);
16632 	DUK_ASSERT(key != NULL);
16633 	DUK_ASSERT(key[key_len] == (char) 0);
16634 
16635 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16636 	(void) duk_push_literal_raw(thr, key, key_len);
16637 	return duk_get_prop(thr, obj_idx);
16638 }
16639 #endif
16640 
duk_get_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)16641 DUK_EXTERNAL duk_bool_t duk_get_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
16642 	DUK_ASSERT_API_ENTRY(thr);
16643 
16644 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16645 	duk_push_uarridx(thr, arr_idx);
16646 	return duk_get_prop(thr, obj_idx);
16647 }
16648 
duk_get_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)16649 DUK_EXTERNAL duk_bool_t duk_get_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
16650 	DUK_ASSERT_API_ENTRY(thr);
16651 
16652 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16653 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
16654 	return duk_get_prop(thr, obj_idx);
16655 }
16656 
duk_get_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)16657 DUK_INTERNAL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
16658 	DUK_ASSERT_API_ENTRY(thr);
16659 	DUK_ASSERT_STRIDX_VALID(stridx);
16660 
16661 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16662 	(void) duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
16663 	return duk_get_prop(thr, obj_idx);
16664 }
16665 
duk_get_prop_stridx_short_raw(duk_hthread * thr,duk_uint_t packed_args)16666 DUK_INTERNAL duk_bool_t duk_get_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
16667 	return duk_get_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
16668 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
16669 }
16670 
duk_get_prop_stridx_boolean(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx,duk_bool_t * out_has_prop)16671 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) {
16672 	duk_bool_t rc;
16673 
16674 	DUK_ASSERT_API_ENTRY(thr);
16675 	DUK_ASSERT_STRIDX_VALID(stridx);
16676 
16677 	rc = duk_get_prop_stridx(thr, obj_idx, stridx);
16678 	if (out_has_prop) {
16679 		*out_has_prop = rc;
16680 	}
16681 	return duk_to_boolean_top_pop(thr);
16682 }
16683 
16684 /* This get variant is for internal use, it differs from standard
16685  * duk_get_prop() in that:
16686  *   - Object argument must be an object (primitive values not supported).
16687  *   - Key argument must be a string (no coercion).
16688  *   - Only own properties are checked (no inheritance).  Only "entry part"
16689  *     properties are checked (not array index properties).
16690  *   - Property must be a plain data property, not a getter.
16691  *   - Proxy traps are not triggered.
16692  */
duk_xget_owndataprop(duk_hthread * thr,duk_idx_t obj_idx)16693 DUK_INTERNAL duk_bool_t duk_xget_owndataprop(duk_hthread *thr, duk_idx_t obj_idx) {
16694 	duk_hobject *h_obj;
16695 	duk_hstring *h_key;
16696 	duk_tval *tv_val;
16697 
16698 	DUK_ASSERT_API_ENTRY(thr);
16699 
16700 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
16701 	 * resize is not necessary for a property get right now.
16702 	 */
16703 
16704 	h_obj = duk_get_hobject(thr, obj_idx);
16705 	if (h_obj == NULL) {
16706 		return 0;
16707 	}
16708 	h_key = duk_require_hstring(thr, -1);
16709 
16710 	tv_val = duk_hobject_find_entry_tval_ptr(thr->heap, h_obj, h_key);
16711 	if (tv_val == NULL) {
16712 		return 0;
16713 	}
16714 
16715 	duk_push_tval(thr, tv_val);
16716 	duk_remove_m2(thr);  /* remove key */
16717 
16718 	return 1;
16719 }
16720 
duk_xget_owndataprop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)16721 DUK_INTERNAL duk_bool_t duk_xget_owndataprop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
16722 	DUK_ASSERT_API_ENTRY(thr);
16723 	DUK_ASSERT_STRIDX_VALID(stridx);
16724 
16725 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16726 	(void) duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
16727 	return duk_xget_owndataprop(thr, obj_idx);
16728 }
16729 
duk_xget_owndataprop_stridx_short_raw(duk_hthread * thr,duk_uint_t packed_args)16730 DUK_INTERNAL duk_bool_t duk_xget_owndataprop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
16731 	return duk_xget_owndataprop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
16732 	                                   (duk_small_uint_t) (packed_args & 0xffffUL));
16733 }
16734 
duk__put_prop_shared(duk_hthread * thr,duk_idx_t obj_idx,duk_idx_t idx_key)16735 DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t idx_key) {
16736 	duk_tval *tv_obj;
16737 	duk_tval *tv_key;
16738 	duk_tval *tv_val;
16739 	duk_bool_t throw_flag;
16740 	duk_bool_t rc;
16741 
16742 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
16743 	 * resize is not necessary for a property put right now (putprop protects
16744 	 * against it internally).
16745 	 */
16746 
16747 	/* Key and value indices are either (-2, -1) or (-1, -2).  Given idx_key,
16748 	 * idx_val is always (idx_key ^ 0x01).
16749 	 */
16750 	DUK_ASSERT((idx_key == -2 && (idx_key ^ 1) == -1) ||
16751 	           (idx_key == -1 && (idx_key ^ 1) == -2));
16752 	/* XXX: Direct access; faster validation. */
16753 	tv_obj = duk_require_tval(thr, obj_idx);
16754 	tv_key = duk_require_tval(thr, idx_key);
16755 	tv_val = duk_require_tval(thr, idx_key ^ 1);
16756 	throw_flag = duk_is_strict_call(thr);
16757 
16758 	rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag);
16759 	DUK_ASSERT(rc == 0 || rc == 1);
16760 
16761 	duk_pop_2(thr);  /* remove key and value */
16762 	return rc;  /* 1 if property found, 0 otherwise */
16763 }
16764 
duk_put_prop(duk_hthread * thr,duk_idx_t obj_idx)16765 DUK_EXTERNAL duk_bool_t duk_put_prop(duk_hthread *thr, duk_idx_t obj_idx) {
16766 	DUK_ASSERT_API_ENTRY(thr);
16767 	return duk__put_prop_shared(thr, obj_idx, -2);
16768 }
16769 
duk_put_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)16770 DUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
16771 	DUK_ASSERT_API_ENTRY(thr);
16772 	DUK_ASSERT(key != NULL);
16773 
16774 	/* Careful here and with other duk_put_prop_xxx() helpers: the
16775 	 * target object and the property value may be in the same value
16776 	 * stack slot (unusual, but still conceptually clear).
16777 	 */
16778 	obj_idx = duk_normalize_index(thr, obj_idx);
16779 	(void) duk_push_string(thr, key);
16780 	return duk__put_prop_shared(thr, obj_idx, -1);
16781 }
16782 
duk_put_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)16783 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) {
16784 	DUK_ASSERT_API_ENTRY(thr);
16785 	DUK_ASSERT(key != NULL);
16786 
16787 	obj_idx = duk_normalize_index(thr, obj_idx);
16788 	(void) duk_push_lstring(thr, key, key_len);
16789 	return duk__put_prop_shared(thr, obj_idx, -1);
16790 }
16791 
16792 #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)16793 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) {
16794 	DUK_ASSERT_API_ENTRY(thr);
16795 	DUK_ASSERT(key != NULL);
16796 	DUK_ASSERT(key[key_len] == (char) 0);
16797 
16798 	obj_idx = duk_normalize_index(thr, obj_idx);
16799 	(void) duk_push_literal_raw(thr, key, key_len);
16800 	return duk__put_prop_shared(thr, obj_idx, -1);
16801 }
16802 #endif
16803 
duk_put_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)16804 DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
16805 	DUK_ASSERT_API_ENTRY(thr);
16806 
16807 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16808 	duk_push_uarridx(thr, arr_idx);
16809 	return duk__put_prop_shared(thr, obj_idx, -1);
16810 }
16811 
duk_put_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)16812 DUK_EXTERNAL duk_bool_t duk_put_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
16813 	DUK_ASSERT_API_ENTRY(thr);
16814 
16815 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16816 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
16817 	return duk__put_prop_shared(thr, obj_idx, -1);
16818 }
16819 
16820 
duk_put_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)16821 DUK_INTERNAL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
16822 	DUK_ASSERT_API_ENTRY(thr);
16823 	DUK_ASSERT_STRIDX_VALID(stridx);
16824 
16825 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16826 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
16827 	return duk__put_prop_shared(thr, obj_idx, -1);
16828 }
16829 
duk_put_prop_stridx_short_raw(duk_hthread * thr,duk_uint_t packed_args)16830 DUK_INTERNAL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
16831 	return duk_put_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
16832 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
16833 }
16834 
duk_del_prop(duk_hthread * thr,duk_idx_t obj_idx)16835 DUK_EXTERNAL duk_bool_t duk_del_prop(duk_hthread *thr, duk_idx_t obj_idx) {
16836 	duk_tval *tv_obj;
16837 	duk_tval *tv_key;
16838 	duk_bool_t throw_flag;
16839 	duk_bool_t rc;
16840 
16841 	DUK_ASSERT_API_ENTRY(thr);
16842 
16843 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
16844 	 * resize is not necessary for a property delete right now.
16845 	 */
16846 
16847 	tv_obj = duk_require_tval(thr, obj_idx);
16848 	tv_key = duk_require_tval(thr, -1);
16849 	throw_flag = duk_is_strict_call(thr);
16850 
16851 	rc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag);
16852 	DUK_ASSERT(rc == 0 || rc == 1);
16853 
16854 	duk_pop(thr);  /* remove key */
16855 	return rc;
16856 }
16857 
duk_del_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)16858 DUK_EXTERNAL duk_bool_t duk_del_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
16859 	DUK_ASSERT_API_ENTRY(thr);
16860 	DUK_ASSERT(key != NULL);
16861 
16862 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16863 	(void) duk_push_string(thr, key);
16864 	return duk_del_prop(thr, obj_idx);
16865 }
16866 
duk_del_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)16867 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) {
16868 	DUK_ASSERT_API_ENTRY(thr);
16869 	DUK_ASSERT(key != NULL);
16870 
16871 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16872 	(void) duk_push_lstring(thr, key, key_len);
16873 	return duk_del_prop(thr, obj_idx);
16874 }
16875 
16876 #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)16877 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) {
16878 	DUK_ASSERT_API_ENTRY(thr);
16879 	DUK_ASSERT(key != NULL);
16880 	DUK_ASSERT(key[key_len] == (char) 0);
16881 
16882 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16883 	(void) duk_push_literal_raw(thr, key, key_len);
16884 	return duk_del_prop(thr, obj_idx);
16885 }
16886 #endif
16887 
duk_del_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)16888 DUK_EXTERNAL duk_bool_t duk_del_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
16889 	DUK_ASSERT_API_ENTRY(thr);
16890 
16891 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16892 	duk_push_uarridx(thr, arr_idx);
16893 	return duk_del_prop(thr, obj_idx);
16894 }
16895 
duk_del_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)16896 DUK_EXTERNAL duk_bool_t duk_del_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
16897 	DUK_ASSERT_API_ENTRY(thr);
16898 
16899 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16900 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
16901 	return duk_del_prop(thr, obj_idx);
16902 }
16903 
duk_del_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)16904 DUK_INTERNAL duk_bool_t duk_del_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
16905 	DUK_ASSERT_API_ENTRY(thr);
16906 	DUK_ASSERT_STRIDX_VALID(stridx);
16907 
16908 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16909 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
16910 	return duk_del_prop(thr, obj_idx);
16911 }
16912 
16913 #if 0
16914 DUK_INTERNAL duk_bool_t duk_del_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
16915 	return duk_del_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
16916 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
16917 }
16918 #endif
16919 
duk_has_prop(duk_hthread * thr,duk_idx_t obj_idx)16920 DUK_EXTERNAL duk_bool_t duk_has_prop(duk_hthread *thr, duk_idx_t obj_idx) {
16921 	duk_tval *tv_obj;
16922 	duk_tval *tv_key;
16923 	duk_bool_t rc;
16924 
16925 	DUK_ASSERT_API_ENTRY(thr);
16926 
16927 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
16928 	 * resize is not necessary for a property existence check right now.
16929 	 */
16930 
16931 	tv_obj = duk_require_tval(thr, obj_idx);
16932 	tv_key = duk_require_tval(thr, -1);
16933 
16934 	rc = duk_hobject_hasprop(thr, tv_obj, tv_key);
16935 	DUK_ASSERT(rc == 0 || rc == 1);
16936 
16937 	duk_pop(thr);  /* remove key */
16938 	return rc;  /* 1 if property found, 0 otherwise */
16939 }
16940 
duk_has_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)16941 DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
16942 	DUK_ASSERT_API_ENTRY(thr);
16943 	DUK_ASSERT(key != NULL);
16944 
16945 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16946 	(void) duk_push_string(thr, key);
16947 	return duk_has_prop(thr, obj_idx);
16948 }
16949 
duk_has_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)16950 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) {
16951 	DUK_ASSERT_API_ENTRY(thr);
16952 	DUK_ASSERT(key != NULL);
16953 
16954 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16955 	(void) duk_push_lstring(thr, key, key_len);
16956 	return duk_has_prop(thr, obj_idx);
16957 }
16958 
16959 #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)16960 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) {
16961 	DUK_ASSERT_API_ENTRY(thr);
16962 	DUK_ASSERT(key != NULL);
16963 	DUK_ASSERT(key[key_len] == (char) 0);
16964 
16965 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16966 	(void) duk_push_literal_raw(thr, key, key_len);
16967 	return duk_has_prop(thr, obj_idx);
16968 }
16969 #endif
16970 
duk_has_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)16971 DUK_EXTERNAL duk_bool_t duk_has_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
16972 	DUK_ASSERT_API_ENTRY(thr);
16973 
16974 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16975 	duk_push_uarridx(thr, arr_idx);
16976 	return duk_has_prop(thr, obj_idx);
16977 }
16978 
duk_has_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)16979 DUK_EXTERNAL duk_bool_t duk_has_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
16980 	DUK_ASSERT_API_ENTRY(thr);
16981 
16982 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16983 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
16984 	return duk_has_prop(thr, obj_idx);
16985 }
16986 
duk_has_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)16987 DUK_INTERNAL duk_bool_t duk_has_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
16988 	DUK_ASSERT_API_ENTRY(thr);
16989 	DUK_ASSERT_STRIDX_VALID(stridx);
16990 
16991 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16992 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
16993 	return duk_has_prop(thr, obj_idx);
16994 }
16995 
16996 #if 0
16997 DUK_INTERNAL duk_bool_t duk_has_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
16998 	return duk_has_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
16999 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
17000 }
17001 #endif
17002 
17003 /* Define own property without inheritance lookups and such.  This differs from
17004  * [[DefineOwnProperty]] because special behaviors (like Array 'length') are
17005  * not invoked by this method.  The caller must be careful to invoke any such
17006  * behaviors if necessary.
17007  */
duk_xdef_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t desc_flags)17008 DUK_INTERNAL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags) {
17009 	duk_hobject *obj;
17010 	duk_hstring *key;
17011 
17012 	DUK_ASSERT_API_ENTRY(thr);
17013 
17014 	obj = duk_require_hobject(thr, obj_idx);
17015 	DUK_ASSERT(obj != NULL);
17016 	key = duk_to_property_key_hstring(thr, -2);
17017 	DUK_ASSERT(key != NULL);
17018 	DUK_ASSERT(duk_require_tval(thr, -1) != NULL);
17019 
17020 	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
17021 
17022 	duk_pop(thr);  /* pop key */
17023 }
17024 
duk_xdef_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx,duk_small_uint_t desc_flags)17025 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) {
17026 	duk_hobject *obj;
17027 
17028 	DUK_ASSERT_API_ENTRY(thr);
17029 
17030 	obj = duk_require_hobject(thr, obj_idx);
17031 	DUK_ASSERT(obj != NULL);
17032 
17033 	duk_hobject_define_property_internal_arridx(thr, obj, arr_idx, desc_flags);
17034 	/* value popped by call */
17035 }
17036 
duk_xdef_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx,duk_small_uint_t desc_flags)17037 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) {
17038 	duk_hobject *obj;
17039 	duk_hstring *key;
17040 
17041 	DUK_ASSERT_API_ENTRY(thr);
17042 	DUK_ASSERT_STRIDX_VALID(stridx);
17043 
17044 	obj = duk_require_hobject(thr, obj_idx);
17045 	DUK_ASSERT(obj != NULL);
17046 	key = DUK_HTHREAD_GET_STRING(thr, stridx);
17047 	DUK_ASSERT(key != NULL);
17048 	DUK_ASSERT(duk_require_tval(thr, -1) != NULL);
17049 
17050 	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
17051 	/* value popped by call */
17052 }
17053 
duk_xdef_prop_stridx_short_raw(duk_hthread * thr,duk_uint_t packed_args)17054 DUK_INTERNAL void duk_xdef_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
17055 	duk_xdef_prop_stridx(thr, (duk_idx_t) (duk_int8_t) (packed_args >> 24),
17056 	                          (duk_small_uint_t) (packed_args >> 8) & 0xffffUL,
17057 	                          (duk_small_uint_t) (packed_args & 0xffL));
17058 }
17059 
17060 #if 0  /*unused*/
17061 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) {
17062 	duk_hobject *obj;
17063 	duk_hstring *key;
17064 
17065 	DUK_ASSERT_API_ENTRY(thr);
17066 	DUK_ASSERT_STRIDX_VALID(stridx);
17067 	DUK_ASSERT_BIDX_VALID(builtin_idx);
17068 
17069 	obj = duk_require_hobject(thr, obj_idx);
17070 	DUK_ASSERT(obj != NULL);
17071 	key = DUK_HTHREAD_GET_STRING(thr, stridx);
17072 	DUK_ASSERT(key != NULL);
17073 
17074 	duk_push_hobject(thr, thr->builtins[builtin_idx]);
17075 	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
17076 	/* value popped by call */
17077 }
17078 #endif
17079 
17080 /* This is a rare property helper; it sets the global thrower (E5 Section 13.2.3)
17081  * setter/getter into an object property.  This is needed by the 'arguments'
17082  * object creation code, function instance creation code, and Function.prototype.bind().
17083  */
17084 
duk_xdef_prop_stridx_thrower(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)17085 DUK_INTERNAL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
17086 	DUK_ASSERT_API_ENTRY(thr);
17087 
17088 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17089 	duk_push_hstring_stridx(thr, stridx);
17090 	duk_push_hobject_bidx(thr, DUK_BIDX_TYPE_ERROR_THROWER);
17091 	duk_dup_top(thr);
17092 	duk_def_prop(thr, obj_idx, DUK_DEFPROP_HAVE_SETTER | DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_FORCE);  /* attributes always 0 */
17093 }
17094 
17095 /* Object.getOwnPropertyDescriptor() equivalent C binding. */
duk_get_prop_desc(duk_hthread * thr,duk_idx_t obj_idx,duk_uint_t flags)17096 DUK_EXTERNAL void duk_get_prop_desc(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t flags) {
17097 	DUK_ASSERT_API_ENTRY(thr);
17098 	DUK_UNREF(flags);  /* no flags defined yet */
17099 
17100 	duk_hobject_object_get_own_property_descriptor(thr, obj_idx);  /* [ ... key ] -> [ ... desc ] */
17101 }
17102 
17103 /* Object.defineProperty() equivalent C binding. */
duk_def_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_uint_t flags)17104 DUK_EXTERNAL void duk_def_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t flags) {
17105 	duk_idx_t idx_base;
17106 	duk_hobject *obj;
17107 	duk_hstring *key;
17108 	duk_idx_t idx_value;
17109 	duk_hobject *get;
17110 	duk_hobject *set;
17111 	duk_uint_t is_data_desc;
17112 	duk_uint_t is_acc_desc;
17113 
17114 	DUK_ASSERT_API_ENTRY(thr);
17115 
17116 	obj = duk_require_hobject(thr, obj_idx);
17117 
17118 	is_data_desc = flags & (DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
17119 	is_acc_desc = flags & (DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
17120 	if (is_data_desc && is_acc_desc) {
17121 		/* "Have" flags must not be conflicting so that they would
17122 		 * apply to both a plain property and an accessor at the same
17123 		 * time.
17124 		 */
17125 		goto fail_invalid_desc;
17126 	}
17127 
17128 	idx_base = duk_get_top_index(thr);
17129 	if (flags & DUK_DEFPROP_HAVE_SETTER) {
17130 		duk_require_type_mask(thr, idx_base, DUK_TYPE_MASK_UNDEFINED |
17131 		                                     DUK_TYPE_MASK_OBJECT |
17132 		                                     DUK_TYPE_MASK_LIGHTFUNC);
17133 		set = duk_get_hobject_promote_lfunc(thr, idx_base);
17134 		if (set != NULL && !DUK_HOBJECT_IS_CALLABLE(set)) {
17135 			goto fail_not_callable;
17136 		}
17137 		idx_base--;
17138 	} else {
17139 		set = NULL;
17140 	}
17141 	if (flags & DUK_DEFPROP_HAVE_GETTER) {
17142 		duk_require_type_mask(thr, idx_base, DUK_TYPE_MASK_UNDEFINED |
17143 		                                     DUK_TYPE_MASK_OBJECT |
17144 		                                     DUK_TYPE_MASK_LIGHTFUNC);
17145 		get = duk_get_hobject_promote_lfunc(thr, idx_base);
17146 		if (get != NULL && !DUK_HOBJECT_IS_CALLABLE(get)) {
17147 			goto fail_not_callable;
17148 		}
17149 		idx_base--;
17150 	} else {
17151 		get = NULL;
17152 	}
17153 	if (flags & DUK_DEFPROP_HAVE_VALUE) {
17154 		idx_value = idx_base;
17155 		idx_base--;
17156 	} else {
17157 		idx_value = (duk_idx_t) -1;
17158 	}
17159 	key = duk_to_property_key_hstring(thr, idx_base);
17160 	DUK_ASSERT(key != NULL);
17161 
17162 	duk_require_valid_index(thr, idx_base);
17163 
17164 	duk_hobject_define_property_helper(thr,
17165 	                                   flags /*defprop_flags*/,
17166 	                                   obj,
17167 	                                   key,
17168 	                                   idx_value,
17169 	                                   get,
17170 	                                   set,
17171 	                                   1 /*throw_flag*/);
17172 
17173 	/* Clean up stack */
17174 
17175 	duk_set_top(thr, idx_base);
17176 
17177 	/* [ ... obj ... ] */
17178 
17179 	return;
17180 
17181  fail_invalid_desc:
17182 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
17183 	DUK_WO_NORETURN(return;);
17184 
17185  fail_not_callable:
17186 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
17187 	DUK_WO_NORETURN(return;);
17188 }
17189 
17190 /*
17191  *  Object related
17192  */
17193 
duk_compact(duk_hthread * thr,duk_idx_t obj_idx)17194 DUK_EXTERNAL void duk_compact(duk_hthread *thr, duk_idx_t obj_idx) {
17195 	duk_hobject *obj;
17196 
17197 	DUK_ASSERT_API_ENTRY(thr);
17198 
17199 	obj = duk_get_hobject(thr, obj_idx);
17200 	if (obj) {
17201 		/* Note: this may fail, caller should protect the call if necessary */
17202 		duk_hobject_compact_props(thr, obj);
17203 	}
17204 }
17205 
duk_compact_m1(duk_hthread * thr)17206 DUK_INTERNAL void duk_compact_m1(duk_hthread *thr) {
17207 	DUK_ASSERT_API_ENTRY(thr);
17208 
17209 	duk_compact(thr, -1);
17210 }
17211 
17212 /* XXX: the duk_hobject_enum.c stack APIs should be reworked */
17213 
duk_enum(duk_hthread * thr,duk_idx_t obj_idx,duk_uint_t enum_flags)17214 DUK_EXTERNAL void duk_enum(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t enum_flags) {
17215 	DUK_ASSERT_API_ENTRY(thr);
17216 
17217 	duk_dup(thr, obj_idx);
17218 	duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
17219 	duk_hobject_enumerator_create(thr, enum_flags);   /* [target] -> [enum] */
17220 }
17221 
duk_next(duk_hthread * thr,duk_idx_t enum_index,duk_bool_t get_value)17222 DUK_EXTERNAL duk_bool_t duk_next(duk_hthread *thr, duk_idx_t enum_index, duk_bool_t get_value) {
17223 	DUK_ASSERT_API_ENTRY(thr);
17224 
17225 	duk_require_hobject(thr, enum_index);
17226 	duk_dup(thr, enum_index);
17227 	return duk_hobject_enumerator_next(thr, get_value);
17228 }
17229 
duk_seal_freeze_raw(duk_hthread * thr,duk_idx_t obj_idx,duk_bool_t is_freeze)17230 DUK_INTERNAL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_bool_t is_freeze) {
17231 	duk_tval *tv;
17232 	duk_hobject *h;
17233 
17234 	DUK_ASSERT_API_ENTRY(thr);
17235 
17236 	tv = duk_require_tval(thr, obj_idx);
17237 	DUK_ASSERT(tv != NULL);
17238 
17239 	/* Seal/freeze are quite rare in practice so it'd be nice to get the
17240 	 * correct behavior simply via automatic promotion (at the cost of some
17241 	 * memory churn).  However, the promoted objects don't behave the same,
17242 	 * e.g. promoted lightfuncs are extensible.
17243 	 */
17244 
17245 	switch (DUK_TVAL_GET_TAG(tv)) {
17246 	case DUK_TAG_BUFFER:
17247 		/* Plain buffer: already sealed, but not frozen (and can't be frozen
17248 		 * because index properties can't be made non-writable.
17249 		 */
17250 		if (is_freeze) {
17251 			goto fail_cannot_freeze;
17252 		}
17253 		break;
17254 	case DUK_TAG_LIGHTFUNC:
17255 		/* Lightfunc: already sealed and frozen, success. */
17256 		break;
17257 	case DUK_TAG_OBJECT:
17258 		h = DUK_TVAL_GET_OBJECT(tv);
17259 		DUK_ASSERT(h != NULL);
17260 		if (is_freeze && DUK_HOBJECT_IS_BUFOBJ(h)) {
17261 			/* Buffer objects cannot be frozen because there's no internal
17262 			 * support for making virtual array indices non-writable.
17263 			 */
17264 			DUK_DD(DUK_DDPRINT("cannot freeze a buffer object"));
17265 			goto fail_cannot_freeze;
17266 		}
17267 		duk_hobject_object_seal_freeze_helper(thr, h, is_freeze);
17268 
17269 		/* Sealed and frozen objects cannot gain any more properties,
17270 		 * so this is a good time to compact them.
17271 		 */
17272 		duk_hobject_compact_props(thr, h);
17273 		break;
17274 	default:
17275 		/* ES2015 Sections 19.1.2.5, 19.1.2.17 */
17276 		break;
17277 	}
17278 	return;
17279 
17280  fail_cannot_freeze:
17281 	DUK_ERROR_TYPE_INVALID_ARGS(thr);  /* XXX: proper error message */
17282 	DUK_WO_NORETURN(return;);
17283 }
17284 
duk_seal(duk_hthread * thr,duk_idx_t obj_idx)17285 DUK_EXTERNAL void duk_seal(duk_hthread *thr, duk_idx_t obj_idx) {
17286 	DUK_ASSERT_API_ENTRY(thr);
17287 
17288 	duk_seal_freeze_raw(thr, obj_idx, 0 /*is_freeze*/);
17289 }
17290 
duk_freeze(duk_hthread * thr,duk_idx_t obj_idx)17291 DUK_EXTERNAL void duk_freeze(duk_hthread *thr, duk_idx_t obj_idx) {
17292 	DUK_ASSERT_API_ENTRY(thr);
17293 
17294 	duk_seal_freeze_raw(thr, obj_idx, 1 /*is_freeze*/);
17295 }
17296 
17297 /*
17298  *  Helpers for writing multiple properties
17299  */
17300 
duk_put_function_list(duk_hthread * thr,duk_idx_t obj_idx,const duk_function_list_entry * funcs)17301 DUK_EXTERNAL void duk_put_function_list(duk_hthread *thr, duk_idx_t obj_idx, const duk_function_list_entry *funcs) {
17302 	const duk_function_list_entry *ent = funcs;
17303 
17304 	DUK_ASSERT_API_ENTRY(thr);
17305 
17306 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17307 	if (ent != NULL) {
17308 		while (ent->key != NULL) {
17309 			duk_push_c_function(thr, ent->value, ent->nargs);
17310 			duk_put_prop_string(thr, obj_idx, ent->key);
17311 			ent++;
17312 		}
17313 	}
17314 }
17315 
duk_put_number_list(duk_hthread * thr,duk_idx_t obj_idx,const duk_number_list_entry * numbers)17316 DUK_EXTERNAL void duk_put_number_list(duk_hthread *thr, duk_idx_t obj_idx, const duk_number_list_entry *numbers) {
17317 	const duk_number_list_entry *ent = numbers;
17318 	duk_tval *tv;
17319 
17320 	DUK_ASSERT_API_ENTRY(thr);
17321 
17322 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17323 	if (ent != NULL) {
17324 		while (ent->key != NULL) {
17325 			tv = thr->valstack_top++;
17326 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));  /* value stack init policy */
17327 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, ent->value);  /* no need for decref/incref */
17328 			duk_put_prop_string(thr, obj_idx, ent->key);
17329 			ent++;
17330 		}
17331 	}
17332 }
17333 
17334 /*
17335  *  Shortcut for accessing global object properties
17336  */
17337 
duk_get_global_string(duk_hthread * thr,const char * key)17338 DUK_EXTERNAL duk_bool_t duk_get_global_string(duk_hthread *thr, const char *key) {
17339 	duk_bool_t ret;
17340 
17341 	DUK_ASSERT_API_ENTRY(thr);
17342 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17343 
17344 	/* XXX: direct implementation */
17345 
17346 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17347 	ret = duk_get_prop_string(thr, -1, key);
17348 	duk_remove_m2(thr);
17349 	return ret;
17350 }
17351 
duk_get_global_lstring(duk_hthread * thr,const char * key,duk_size_t key_len)17352 DUK_EXTERNAL duk_bool_t duk_get_global_lstring(duk_hthread *thr, const char *key, duk_size_t key_len) {
17353 	duk_bool_t ret;
17354 
17355 	DUK_ASSERT_API_ENTRY(thr);
17356 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17357 
17358 	/* XXX: direct implementation */
17359 
17360 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17361 	ret = duk_get_prop_lstring(thr, -1, key, key_len);
17362 	duk_remove_m2(thr);
17363 	return ret;
17364 }
17365 
17366 #if !defined(DUK_USE_PREFER_SIZE)
duk_get_global_literal_raw(duk_hthread * thr,const char * key,duk_size_t key_len)17367 DUK_EXTERNAL duk_bool_t duk_get_global_literal_raw(duk_hthread *thr, const char *key, duk_size_t key_len) {
17368 	duk_bool_t ret;
17369 
17370 	DUK_ASSERT_API_ENTRY(thr);
17371 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17372 	DUK_ASSERT(key[key_len] == (char) 0);
17373 
17374 	/* XXX: direct implementation */
17375 
17376 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17377 	ret = duk_get_prop_literal_raw(thr, -1, key, key_len);
17378 	duk_remove_m2(thr);
17379 	return ret;
17380 }
17381 #endif
17382 
duk_get_global_heapptr(duk_hthread * thr,void * ptr)17383 DUK_EXTERNAL duk_bool_t duk_get_global_heapptr(duk_hthread *thr, void *ptr) {
17384 	duk_bool_t ret;
17385 
17386 	DUK_ASSERT_API_ENTRY(thr);
17387 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17388 
17389 	/* XXX: direct implementation */
17390 
17391 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17392 	ret = duk_get_prop_heapptr(thr, -1, ptr);
17393 	duk_remove_m2(thr);
17394 	return ret;
17395 }
17396 
17397 
duk_put_global_string(duk_hthread * thr,const char * key)17398 DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_hthread *thr, const char *key) {
17399 	duk_bool_t ret;
17400 
17401 	DUK_ASSERT_API_ENTRY(thr);
17402 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17403 
17404 	/* XXX: direct implementation */
17405 
17406 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17407 	duk_insert(thr, -2);
17408 	ret = duk_put_prop_string(thr, -2, key);  /* [ ... global val ] -> [ ... global ] */
17409 	duk_pop(thr);
17410 	return ret;
17411 }
17412 
duk_put_global_lstring(duk_hthread * thr,const char * key,duk_size_t key_len)17413 DUK_EXTERNAL duk_bool_t duk_put_global_lstring(duk_hthread *thr, const char *key, duk_size_t key_len) {
17414 	duk_bool_t ret;
17415 
17416 	DUK_ASSERT_API_ENTRY(thr);
17417 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17418 
17419 	/* XXX: direct implementation */
17420 
17421 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17422 	duk_insert(thr, -2);
17423 	ret = duk_put_prop_lstring(thr, -2, key, key_len);  /* [ ... global val ] -> [ ... global ] */
17424 	duk_pop(thr);
17425 	return ret;
17426 }
17427 
17428 #if !defined(DUK_USE_PREFER_SIZE)
duk_put_global_literal_raw(duk_hthread * thr,const char * key,duk_size_t key_len)17429 DUK_EXTERNAL duk_bool_t duk_put_global_literal_raw(duk_hthread *thr, const char *key, duk_size_t key_len) {
17430 	duk_bool_t ret;
17431 
17432 	DUK_ASSERT_API_ENTRY(thr);
17433 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17434 	DUK_ASSERT(key[key_len] == (char) 0);
17435 
17436 	/* XXX: direct implementation */
17437 
17438 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17439 	duk_insert(thr, -2);
17440 	ret = duk_put_prop_literal_raw(thr, -2, key, key_len);  /* [ ... global val ] -> [ ... global ] */
17441 	duk_pop(thr);
17442 	return ret;
17443 }
17444 #endif
17445 
duk_put_global_heapptr(duk_hthread * thr,void * ptr)17446 DUK_EXTERNAL duk_bool_t duk_put_global_heapptr(duk_hthread *thr, void *ptr) {
17447 	duk_bool_t ret;
17448 
17449 	DUK_ASSERT_API_ENTRY(thr);
17450 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17451 
17452 	/* XXX: direct implementation */
17453 
17454 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17455 	duk_insert(thr, -2);
17456 	ret = duk_put_prop_heapptr(thr, -2, ptr);  /* [ ... global val ] -> [ ... global ] */
17457 	duk_pop(thr);
17458 	return ret;
17459 }
17460 
17461 /*
17462  *  ES2015 GetMethod()
17463  */
17464 
duk_get_method_stridx(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t stridx)17465 DUK_INTERNAL duk_bool_t duk_get_method_stridx(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t stridx) {
17466 	(void) duk_get_prop_stridx(thr, idx, stridx);
17467 	if (duk_is_null_or_undefined(thr, -1)) {
17468 		duk_pop_nodecref_unsafe(thr);
17469 		return 0;
17470 	}
17471 	if (!duk_is_callable(thr, -1)) {
17472 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
17473 		DUK_WO_NORETURN(return 0;);
17474 	}
17475 	return 1;
17476 }
17477 
17478 /*
17479  *  Object prototype
17480  */
17481 
duk_get_prototype(duk_hthread * thr,duk_idx_t idx)17482 DUK_EXTERNAL void duk_get_prototype(duk_hthread *thr, duk_idx_t idx) {
17483 	duk_hobject *obj;
17484 	duk_hobject *proto;
17485 
17486 	DUK_ASSERT_API_ENTRY(thr);
17487 
17488 	obj = duk_require_hobject(thr, idx);
17489 	DUK_ASSERT(obj != NULL);
17490 
17491 	/* XXX: shared helper for duk_push_hobject_or_undefined()? */
17492 	proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);
17493 	if (proto) {
17494 		duk_push_hobject(thr, proto);
17495 	} else {
17496 		duk_push_undefined(thr);
17497 	}
17498 }
17499 
duk_set_prototype(duk_hthread * thr,duk_idx_t idx)17500 DUK_EXTERNAL void duk_set_prototype(duk_hthread *thr, duk_idx_t idx) {
17501 	duk_hobject *obj;
17502 	duk_hobject *proto;
17503 
17504 	DUK_ASSERT_API_ENTRY(thr);
17505 
17506 	obj = duk_require_hobject(thr, idx);
17507 	DUK_ASSERT(obj != NULL);
17508 	duk_require_type_mask(thr, -1, DUK_TYPE_MASK_UNDEFINED |
17509 	                               DUK_TYPE_MASK_OBJECT);
17510 	proto = duk_get_hobject(thr, -1);
17511 	/* proto can also be NULL here (allowed explicitly) */
17512 
17513 #if defined(DUK_USE_ROM_OBJECTS)
17514 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
17515 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);  /* XXX: "read only object"? */
17516 		DUK_WO_NORETURN(return;);
17517 	}
17518 #endif
17519 
17520 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, proto);
17521 
17522 	duk_pop(thr);
17523 }
17524 
duk_clear_prototype(duk_hthread * thr,duk_idx_t idx)17525 DUK_INTERNAL void duk_clear_prototype(duk_hthread *thr, duk_idx_t idx) {
17526 	duk_hobject *obj;
17527 
17528 	DUK_ASSERT_API_ENTRY(thr);
17529 
17530 	obj = duk_require_hobject(thr, idx);
17531 	DUK_ASSERT(obj != NULL);
17532 
17533 #if defined(DUK_USE_ROM_OBJECTS)
17534 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
17535 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);  /* XXX: "read only object"? */
17536 		DUK_WO_NORETURN(return;);
17537 	}
17538 #endif
17539 
17540 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, NULL);
17541 }
17542 
duk_is_bare_object(duk_hthread * thr,duk_idx_t idx)17543 DUK_INTERNAL duk_bool_t duk_is_bare_object(duk_hthread *thr, duk_idx_t idx) {
17544 	duk_hobject *obj;
17545 	duk_hobject *proto;
17546 
17547 	DUK_ASSERT_API_ENTRY(thr);
17548 
17549 	obj = duk_require_hobject(thr, idx);
17550 	DUK_ASSERT(obj != NULL);
17551 
17552 	proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);
17553 	return (proto == NULL);
17554 }
17555 
17556 /*
17557  *  Object finalizer
17558  */
17559 
17560 #if defined(DUK_USE_FINALIZER_SUPPORT)
17561 /* XXX: these could be implemented as macros calling an internal function
17562  * directly.
17563  * XXX: same issue as with Duktape.fin: there's no way to delete the property
17564  * now (just set it to undefined).
17565  */
duk_get_finalizer(duk_hthread * thr,duk_idx_t idx)17566 DUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx) {
17567 	DUK_ASSERT_API_ENTRY(thr);
17568 
17569 	/* This get intentionally walks the inheritance chain at present,
17570 	 * which matches how the effective finalizer property is also
17571 	 * looked up in GC.
17572 	 */
17573 	duk_get_prop_stridx(thr, idx, DUK_STRIDX_INT_FINALIZER);
17574 }
17575 
duk_set_finalizer(duk_hthread * thr,duk_idx_t idx)17576 DUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) {
17577 	duk_hobject *h;
17578 	duk_bool_t callable;
17579 
17580 	DUK_ASSERT_API_ENTRY(thr);
17581 
17582 	h = duk_require_hobject(thr, idx);  /* Get before 'put' so that 'idx' is correct. */
17583 	callable = duk_is_callable(thr, -1);
17584 
17585 	/* At present finalizer is stored as a hidden Symbol, with normal
17586 	 * inheritance and access control.  As a result, finalizer cannot
17587 	 * currently be set on a non-extensible (sealed or frozen) object.
17588 	 * It might be useful to allow it.
17589 	 */
17590 	duk_put_prop_stridx(thr, idx, DUK_STRIDX_INT_FINALIZER);
17591 
17592 	/* In addition to setting the finalizer property, keep a "have
17593 	 * finalizer" flag in duk_hobject in sync so that refzero can do
17594 	 * a very quick finalizer check by walking the prototype chain
17595 	 * and checking the flag alone.  (Note that this means that just
17596 	 * setting _Finalizer on an object won't affect finalizer checks.)
17597 	 *
17598 	 * NOTE: if the argument is a Proxy object, this flag will be set
17599 	 * on the Proxy, not the target.  As a result, the target won't get
17600 	 * a finalizer flag and the Proxy also won't be finalized as there's
17601 	 * an explicit Proxy check in finalization now.
17602 	 */
17603 	if (callable) {
17604 		DUK_HOBJECT_SET_HAVE_FINALIZER(h);
17605 	} else {
17606 		DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h);
17607 	}
17608 }
17609 #else  /* DUK_USE_FINALIZER_SUPPORT */
duk_get_finalizer(duk_hthread * thr,duk_idx_t idx)17610 DUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx) {
17611 	DUK_ASSERT_API_ENTRY(thr);
17612 	DUK_UNREF(idx);
17613 	DUK_ERROR_UNSUPPORTED(thr);
17614 	DUK_WO_NORETURN(return;);
17615 }
17616 
duk_set_finalizer(duk_hthread * thr,duk_idx_t idx)17617 DUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) {
17618 	DUK_ASSERT_API_ENTRY(thr);
17619 	DUK_UNREF(idx);
17620 	DUK_ERROR_UNSUPPORTED(thr);
17621 	DUK_WO_NORETURN(return;);
17622 }
17623 #endif  /* DUK_USE_FINALIZER_SUPPORT */
17624 /*
17625  *  Random numbers
17626  */
17627 
17628 /* #include duk_internal.h -> already included */
17629 
duk_random(duk_hthread * thr)17630 DUK_EXTERNAL duk_double_t duk_random(duk_hthread *thr) {
17631 	return (duk_double_t) DUK_UTIL_GET_RANDOM_DOUBLE(thr);
17632 }
17633 /*
17634  *  API calls related to general value stack manipulation: resizing the value
17635  *  stack, pushing and popping values, type checking and reading values,
17636  *  coercing values, etc.
17637  *
17638  *  Also contains internal functions (such as duk_get_tval()), defined
17639  *  in duk_api_internal.h, with semantics similar to the public API.
17640  */
17641 
17642 /* XXX: repetition of stack pre-checks -> helper or macro or inline */
17643 /* XXX: shared api error strings, and perhaps even throw code for rare cases? */
17644 
17645 /* #include duk_internal.h -> already included */
17646 
17647 /*
17648  *  Forward declarations
17649  */
17650 
17651 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);
17652 
17653 /*
17654  *  Global state for working around missing variadic macros
17655  */
17656 
17657 #if !defined(DUK_USE_VARIADIC_MACROS)
17658 DUK_EXTERNAL const char *duk_api_global_filename = NULL;
17659 DUK_EXTERNAL duk_int_t duk_api_global_line = 0;
17660 #endif
17661 
17662 /*
17663  *  Misc helpers
17664  */
17665 
17666 DUK_LOCAL const char * const duk__symbol_type_strings[4] = {
17667 	"hidden", "global", "local", "wellknown"
17668 };
17669 
17670 #if !defined(DUK_USE_PACKED_TVAL)
17671 DUK_LOCAL const duk_uint_t duk__type_from_tag[] = {
17672 	DUK_TYPE_NUMBER,
17673 	DUK_TYPE_NUMBER,  /* fastint */
17674 	DUK_TYPE_UNDEFINED,
17675 	DUK_TYPE_NULL,
17676 	DUK_TYPE_BOOLEAN,
17677 	DUK_TYPE_POINTER,
17678 	DUK_TYPE_LIGHTFUNC,
17679 	DUK_TYPE_NONE,
17680 	DUK_TYPE_STRING,
17681 	DUK_TYPE_OBJECT,
17682 	DUK_TYPE_BUFFER,
17683 };
17684 DUK_LOCAL const duk_uint_t duk__type_mask_from_tag[] = {
17685 	DUK_TYPE_MASK_NUMBER,
17686 	DUK_TYPE_MASK_NUMBER,  /* fastint */
17687 	DUK_TYPE_MASK_UNDEFINED,
17688 	DUK_TYPE_MASK_NULL,
17689 	DUK_TYPE_MASK_BOOLEAN,
17690 	DUK_TYPE_MASK_POINTER,
17691 	DUK_TYPE_MASK_LIGHTFUNC,
17692 	DUK_TYPE_MASK_NONE,
17693 	DUK_TYPE_MASK_STRING,
17694 	DUK_TYPE_MASK_OBJECT,
17695 	DUK_TYPE_MASK_BUFFER,
17696 };
17697 #endif  /* !DUK_USE_PACKED_TVAL */
17698 
17699 /* Assert that there's room for one value. */
17700 #define DUK__ASSERT_SPACE() do { \
17701 		DUK_ASSERT(!(thr->valstack_top >= thr->valstack_end)); \
17702 	} while (0)
17703 
17704 /* Check that there's room to push one value. */
17705 #if defined(DUK_USE_VALSTACK_UNSAFE)
17706 /* Faster but value stack overruns are memory unsafe. */
17707 #define DUK__CHECK_SPACE() DUK__ASSERT_SPACE()
17708 #else
17709 #define DUK__CHECK_SPACE() do { \
17710 		if (DUK_UNLIKELY(thr->valstack_top >= thr->valstack_end)) { \
17711 			DUK_ERROR_RANGE_PUSH_BEYOND(thr); \
17712 		} \
17713 	} while (0)
17714 #endif
17715 
duk__get_symbol_type(duk_hstring * h)17716 DUK_LOCAL duk_small_uint_t duk__get_symbol_type(duk_hstring *h) {
17717 	const duk_uint8_t *data;
17718 	duk_size_t len;
17719 
17720 	DUK_ASSERT(h != NULL);
17721 	DUK_ASSERT(DUK_HSTRING_HAS_SYMBOL(h));
17722 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h) >= 1);  /* always true, symbol prefix */
17723 
17724 	data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
17725 	len = DUK_HSTRING_GET_BYTELEN(h);
17726 	DUK_ASSERT(len >= 1);
17727 
17728 	/* XXX: differentiate between 0x82 and 0xff (hidden vs. internal?)? */
17729 
17730 	if (data[0] == 0xffU) {
17731 		return DUK_SYMBOL_TYPE_HIDDEN;
17732 	} else if (data[0] == 0x82U) {
17733 		return DUK_SYMBOL_TYPE_HIDDEN;
17734 	} else if (data[0] == 0x80U) {
17735 		return DUK_SYMBOL_TYPE_GLOBAL;
17736 	} else if (data[len - 1] != 0xffU) {
17737 		return DUK_SYMBOL_TYPE_LOCAL;
17738 	} else {
17739 		return DUK_SYMBOL_TYPE_WELLKNOWN;
17740 	}
17741 }
17742 
duk__get_symbol_type_string(duk_hstring * h)17743 DUK_LOCAL const char *duk__get_symbol_type_string(duk_hstring *h) {
17744 	duk_small_uint_t idx;
17745 	idx = duk__get_symbol_type(h);
17746 	DUK_ASSERT(idx < sizeof(duk__symbol_type_strings));
17747 	return duk__symbol_type_strings[idx];
17748 }
17749 
17750 DUK_LOCAL_DECL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t tag);
17751 
duk__api_coerce_d2i(duk_hthread * thr,duk_idx_t idx,duk_int_t def_value,duk_bool_t require)17752 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) {
17753 	duk_tval *tv;
17754 	duk_small_int_t c;
17755 	duk_double_t d;
17756 
17757 	tv = duk_get_tval_or_unused(thr, idx);
17758 	DUK_ASSERT(tv != NULL);
17759 
17760 	/*
17761 	 *  Special cases like NaN and +/- Infinity are handled explicitly
17762 	 *  because a plain C coercion from double to int handles these cases
17763 	 *  in undesirable ways.  For instance, NaN may coerce to INT_MIN
17764 	 *  (not zero), and INT_MAX + 1 may coerce to INT_MIN (not INT_MAX).
17765 	 *
17766 	 *  This double-to-int coercion differs from ToInteger() because it
17767 	 *  has a finite range (ToInteger() allows e.g. +/- Infinity).  It
17768 	 *  also differs from ToInt32() because the INT_MIN/INT_MAX clamping
17769 	 *  depends on the size of the int type on the platform.  In particular,
17770 	 *  on platforms with a 64-bit int type, the full range is allowed.
17771 	 */
17772 
17773 #if defined(DUK_USE_FASTINT)
17774 	if (DUK_TVAL_IS_FASTINT(tv)) {
17775 		duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
17776 #if (DUK_INT_MAX <= 0x7fffffffL)
17777 		/* Clamping only necessary for 32-bit ints. */
17778 		if (t < DUK_INT_MIN) {
17779 			t = DUK_INT_MIN;
17780 		} else if (t > DUK_INT_MAX) {
17781 			t = DUK_INT_MAX;
17782 		}
17783 #endif
17784 		return (duk_int_t) t;
17785 	}
17786 #endif
17787 
17788 	if (DUK_TVAL_IS_NUMBER(tv)) {
17789 		d = DUK_TVAL_GET_NUMBER(tv);
17790 		c = (duk_small_int_t) DUK_FPCLASSIFY(d);
17791 		if (c == DUK_FP_NAN) {
17792 			return 0;
17793 		} else if (d < (duk_double_t) DUK_INT_MIN) {
17794 			/* covers -Infinity */
17795 			return DUK_INT_MIN;
17796 		} else if (d > (duk_double_t) DUK_INT_MAX) {
17797 			/* covers +Infinity */
17798 			return DUK_INT_MAX;
17799 		} else {
17800 			/* coerce towards zero */
17801 			return (duk_int_t) d;
17802 		}
17803 	}
17804 
17805 	if (require) {
17806 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
17807 		DUK_WO_NORETURN(return 0;);
17808 	}
17809 
17810 	return def_value;
17811 }
17812 
duk__api_coerce_d2ui(duk_hthread * thr,duk_idx_t idx,duk_uint_t def_value,duk_bool_t require)17813 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) {
17814 	duk_tval *tv;
17815 	duk_small_int_t c;
17816 	duk_double_t d;
17817 
17818 	/* Same as above but for unsigned int range. */
17819 
17820 	tv = duk_get_tval_or_unused(thr, idx);
17821 	DUK_ASSERT(tv != NULL);
17822 
17823 #if defined(DUK_USE_FASTINT)
17824 	if (DUK_TVAL_IS_FASTINT(tv)) {
17825 		duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
17826 		if (t < 0) {
17827 			t = 0;
17828 		}
17829 #if (DUK_UINT_MAX <= 0xffffffffUL)
17830 		/* Clamping only necessary for 32-bit ints. */
17831 		else if (t > DUK_UINT_MAX) {
17832 			t = DUK_UINT_MAX;
17833 		}
17834 #endif
17835 		return (duk_uint_t) t;
17836 	}
17837 #endif
17838 
17839 	if (DUK_TVAL_IS_NUMBER(tv)) {
17840 		d = DUK_TVAL_GET_NUMBER(tv);
17841 		c = (duk_small_int_t) DUK_FPCLASSIFY(d);
17842 		if (c == DUK_FP_NAN) {
17843 			return 0;
17844 		} else if (d < 0.0) {
17845 			/* covers -Infinity */
17846 			return (duk_uint_t) 0;
17847 		} else if (d > (duk_double_t) DUK_UINT_MAX) {
17848 			/* covers +Infinity */
17849 			return (duk_uint_t) DUK_UINT_MAX;
17850 		} else {
17851 			/* coerce towards zero */
17852 			return (duk_uint_t) d;
17853 		}
17854 	}
17855 
17856 	if (require) {
17857 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
17858 		DUK_WO_NORETURN(return 0;);
17859 	}
17860 
17861 	return def_value;
17862 }
17863 
17864 /*
17865  *  Stack index validation/normalization and getting a stack duk_tval ptr.
17866  *
17867  *  These are called by many API entrypoints so the implementations must be
17868  *  fast and "inlined".
17869  *
17870  *  There's some repetition because of this; keep the functions in sync.
17871  */
17872 
duk_normalize_index(duk_hthread * thr,duk_idx_t idx)17873 DUK_EXTERNAL duk_idx_t duk_normalize_index(duk_hthread *thr, duk_idx_t idx) {
17874 	duk_uidx_t vs_size;
17875 	duk_uidx_t uidx;
17876 
17877 	DUK_ASSERT_API_ENTRY(thr);
17878 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
17879 
17880 	/* Care must be taken to avoid pointer wrapping in the index
17881 	 * validation.  For instance, on a 32-bit platform with 8-byte
17882 	 * duk_tval the index 0x20000000UL would wrap the memory space
17883 	 * once.
17884 	 */
17885 
17886 	/* Assume value stack sizes (in elements) fits into duk_idx_t. */
17887 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
17888 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
17889 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
17890 
17891 	if (idx < 0) {
17892 		uidx = vs_size + (duk_uidx_t) idx;
17893 	} else {
17894 		/* since index non-negative */
17895 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
17896 		uidx = (duk_uidx_t) idx;
17897 	}
17898 
17899 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
17900 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
17901 
17902 	if (DUK_LIKELY(uidx < vs_size)) {
17903 		return (duk_idx_t) uidx;
17904 	}
17905 	return DUK_INVALID_INDEX;
17906 }
17907 
duk_require_normalize_index(duk_hthread * thr,duk_idx_t idx)17908 DUK_EXTERNAL duk_idx_t duk_require_normalize_index(duk_hthread *thr, duk_idx_t idx) {
17909 	duk_uidx_t vs_size;
17910 	duk_uidx_t uidx;
17911 
17912 	DUK_ASSERT_API_ENTRY(thr);
17913 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
17914 
17915 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
17916 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
17917 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
17918 
17919 	if (idx < 0) {
17920 		uidx = vs_size + (duk_uidx_t) idx;
17921 	} else {
17922 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
17923 		uidx = (duk_uidx_t) idx;
17924 	}
17925 
17926 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
17927 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
17928 
17929 	if (DUK_LIKELY(uidx < vs_size)) {
17930 		return (duk_idx_t) uidx;
17931 	}
17932 	DUK_ERROR_RANGE_INDEX(thr, idx);
17933 	DUK_WO_NORETURN(return 0;);
17934 }
17935 
duk_get_tval(duk_hthread * thr,duk_idx_t idx)17936 DUK_INTERNAL duk_tval *duk_get_tval(duk_hthread *thr, duk_idx_t idx) {
17937 	duk_uidx_t vs_size;
17938 	duk_uidx_t uidx;
17939 
17940 	DUK_ASSERT_API_ENTRY(thr);
17941 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
17942 
17943 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
17944 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
17945 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
17946 
17947 	if (idx < 0) {
17948 		uidx = vs_size + (duk_uidx_t) idx;
17949 	} else {
17950 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
17951 		uidx = (duk_uidx_t) idx;
17952 	}
17953 
17954 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
17955 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
17956 
17957 	if (DUK_LIKELY(uidx < vs_size)) {
17958 		return thr->valstack_bottom + uidx;
17959 	}
17960 	return NULL;
17961 }
17962 
17963 /* Variant of duk_get_tval() which is guaranteed to return a valid duk_tval
17964  * pointer.  When duk_get_tval() would return NULL, this variant returns a
17965  * pointer to a duk_tval with tag DUK_TAG_UNUSED.  This allows the call site
17966  * to avoid an unnecessary NULL check which sometimes leads to better code.
17967  * The return duk_tval is read only (at least for the UNUSED value).
17968  */
17969 DUK_LOCAL const duk_tval_unused duk__const_tval_unused = DUK_TVAL_UNUSED_INITIALIZER();
17970 
duk_get_tval_or_unused(duk_hthread * thr,duk_idx_t idx)17971 DUK_INTERNAL duk_tval *duk_get_tval_or_unused(duk_hthread *thr, duk_idx_t idx) {
17972 	duk_tval *tv;
17973 
17974 	DUK_ASSERT_API_ENTRY(thr);
17975 
17976 	tv = duk_get_tval(thr, idx);
17977 	if (tv != NULL) {
17978 		return tv;
17979 	}
17980 	return (duk_tval *) DUK_LOSE_CONST(&duk__const_tval_unused);
17981 }
17982 
duk_require_tval(duk_hthread * thr,duk_idx_t idx)17983 DUK_INTERNAL duk_tval *duk_require_tval(duk_hthread *thr, duk_idx_t idx) {
17984 	duk_uidx_t vs_size;
17985 	duk_uidx_t uidx;
17986 
17987 	DUK_ASSERT_API_ENTRY(thr);
17988 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
17989 
17990 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
17991 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
17992 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
17993 
17994 	/* Use unsigned arithmetic to optimize comparison. */
17995 	if (idx < 0) {
17996 		uidx = vs_size + (duk_uidx_t) idx;
17997 	} else {
17998 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
17999 		uidx = (duk_uidx_t) idx;
18000 	}
18001 
18002 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
18003 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
18004 
18005 	if (DUK_LIKELY(uidx < vs_size)) {
18006 		return thr->valstack_bottom + uidx;
18007 	}
18008 	DUK_ERROR_RANGE_INDEX(thr, idx);
18009 	DUK_WO_NORETURN(return NULL;);
18010 }
18011 
18012 /* Non-critical. */
duk_is_valid_index(duk_hthread * thr,duk_idx_t idx)18013 DUK_EXTERNAL duk_bool_t duk_is_valid_index(duk_hthread *thr, duk_idx_t idx) {
18014 	DUK_ASSERT_API_ENTRY(thr);
18015 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
18016 
18017 	return (duk_normalize_index(thr, idx) >= 0);
18018 }
18019 
18020 /* Non-critical. */
duk_require_valid_index(duk_hthread * thr,duk_idx_t idx)18021 DUK_EXTERNAL void duk_require_valid_index(duk_hthread *thr, duk_idx_t idx) {
18022 	DUK_ASSERT_API_ENTRY(thr);
18023 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
18024 
18025 	if (DUK_UNLIKELY(duk_normalize_index(thr, idx) < 0)) {
18026 		DUK_ERROR_RANGE_INDEX(thr, idx);
18027 		DUK_WO_NORETURN(return;);
18028 	}
18029 }
18030 
18031 /*
18032  *  Value stack top handling
18033  */
18034 
duk_get_top(duk_hthread * thr)18035 DUK_EXTERNAL duk_idx_t duk_get_top(duk_hthread *thr) {
18036 	DUK_ASSERT_API_ENTRY(thr);
18037 
18038 	return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
18039 }
18040 
18041 /* Internal helper to get current top but to require a minimum top value
18042  * (TypeError if not met).
18043  */
duk_get_top_require_min(duk_hthread * thr,duk_idx_t min_top)18044 DUK_INTERNAL duk_idx_t duk_get_top_require_min(duk_hthread *thr, duk_idx_t min_top) {
18045 	duk_idx_t ret;
18046 
18047 	DUK_ASSERT_API_ENTRY(thr);
18048 
18049 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
18050 	if (DUK_UNLIKELY(ret < min_top)) {
18051 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
18052 		DUK_WO_NORETURN(return 0;);
18053 	}
18054 	return ret;
18055 }
18056 
18057 /* Set stack top within currently allocated range, but don't reallocate.
18058  * This is performance critical especially for call handling, so whenever
18059  * changing, profile and look at generated code.
18060  */
duk_set_top(duk_hthread * thr,duk_idx_t idx)18061 DUK_EXTERNAL void duk_set_top(duk_hthread *thr, duk_idx_t idx) {
18062 	duk_uidx_t vs_size;
18063 	duk_uidx_t vs_limit;
18064 	duk_uidx_t uidx;
18065 	duk_tval *tv;
18066 
18067 	DUK_ASSERT_API_ENTRY(thr);
18068 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
18069 
18070 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18071 	DUK_ASSERT(thr->valstack_end >= thr->valstack_bottom);
18072 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18073 	vs_limit = (duk_uidx_t) (thr->valstack_end - thr->valstack_bottom);
18074 
18075 	if (idx < 0) {
18076 		/* Negative indices are always within allocated stack but
18077 		 * must not go below zero index.
18078 		 */
18079 		uidx = vs_size + (duk_uidx_t) idx;
18080 	} else {
18081 		/* Positive index can be higher than valstack top but must
18082 		 * not go above allocated stack (equality is OK).
18083 		 */
18084 		uidx = (duk_uidx_t) idx;
18085 	}
18086 
18087 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
18088 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
18089 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_limit);
18090 
18091 #if defined(DUK_USE_VALSTACK_UNSAFE)
18092 	DUK_ASSERT(uidx <= vs_limit);
18093 	DUK_UNREF(vs_limit);
18094 #else
18095 	if (DUK_UNLIKELY(uidx > vs_limit)) {
18096 		DUK_ERROR_RANGE_INDEX(thr, idx);
18097 		DUK_WO_NORETURN(return;);
18098 	}
18099 #endif
18100 	DUK_ASSERT(uidx <= vs_limit);
18101 
18102 	/* Handle change in value stack top.  Respect value stack
18103 	 * initialization policy: 'undefined' above top.  Note that
18104 	 * DECREF may cause a side effect that reallocates valstack,
18105 	 * so must relookup after DECREF.
18106 	 */
18107 
18108 	if (uidx >= vs_size) {
18109 		/* Stack size increases or stays the same. */
18110 #if defined(DUK_USE_ASSERTIONS)
18111 		duk_uidx_t count;
18112 
18113 		count = uidx - vs_size;
18114 		while (count != 0) {
18115 			count--;
18116 			tv = thr->valstack_top + count;
18117 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
18118 		}
18119 #endif
18120 		thr->valstack_top = thr->valstack_bottom + uidx;
18121 	} else {
18122 		/* Stack size decreases. */
18123 #if defined(DUK_USE_REFERENCE_COUNTING)
18124 		duk_uidx_t count;
18125 		duk_tval *tv_end;
18126 
18127 		count = vs_size - uidx;
18128 		DUK_ASSERT(count > 0);
18129 		tv = thr->valstack_top;
18130 		tv_end = tv - count;
18131 		DUK_ASSERT(tv > tv_end);  /* Because count > 0. */
18132 		do {
18133 			tv--;
18134 			DUK_ASSERT(tv >= thr->valstack_bottom);
18135 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
18136 		} while (tv != tv_end);
18137 		thr->valstack_top = tv_end;
18138 		DUK_REFZERO_CHECK_FAST(thr);
18139 #else  /* DUK_USE_REFERENCE_COUNTING */
18140 		duk_uidx_t count;
18141 		duk_tval *tv_end;
18142 
18143 		count = vs_size - uidx;
18144 		tv = thr->valstack_top;
18145 		tv_end = tv - count;
18146 		DUK_ASSERT(tv > tv_end);
18147 		do {
18148 			tv--;
18149 			DUK_TVAL_SET_UNDEFINED(tv);
18150 		} while (tv != tv_end);
18151 		thr->valstack_top = tv_end;
18152 #endif  /* DUK_USE_REFERENCE_COUNTING */
18153 	}
18154 }
18155 
18156 /* Internal variant with a non-negative index and no runtime size checks. */
18157 #if defined(DUK_USE_PREFER_SIZE)
duk_set_top_unsafe(duk_hthread * thr,duk_idx_t idx)18158 DUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {
18159 	DUK_ASSERT_API_ENTRY(thr);
18160 
18161 	duk_set_top(thr, idx);
18162 }
18163 #else  /* DUK_USE_PREFER_SIZE */
duk_set_top_unsafe(duk_hthread * thr,duk_idx_t idx)18164 DUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {
18165 	duk_uidx_t uidx;
18166 	duk_uidx_t vs_size;
18167 	duk_tval *tv;
18168 
18169 	DUK_ASSERT_API_ENTRY(thr);
18170 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18171 	DUK_ASSERT(thr->valstack_end >= thr->valstack_bottom);
18172 	DUK_ASSERT(idx >= 0);
18173 	DUK_ASSERT(idx <= (duk_idx_t) (thr->valstack_end - thr->valstack_bottom));
18174 
18175 	/* XXX: byte arithmetic */
18176 	uidx = (duk_uidx_t) idx;
18177 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18178 
18179 	if (uidx >= vs_size) {
18180 		/* Stack size increases or stays the same. */
18181 #if defined(DUK_USE_ASSERTIONS)
18182 		duk_uidx_t count;
18183 
18184 		count = uidx - vs_size;
18185 		while (count != 0) {
18186 			count--;
18187 			tv = thr->valstack_top + count;
18188 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
18189 		}
18190 #endif
18191 		thr->valstack_top = thr->valstack_bottom + uidx;
18192 	} else {
18193 		/* Stack size decreases. */
18194 #if defined(DUK_USE_REFERENCE_COUNTING)
18195 		duk_uidx_t count;
18196 		duk_tval *tv_end;
18197 
18198 		count = vs_size - uidx;
18199 		DUK_ASSERT(count > 0);
18200 		tv = thr->valstack_top;
18201 		tv_end = tv - count;
18202 		DUK_ASSERT(tv > tv_end);  /* Because count > 0. */
18203 		do {
18204 			tv--;
18205 			DUK_ASSERT(tv >= thr->valstack_bottom);
18206 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
18207 		} while (tv != tv_end);
18208 		thr->valstack_top = tv_end;
18209 		DUK_REFZERO_CHECK_FAST(thr);
18210 #else  /* DUK_USE_REFERENCE_COUNTING */
18211 		duk_uidx_t count;
18212 		duk_tval *tv_end;
18213 
18214 		count = vs_size - uidx;
18215 		tv = thr->valstack_top;
18216 		tv_end = tv - count;
18217 		DUK_ASSERT(tv > tv_end);
18218 		do {
18219 			tv--;
18220 			DUK_TVAL_SET_UNDEFINED(tv);
18221 		} while (tv != tv_end);
18222 		thr->valstack_top = tv_end;
18223 #endif  /* DUK_USE_REFERENCE_COUNTING */
18224 	}
18225 }
18226 #endif  /* DUK_USE_PREFER_SIZE */
18227 
18228 /* Internal helper: set top to 'top', and set [idx_wipe_start,top[ to
18229  * 'undefined' (doing nothing if idx_wipe_start == top).  Indices are
18230  * positive and within value stack reserve.  This is used by call handling.
18231  */
duk_set_top_and_wipe(duk_hthread * thr,duk_idx_t top,duk_idx_t idx_wipe_start)18232 DUK_INTERNAL void duk_set_top_and_wipe(duk_hthread *thr, duk_idx_t top, duk_idx_t idx_wipe_start) {
18233 	DUK_ASSERT_API_ENTRY(thr);
18234 	DUK_ASSERT(top >= 0);
18235 	DUK_ASSERT(idx_wipe_start >= 0);
18236 	DUK_ASSERT(idx_wipe_start <= top);
18237 	DUK_ASSERT(thr->valstack_bottom + top <= thr->valstack_end);
18238 	DUK_ASSERT(thr->valstack_bottom + idx_wipe_start <= thr->valstack_end);
18239 
18240 	duk_set_top_unsafe(thr, idx_wipe_start);
18241 	duk_set_top_unsafe(thr, top);
18242 }
18243 
duk_get_top_index(duk_hthread * thr)18244 DUK_EXTERNAL duk_idx_t duk_get_top_index(duk_hthread *thr) {
18245 	duk_idx_t ret;
18246 
18247 	DUK_ASSERT_API_ENTRY(thr);
18248 
18249 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
18250 	if (DUK_UNLIKELY(ret < 0)) {
18251 		/* Return invalid index; if caller uses this without checking
18252 		 * in another API call, the index won't map to a valid stack
18253 		 * entry.
18254 		 */
18255 		return DUK_INVALID_INDEX;
18256 	}
18257 	return ret;
18258 }
18259 
18260 /* Internal variant: call assumes there is at least one element on the value
18261  * stack frame; this is only asserted for.
18262  */
duk_get_top_index_unsafe(duk_hthread * thr)18263 DUK_INTERNAL duk_idx_t duk_get_top_index_unsafe(duk_hthread *thr) {
18264 	duk_idx_t ret;
18265 
18266 	DUK_ASSERT_API_ENTRY(thr);
18267 
18268 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
18269 	return ret;
18270 }
18271 
duk_require_top_index(duk_hthread * thr)18272 DUK_EXTERNAL duk_idx_t duk_require_top_index(duk_hthread *thr) {
18273 	duk_idx_t ret;
18274 
18275 	DUK_ASSERT_API_ENTRY(thr);
18276 
18277 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
18278 	if (DUK_UNLIKELY(ret < 0)) {
18279 		DUK_ERROR_RANGE_INDEX(thr, -1);
18280 		DUK_WO_NORETURN(return 0;);
18281 	}
18282 	return ret;
18283 }
18284 
18285 /*
18286  *  Value stack resizing.
18287  *
18288  *  This resizing happens above the current "top": the value stack can be
18289  *  grown or shrunk, but the "top" is not affected.  The value stack cannot
18290  *  be resized to a size below the current reserve.
18291  *
18292  *  The low level reallocation primitive must carefully recompute all value
18293  *  stack pointers, and must also work if ALL pointers are NULL.  The resize
18294  *  is quite tricky because the valstack realloc may cause a mark-and-sweep,
18295  *  which may run finalizers.  Running finalizers may resize the valstack
18296  *  recursively (the same value stack we're working on).  So, after realloc
18297  *  returns, we know that the valstack bottom, top, and reserve should still
18298  *  be the same (there should not be live values above the "top"), but its
18299  *  underlying size, alloc_end, and base pointer may have changed.
18300  *
18301  *  'new_size' is known to be <= DUK_USE_VALSTACK_LIMIT, which ensures that
18302  *  size_t and pointer arithmetic won't wrap in duk__resize_valstack().
18303  */
18304 
18305 /* Low level valstack resize primitive, used for both grow and shrink.  All
18306  * adjustments for slack etc have already been done.  Doesn't throw but does
18307  * have allocation side effects.
18308  */
duk__resize_valstack(duk_hthread * thr,duk_size_t new_size)18309 DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__resize_valstack(duk_hthread *thr, duk_size_t new_size) {
18310 	duk_tval *pre_valstack;
18311 	duk_tval *pre_bottom;
18312 	duk_tval *pre_top;
18313 	duk_tval *pre_end;
18314 	duk_tval *pre_alloc_end;
18315 	duk_ptrdiff_t ptr_diff;
18316 	duk_tval *new_valstack;
18317 	duk_size_t new_alloc_size;
18318 	duk_tval *tv_prev_alloc_end;
18319 	duk_tval *p;
18320 
18321 	DUK_HTHREAD_ASSERT_VALID(thr);
18322 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
18323 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18324 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
18325 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18326 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) <= new_size);  /* can't resize below 'top' */
18327 	DUK_ASSERT(new_size <= DUK_USE_VALSTACK_LIMIT);  /* valstack limit caller has check, prevents wrapping */
18328 	DUK_ASSERT(new_size <= DUK_SIZE_MAX / sizeof(duk_tval));  /* specific assert for wrapping */
18329 
18330 	/* Pre-realloc pointer copies for asserts and debug logs. */
18331 	pre_valstack = thr->valstack;
18332 	pre_bottom = thr->valstack_bottom;
18333 	pre_top = thr->valstack_top;
18334 	pre_end = thr->valstack_end;
18335 	pre_alloc_end = thr->valstack_alloc_end;
18336 
18337 	DUK_UNREF(pre_valstack);
18338 	DUK_UNREF(pre_bottom);
18339 	DUK_UNREF(pre_top);
18340 	DUK_UNREF(pre_end);
18341 	DUK_UNREF(pre_alloc_end);
18342 
18343 	/* If finalizer torture enabled, force base pointer change every time
18344 	 * when it would be allowed.
18345 	 */
18346 #if defined(DUK_USE_FINALIZER_TORTURE)
18347 	if (thr->heap->pf_prevent_count == 0) {
18348 		duk_hthread_valstack_torture_realloc(thr);
18349 	}
18350 #endif
18351 
18352 	/* Allocate a new valstack using DUK_REALLOC_DIRECT() to deal with
18353 	 * a side effect changing the base pointer.
18354 	 */
18355 	new_alloc_size = sizeof(duk_tval) * new_size;
18356 	new_valstack = (duk_tval *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_valstack_ptr, (void *) thr, new_alloc_size);
18357 	if (DUK_UNLIKELY(new_valstack == NULL)) {
18358 		/* Because new_size != 0, if condition doesn't need to be
18359 		 * (new_valstack != NULL || new_size == 0).
18360 		 */
18361 		DUK_ASSERT(new_size != 0);
18362 		DUK_D(DUK_DPRINT("failed to resize valstack to %lu entries (%lu bytes)",
18363 		                 (unsigned long) new_size, (unsigned long) new_alloc_size));
18364 		return 0;
18365 	}
18366 
18367 	/* Debug log any changes in pointer(s) by side effects.  These don't
18368 	 * necessarily imply any incorrect behavior, but should be rare in
18369 	 * practice.
18370 	 */
18371 #if defined(DUK_USE_DEBUG)
18372 	if (thr->valstack != pre_valstack) {
18373 		DUK_D(DUK_DPRINT("valstack base pointer changed during valstack resize: %p -> %p",
18374 		                 (void *) pre_valstack, (void *) thr->valstack));
18375 	}
18376 	if (thr->valstack_bottom != pre_bottom) {
18377 		DUK_D(DUK_DPRINT("valstack bottom pointer changed during valstack resize: %p -> %p",
18378 		                 (void *) pre_bottom, (void *) thr->valstack_bottom));
18379 	}
18380 	if (thr->valstack_top != pre_top) {
18381 		DUK_D(DUK_DPRINT("valstack top pointer changed during valstack resize: %p -> %p",
18382 		                 (void *) pre_top, (void *) thr->valstack_top));
18383 	}
18384 	if (thr->valstack_end != pre_end) {
18385 		DUK_D(DUK_DPRINT("valstack end pointer changed during valstack resize: %p -> %p",
18386 		                 (void *) pre_end, (void *) thr->valstack_end));
18387 	}
18388 	if (thr->valstack_alloc_end != pre_alloc_end) {
18389 		DUK_D(DUK_DPRINT("valstack alloc_end pointer changed during valstack resize: %p -> %p",
18390 		                 (void *) pre_alloc_end, (void *) thr->valstack_alloc_end));
18391 	}
18392 #endif
18393 
18394 	/* Assertions: offsets for bottom, top, and end (reserve) must not
18395 	 * have changed even with side effects because they are always
18396 	 * restored in unwind.  For alloc_end there's no guarantee: it may
18397 	 * have grown or shrunk (but remain above 'end').
18398 	 */
18399 	DUK_ASSERT(thr->valstack_bottom - thr->valstack == pre_bottom - pre_valstack);
18400 	DUK_ASSERT(thr->valstack_top - thr->valstack == pre_top - pre_valstack);
18401 	DUK_ASSERT(thr->valstack_end - thr->valstack == pre_end - pre_valstack);
18402 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18403 
18404 	/* Write new pointers.  Most pointers can be handled as a pointer
18405 	 * difference.
18406 	 */
18407 	ptr_diff = (duk_ptrdiff_t) ((duk_uint8_t *) new_valstack - (duk_uint8_t *) thr->valstack);
18408 	tv_prev_alloc_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_alloc_end + ptr_diff);
18409 	thr->valstack = new_valstack;
18410 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + ptr_diff);
18411 	thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_top + ptr_diff);
18412 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_end + ptr_diff);
18413 	thr->valstack_alloc_end = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + new_alloc_size);
18414 
18415 	/* Assertions: pointer sanity after pointer updates. */
18416 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
18417 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18418 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
18419 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18420 
18421 	DUK_D(DUK_DPRINT("resized valstack %lu -> %lu elements (%lu -> %lu bytes): "
18422 	                 "base=%p -> %p, bottom=%p -> %p (%ld), top=%p -> %p (%ld), "
18423 	                 "end=%p -> %p (%ld), alloc_end=%p -> %p (%ld);"
18424 	                 " tv_prev_alloc_end=%p (-> %ld inits; <0 means shrink)",
18425 	                 (unsigned long) (pre_alloc_end - pre_valstack),
18426 	                 (unsigned long) new_size,
18427 	                 (unsigned long) ((duk_uint8_t *) pre_alloc_end - (duk_uint8_t *) pre_valstack),
18428 	                 (unsigned long) new_alloc_size,
18429 	                 (void *) pre_valstack, (void *) thr->valstack,
18430 	                 (void *) pre_bottom, (void *) thr->valstack_bottom, (long) (thr->valstack_bottom - thr->valstack),
18431 	                 (void *) pre_top, (void *) thr->valstack_top, (long) (thr->valstack_top - thr->valstack),
18432 	                 (void *) pre_end, (void *) thr->valstack_end, (long) (thr->valstack_end - thr->valstack),
18433 	                 (void *) pre_alloc_end, (void *) thr->valstack_alloc_end, (long) (thr->valstack_alloc_end - thr->valstack),
18434 	                 (void *) tv_prev_alloc_end, (long) (thr->valstack_alloc_end - tv_prev_alloc_end)));
18435 
18436 	/* If allocation grew, init any new slots to 'undefined'. */
18437 	p = tv_prev_alloc_end;
18438 	while (p < thr->valstack_alloc_end) {
18439 		/* Never executed if new size is smaller. */
18440 		DUK_TVAL_SET_UNDEFINED(p);
18441 		p++;
18442 	}
18443 
18444 	/* Assert for value stack initialization policy. */
18445 #if defined(DUK_USE_ASSERTIONS)
18446 	p = thr->valstack_top;
18447 	while (p < thr->valstack_alloc_end) {
18448 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(p));
18449 		p++;
18450 	}
18451 #endif
18452 
18453 	return 1;
18454 }
18455 
duk__valstack_grow(duk_hthread * thr,duk_size_t min_bytes,duk_bool_t throw_on_error)18456 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) {
18457 	duk_size_t min_size;
18458 	duk_size_t new_size;
18459 
18460 	DUK_ASSERT(min_bytes / sizeof(duk_tval) * sizeof(duk_tval) == min_bytes);
18461 	min_size = min_bytes / sizeof(duk_tval);  /* from bytes to slots */
18462 
18463 #if defined(DUK_USE_VALSTACK_GROW_SHIFT)
18464 	/* New size is minimum size plus a proportional slack, e.g. shift of
18465 	 * 2 means a 25% slack.
18466 	 */
18467 	new_size = min_size + (min_size >> DUK_USE_VALSTACK_GROW_SHIFT);
18468 #else
18469 	/* New size is tight with no slack.  This is sometimes preferred in
18470 	 * low memory environments.
18471 	 */
18472 	new_size = min_size;
18473 #endif
18474 
18475 	if (DUK_UNLIKELY(new_size > DUK_USE_VALSTACK_LIMIT || new_size < min_size /*wrap*/)) {
18476 		/* Note: may be triggered even if minimal new_size would not reach the limit,
18477 		 * plan limit accordingly.
18478 		 */
18479 		if (throw_on_error) {
18480 			DUK_ERROR_RANGE(thr, DUK_STR_VALSTACK_LIMIT);
18481 			DUK_WO_NORETURN(return 0;);
18482 		}
18483 		return 0;
18484 	}
18485 
18486 	if (duk__resize_valstack(thr, new_size) == 0) {
18487 		if (throw_on_error) {
18488 			DUK_ERROR_ALLOC_FAILED(thr);
18489 			DUK_WO_NORETURN(return 0;);
18490 		}
18491 		return 0;
18492 	}
18493 
18494 	thr->valstack_end = thr->valstack + min_size;
18495 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18496 
18497 	return 1;
18498 }
18499 
18500 /* Hot, inlined value stack grow check.  Because value stack almost never
18501  * grows, the actual resize call is in a NOINLINE helper.
18502  */
duk_valstack_grow_check_throw(duk_hthread * thr,duk_size_t min_bytes)18503 DUK_INTERNAL DUK_INLINE void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes) {
18504 	duk_tval *tv;
18505 
18506 	tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + min_bytes);
18507 	if (DUK_LIKELY(thr->valstack_end >= tv)) {
18508 		return;
18509 	}
18510 	if (DUK_LIKELY(thr->valstack_alloc_end >= tv)) {
18511 		/* Values in [valstack_top,valstack_alloc_end[ are initialized
18512 		 * to 'undefined' so we can just move the end pointer.
18513 		 */
18514 		thr->valstack_end = tv;
18515 		return;
18516 	}
18517 	(void) duk__valstack_grow(thr, min_bytes, 1 /*throw_on_error*/);
18518 }
18519 
18520 /* Hot, inlined value stack grow check which doesn't throw. */
duk_valstack_grow_check_nothrow(duk_hthread * thr,duk_size_t min_bytes)18521 DUK_INTERNAL DUK_INLINE duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes) {
18522 	duk_tval *tv;
18523 
18524 	tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + min_bytes);
18525 	if (DUK_LIKELY(thr->valstack_end >= tv)) {
18526 		return 1;
18527 	}
18528 	if (DUK_LIKELY(thr->valstack_alloc_end >= tv)) {
18529 		thr->valstack_end = tv;
18530 		return 1;
18531 	}
18532 	return duk__valstack_grow(thr, min_bytes, 0 /*throw_on_error*/);
18533 }
18534 
18535 /* Value stack shrink check, called from mark-and-sweep. */
duk_valstack_shrink_check_nothrow(duk_hthread * thr,duk_bool_t snug)18536 DUK_INTERNAL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t snug) {
18537 	duk_size_t alloc_bytes;
18538 	duk_size_t reserve_bytes;
18539 	duk_size_t shrink_bytes;
18540 
18541 	alloc_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_alloc_end - (duk_uint8_t *) thr->valstack);
18542 	reserve_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
18543 	DUK_ASSERT(alloc_bytes >= reserve_bytes);
18544 
18545 	/* We're free to shrink the value stack allocation down to
18546 	 * reserve_bytes but not more.  If 'snug' (emergency GC)
18547 	 * shrink whatever we can.  Otherwise only shrink if the new
18548 	 * size would be considerably smaller.
18549 	 */
18550 
18551 #if defined(DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT)
18552 	if (snug) {
18553 		shrink_bytes = reserve_bytes;
18554 	} else {
18555 		duk_size_t proportion, slack;
18556 
18557 		/* Require that value stack shrinks by at least X% of its
18558 		 * current size.  For example, shift of 2 means at least
18559 		 * 25%.  The proportion is computed as bytes and may not
18560 		 * be a multiple of sizeof(duk_tval); that's OK here.
18561 		 */
18562 		proportion = alloc_bytes >> DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT;
18563 		if (alloc_bytes - reserve_bytes < proportion) {
18564 			/* Too little would be freed, do nothing. */
18565 			return;
18566 		}
18567 
18568 		/* Keep a slack after shrinking.  The slack is again a
18569 		 * proportion of the current size (the proportion should
18570 		 * of course be smaller than the check proportion above).
18571 		 */
18572 #if defined(DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT)
18573 		DUK_ASSERT(DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT > DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT);
18574 		slack = alloc_bytes >> DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT;
18575 #else
18576 		slack = 0;
18577 #endif
18578 		shrink_bytes = reserve_bytes +
18579 		               slack / sizeof(duk_tval) * sizeof(duk_tval);  /* multiple of duk_tval */
18580 	}
18581 #else  /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */
18582 	/* Always snug, useful in some low memory environments. */
18583 	DUK_UNREF(snug);
18584 	shrink_bytes = reserve_bytes;
18585 #endif  /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */
18586 
18587 	DUK_D(DUK_DPRINT("valstack shrink check: alloc_bytes=%ld, reserve_bytes=%ld, shrink_bytes=%ld (unvalidated)",
18588 	                 (long) alloc_bytes, (long) reserve_bytes, (long) shrink_bytes));
18589 	DUK_ASSERT(shrink_bytes >= reserve_bytes);
18590 	if (shrink_bytes >= alloc_bytes) {
18591 		/* Skip if shrink target is same as current one (or higher,
18592 		 * though that shouldn't happen in practice).
18593 		 */
18594 		return;
18595 	}
18596 	DUK_ASSERT(shrink_bytes / sizeof(duk_tval) * sizeof(duk_tval) == shrink_bytes);
18597 
18598 	DUK_D(DUK_DPRINT("valstack shrink check: decided to shrink, snug: %ld", (long) snug));
18599 
18600 	duk__resize_valstack(thr, shrink_bytes / sizeof(duk_tval));
18601 }
18602 
duk_check_stack(duk_hthread * thr,duk_idx_t extra)18603 DUK_EXTERNAL duk_bool_t duk_check_stack(duk_hthread *thr, duk_idx_t extra) {
18604 	duk_size_t min_new_bytes;
18605 
18606 	DUK_ASSERT_API_ENTRY(thr);
18607 	DUK_ASSERT(thr != NULL);
18608 
18609 	if (DUK_UNLIKELY(extra < 0 || extra > DUK_USE_VALSTACK_LIMIT)) {
18610 		if (extra < 0) {
18611 			/* Clamping to zero makes the API more robust to calling code
18612 			 * calculation errors.
18613 			 */
18614 			extra = 0;
18615 		} else {
18616 			/* Cause grow check to fail without wrapping arithmetic. */
18617 			extra = DUK_USE_VALSTACK_LIMIT;
18618 		}
18619 	}
18620 
18621 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack) +
18622 	                sizeof(duk_tval) * ((duk_size_t) extra + DUK_VALSTACK_INTERNAL_EXTRA);
18623 	return duk_valstack_grow_check_nothrow(thr, min_new_bytes);
18624 }
18625 
duk_require_stack(duk_hthread * thr,duk_idx_t extra)18626 DUK_EXTERNAL void duk_require_stack(duk_hthread *thr, duk_idx_t extra) {
18627 	duk_size_t min_new_bytes;
18628 
18629 	DUK_ASSERT_API_ENTRY(thr);
18630 	DUK_ASSERT(thr != NULL);
18631 
18632 	if (DUK_UNLIKELY(extra < 0 || extra > DUK_USE_VALSTACK_LIMIT)) {
18633 		if (extra < 0) {
18634 			/* Clamping to zero makes the API more robust to calling code
18635 			 * calculation errors.
18636 			 */
18637 			extra = 0;
18638 		} else {
18639 			/* Cause grow check to fail without wrapping arithmetic. */
18640 			extra = DUK_USE_VALSTACK_LIMIT;
18641 		}
18642 	}
18643 
18644 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack) +
18645 	                sizeof(duk_tval) * ((duk_size_t) extra + DUK_VALSTACK_INTERNAL_EXTRA);
18646 	duk_valstack_grow_check_throw(thr, min_new_bytes);
18647 }
18648 
duk_check_stack_top(duk_hthread * thr,duk_idx_t top)18649 DUK_EXTERNAL duk_bool_t duk_check_stack_top(duk_hthread *thr, duk_idx_t top) {
18650 	duk_size_t min_new_bytes;
18651 
18652 	DUK_ASSERT_API_ENTRY(thr);
18653 
18654 	if (DUK_UNLIKELY(top < 0 || top > DUK_USE_VALSTACK_LIMIT)) {
18655 		if (top < 0) {
18656 			/* Clamping to zero makes the API more robust to calling code
18657 			 * calculation errors.
18658 			 */
18659 			top = 0;
18660 		} else {
18661 			/* Cause grow check to fail without wrapping arithmetic. */
18662 			top = DUK_USE_VALSTACK_LIMIT;
18663 		}
18664 	}
18665 
18666 	DUK_ASSERT(top >= 0);
18667 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) +
18668 	                sizeof(duk_tval) * ((duk_size_t) top + DUK_VALSTACK_INTERNAL_EXTRA);
18669 	return duk_valstack_grow_check_nothrow(thr, min_new_bytes);
18670 }
18671 
duk_require_stack_top(duk_hthread * thr,duk_idx_t top)18672 DUK_EXTERNAL void duk_require_stack_top(duk_hthread *thr, duk_idx_t top) {
18673 	duk_size_t min_new_bytes;
18674 
18675 	DUK_ASSERT_API_ENTRY(thr);
18676 
18677 	if (DUK_UNLIKELY(top < 0 || top > DUK_USE_VALSTACK_LIMIT)) {
18678 		if (top < 0) {
18679 			/* Clamping to zero makes the API more robust to calling code
18680 			 * calculation errors.
18681 			 */
18682 			top = 0;
18683 		} else {
18684 			/* Cause grow check to fail without wrapping arithmetic. */
18685 			top = DUK_USE_VALSTACK_LIMIT;
18686 		}
18687 	}
18688 
18689 	DUK_ASSERT(top >= 0);
18690 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) +
18691 	                sizeof(duk_tval) * ((duk_size_t) top + DUK_VALSTACK_INTERNAL_EXTRA);
18692 	duk_valstack_grow_check_throw(thr, min_new_bytes);
18693 }
18694 
18695 /*
18696  *  Basic stack manipulation: swap, dup, insert, replace, etc
18697  */
18698 
duk_swap(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)18699 DUK_EXTERNAL void duk_swap(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
18700 	duk_tval *tv1;
18701 	duk_tval *tv2;
18702 	duk_tval tv_tmp;
18703 
18704 	DUK_ASSERT_API_ENTRY(thr);
18705 
18706 	tv1 = duk_require_tval(thr, idx1);
18707 	DUK_ASSERT(tv1 != NULL);
18708 	tv2 = duk_require_tval(thr, idx2);
18709 	DUK_ASSERT(tv2 != NULL);
18710 
18711 	/* If tv1==tv2 this is a NOP, no check is needed */
18712 	DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
18713 	DUK_TVAL_SET_TVAL(tv1, tv2);
18714 	DUK_TVAL_SET_TVAL(tv2, &tv_tmp);
18715 }
18716 
duk_swap_top(duk_hthread * thr,duk_idx_t idx)18717 DUK_EXTERNAL void duk_swap_top(duk_hthread *thr, duk_idx_t idx) {
18718 	DUK_ASSERT_API_ENTRY(thr);
18719 
18720 	duk_swap(thr, idx, -1);
18721 }
18722 
duk_dup(duk_hthread * thr,duk_idx_t from_idx)18723 DUK_EXTERNAL void duk_dup(duk_hthread *thr, duk_idx_t from_idx) {
18724 	duk_tval *tv_from;
18725 	duk_tval *tv_to;
18726 
18727 	DUK_ASSERT_API_ENTRY(thr);
18728 	DUK__CHECK_SPACE();
18729 
18730 	tv_from = duk_require_tval(thr, from_idx);
18731 	tv_to = thr->valstack_top++;
18732 	DUK_ASSERT(tv_from != NULL);
18733 	DUK_ASSERT(tv_to != NULL);
18734 	DUK_TVAL_SET_TVAL(tv_to, tv_from);
18735 	DUK_TVAL_INCREF(thr, tv_to);  /* no side effects */
18736 }
18737 
duk_dup_top(duk_hthread * thr)18738 DUK_EXTERNAL void duk_dup_top(duk_hthread *thr) {
18739 #if defined(DUK_USE_PREFER_SIZE)
18740 	duk_dup(thr, -1);
18741 #else
18742 	duk_tval *tv_from;
18743 	duk_tval *tv_to;
18744 
18745 	DUK_ASSERT_API_ENTRY(thr);
18746 	DUK__CHECK_SPACE();
18747 
18748 	if (DUK_UNLIKELY(thr->valstack_top - thr->valstack_bottom <= 0)) {
18749 		DUK_ERROR_RANGE_INDEX(thr, -1);
18750 		DUK_WO_NORETURN(return;);
18751 	}
18752 	tv_from = thr->valstack_top - 1;
18753 	tv_to = thr->valstack_top++;
18754 	DUK_ASSERT(tv_from != NULL);
18755 	DUK_ASSERT(tv_to != NULL);
18756 	DUK_TVAL_SET_TVAL(tv_to, tv_from);
18757 	DUK_TVAL_INCREF(thr, tv_to);  /* no side effects */
18758 #endif
18759 }
18760 
duk_dup_0(duk_hthread * thr)18761 DUK_INTERNAL void duk_dup_0(duk_hthread *thr) {
18762 	DUK_ASSERT_API_ENTRY(thr);
18763 	duk_dup(thr, 0);
18764 }
duk_dup_1(duk_hthread * thr)18765 DUK_INTERNAL void duk_dup_1(duk_hthread *thr) {
18766 	DUK_ASSERT_API_ENTRY(thr);
18767 	duk_dup(thr, 1);
18768 }
duk_dup_2(duk_hthread * thr)18769 DUK_INTERNAL void duk_dup_2(duk_hthread *thr) {
18770 	DUK_ASSERT_API_ENTRY(thr);
18771 	duk_dup(thr, 2);
18772 }
duk_dup_m2(duk_hthread * thr)18773 DUK_INTERNAL void duk_dup_m2(duk_hthread *thr) {
18774 	DUK_ASSERT_API_ENTRY(thr);
18775 	duk_dup(thr, -2);
18776 }
duk_dup_m3(duk_hthread * thr)18777 DUK_INTERNAL void duk_dup_m3(duk_hthread *thr) {
18778 	DUK_ASSERT_API_ENTRY(thr);
18779 	duk_dup(thr, -3);
18780 }
duk_dup_m4(duk_hthread * thr)18781 DUK_INTERNAL void duk_dup_m4(duk_hthread *thr) {
18782 	DUK_ASSERT_API_ENTRY(thr);
18783 	duk_dup(thr, -4);
18784 }
18785 
duk_insert(duk_hthread * thr,duk_idx_t to_idx)18786 DUK_EXTERNAL void duk_insert(duk_hthread *thr, duk_idx_t to_idx) {
18787 	duk_tval *p;
18788 	duk_tval *q;
18789 	duk_tval tv_tmp;
18790 	duk_size_t nbytes;
18791 
18792 	DUK_ASSERT_API_ENTRY(thr);
18793 
18794 	p = duk_require_tval(thr, to_idx);
18795 	DUK_ASSERT(p != NULL);
18796 	q = duk_require_tval(thr, -1);
18797 	DUK_ASSERT(q != NULL);
18798 
18799 	DUK_ASSERT(q >= p);
18800 
18801 	/*              nbytes
18802 	 *           <--------->
18803 	 *    [ ... | p | x | x | q ]
18804 	 * => [ ... | q | p | x | x ]
18805 	 */
18806 
18807 	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));  /* Note: 'q' is top-1 */
18808 
18809 	DUK_DDD(DUK_DDDPRINT("duk_insert: to_idx=%ld, p=%p, q=%p, nbytes=%lu",
18810 	                     (long) to_idx, (void *) p, (void *) q, (unsigned long) nbytes));
18811 
18812 	/* No net refcount changes.  No need to special case nbytes == 0
18813 	 * (p == q).
18814 	 */
18815 	DUK_TVAL_SET_TVAL(&tv_tmp, q);
18816 	duk_memmove((void *) (p + 1), (const void *) p, (size_t) nbytes);
18817 	DUK_TVAL_SET_TVAL(p, &tv_tmp);
18818 }
18819 
duk_insert_undefined(duk_hthread * thr,duk_idx_t idx)18820 DUK_INTERNAL void duk_insert_undefined(duk_hthread *thr, duk_idx_t idx) {
18821 	DUK_ASSERT_API_ENTRY(thr);
18822 	DUK_ASSERT(idx >= 0);  /* Doesn't support negative indices. */
18823 
18824 	duk_push_undefined(thr);
18825 	duk_insert(thr, idx);
18826 }
18827 
duk_insert_undefined_n(duk_hthread * thr,duk_idx_t idx,duk_idx_t count)18828 DUK_INTERNAL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
18829 	duk_tval *tv, *tv_end;
18830 
18831 	DUK_ASSERT_API_ENTRY(thr);
18832 	DUK_ASSERT(idx >= 0);  /* Doesn't support negative indices or count. */
18833 	DUK_ASSERT(count >= 0);
18834 
18835 	tv = duk_reserve_gap(thr, idx, count);
18836 	tv_end = tv + count;
18837 	while (tv != tv_end) {
18838 		DUK_TVAL_SET_UNDEFINED(tv);
18839 		tv++;
18840 	}
18841 }
18842 
duk_replace(duk_hthread * thr,duk_idx_t to_idx)18843 DUK_EXTERNAL void duk_replace(duk_hthread *thr, duk_idx_t to_idx) {
18844 	duk_tval *tv1;
18845 	duk_tval *tv2;
18846 	duk_tval tv_tmp;
18847 
18848 	DUK_ASSERT_API_ENTRY(thr);
18849 
18850 	tv1 = duk_require_tval(thr, -1);
18851 	DUK_ASSERT(tv1 != NULL);
18852 	tv2 = duk_require_tval(thr, to_idx);
18853 	DUK_ASSERT(tv2 != NULL);
18854 
18855 	/* For tv1 == tv2, both pointing to stack top, the end result
18856 	 * is same as duk_pop(thr).
18857 	 */
18858 	DUK_TVAL_SET_TVAL(&tv_tmp, tv2);
18859 	DUK_TVAL_SET_TVAL(tv2, tv1);
18860 	DUK_TVAL_SET_UNDEFINED(tv1);
18861 	thr->valstack_top--;
18862 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
18863 }
18864 
duk_copy(duk_hthread * thr,duk_idx_t from_idx,duk_idx_t to_idx)18865 DUK_EXTERNAL void duk_copy(duk_hthread *thr, duk_idx_t from_idx, duk_idx_t to_idx) {
18866 	duk_tval *tv1;
18867 	duk_tval *tv2;
18868 
18869 	DUK_ASSERT_API_ENTRY(thr);
18870 
18871 	tv1 = duk_require_tval(thr, from_idx);
18872 	DUK_ASSERT(tv1 != NULL);
18873 	tv2 = duk_require_tval(thr, to_idx);
18874 	DUK_ASSERT(tv2 != NULL);
18875 
18876 	/* For tv1 == tv2, this is a no-op (no explicit check needed). */
18877 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv2, tv1);  /* side effects */
18878 }
18879 
duk_remove(duk_hthread * thr,duk_idx_t idx)18880 DUK_EXTERNAL void duk_remove(duk_hthread *thr, duk_idx_t idx) {
18881 	duk_tval *p;
18882 	duk_tval *q;
18883 #if defined(DUK_USE_REFERENCE_COUNTING)
18884 	duk_tval tv_tmp;
18885 #endif
18886 	duk_size_t nbytes;
18887 
18888 	DUK_ASSERT_API_ENTRY(thr);
18889 
18890 	p = duk_require_tval(thr, idx);
18891 	DUK_ASSERT(p != NULL);
18892 	q = duk_require_tval(thr, -1);
18893 	DUK_ASSERT(q != NULL);
18894 
18895 	DUK_ASSERT(q >= p);
18896 
18897 	/*              nbytes            zero size case
18898 	 *           <--------->
18899 	 *    [ ... | p | x | x | q ]     [ ... | p==q ]
18900 	 * => [ ... | x | x | q ]         [ ... ]
18901 	 */
18902 
18903 #if defined(DUK_USE_REFERENCE_COUNTING)
18904 	/* use a temp: decref only when valstack reachable values are correct */
18905 	DUK_TVAL_SET_TVAL(&tv_tmp, p);
18906 #endif
18907 
18908 	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));  /* Note: 'q' is top-1 */
18909 	duk_memmove((void *) p, (const void *) (p + 1), (size_t) nbytes);
18910 
18911 	DUK_TVAL_SET_UNDEFINED(q);
18912 	thr->valstack_top--;
18913 
18914 #if defined(DUK_USE_REFERENCE_COUNTING)
18915 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
18916 #endif
18917 }
18918 
duk_remove_unsafe(duk_hthread * thr,duk_idx_t idx)18919 DUK_INTERNAL void duk_remove_unsafe(duk_hthread *thr, duk_idx_t idx) {
18920 	DUK_ASSERT_API_ENTRY(thr);
18921 
18922 	duk_remove(thr, idx);  /* XXX: no optimization for now */
18923 }
18924 
duk_remove_m2(duk_hthread * thr)18925 DUK_INTERNAL void duk_remove_m2(duk_hthread *thr) {
18926 	DUK_ASSERT_API_ENTRY(thr);
18927 
18928 	duk_remove(thr, -2);
18929 }
18930 
duk_remove_n(duk_hthread * thr,duk_idx_t idx,duk_idx_t count)18931 DUK_INTERNAL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
18932 #if defined(DUK_USE_PREFER_SIZE)
18933 	/* XXX: maybe too slow even when preferring size? */
18934 	DUK_ASSERT_API_ENTRY(thr);
18935 	DUK_ASSERT(count >= 0);
18936 	DUK_ASSERT(idx >= 0);
18937 
18938 	while (count-- > 0) {
18939 		duk_remove(thr, idx);
18940 	}
18941 #else  /* DUK_USE_PREFER_SIZE */
18942 	duk_tval *tv_src;
18943 	duk_tval *tv_dst;
18944 	duk_tval *tv_newtop;
18945 	duk_tval *tv;
18946 	duk_size_t bytes;
18947 
18948 	DUK_ASSERT_API_ENTRY(thr);
18949 	DUK_ASSERT(count >= 0);
18950 	DUK_ASSERT(idx >= 0);
18951 
18952 	tv_dst = thr->valstack_bottom + idx;
18953 	DUK_ASSERT(tv_dst <= thr->valstack_top);
18954 	tv_src = tv_dst + count;
18955 	DUK_ASSERT(tv_src <= thr->valstack_top);
18956 	bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) tv_src);
18957 
18958 	for (tv = tv_dst; tv < tv_src; tv++) {
18959 		DUK_TVAL_DECREF_NORZ(thr, tv);
18960 	}
18961 
18962 	duk_memmove((void *) tv_dst, (const void *) tv_src, bytes);
18963 
18964 	tv_newtop = thr->valstack_top - count;
18965 	for (tv = tv_newtop; tv < thr->valstack_top; tv++) {
18966 		DUK_TVAL_SET_UNDEFINED(tv);
18967 	}
18968 	thr->valstack_top = tv_newtop;
18969 
18970 	/* When not preferring size, only NORZ macros are used; caller
18971 	 * is expected to DUK_REFZERO_CHECK().
18972 	 */
18973 #endif  /* DUK_USE_PREFER_SIZE */
18974 }
18975 
duk_remove_n_unsafe(duk_hthread * thr,duk_idx_t idx,duk_idx_t count)18976 DUK_INTERNAL void duk_remove_n_unsafe(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
18977 	DUK_ASSERT_API_ENTRY(thr);
18978 
18979 	duk_remove_n(thr, idx, count);  /* XXX: no optimization for now */
18980 }
18981 
18982 /*
18983  *  Stack slice primitives
18984  */
18985 
duk_xcopymove_raw(duk_hthread * to_thr,duk_hthread * from_thr,duk_idx_t count,duk_bool_t is_copy)18986 DUK_EXTERNAL void duk_xcopymove_raw(duk_hthread *to_thr, duk_hthread *from_thr, duk_idx_t count, duk_bool_t is_copy) {
18987 	void *src;
18988 	duk_size_t nbytes;
18989 	duk_tval *p;
18990 	duk_tval *q;
18991 
18992 	/* XXX: several pointer comparison issues here */
18993 
18994 	DUK_ASSERT_API_ENTRY(to_thr);
18995 	DUK_CTX_ASSERT_VALID(to_thr);
18996 	DUK_CTX_ASSERT_VALID(from_thr);
18997 	DUK_ASSERT(to_thr->heap == from_thr->heap);
18998 
18999 	if (DUK_UNLIKELY(to_thr == from_thr)) {
19000 		DUK_ERROR_TYPE(to_thr, DUK_STR_INVALID_CONTEXT);
19001 		DUK_WO_NORETURN(return;);
19002 	}
19003 	if (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) DUK_USE_VALSTACK_LIMIT)) {
19004 		/* Maximum value check ensures 'nbytes' won't wrap below.
19005 		 * Also handles negative count.
19006 		 */
19007 		DUK_ERROR_RANGE_INVALID_COUNT(to_thr);
19008 		DUK_WO_NORETURN(return;);
19009 	}
19010 	DUK_ASSERT(count >= 0);
19011 
19012 	nbytes = sizeof(duk_tval) * (duk_size_t) count;
19013 	if (DUK_UNLIKELY(nbytes == 0)) {
19014 		return;
19015 	}
19016 	DUK_ASSERT(to_thr->valstack_top <= to_thr->valstack_end);
19017 	if (DUK_UNLIKELY((duk_size_t) ((duk_uint8_t *) to_thr->valstack_end - (duk_uint8_t *) to_thr->valstack_top) < nbytes)) {
19018 		DUK_ERROR_RANGE_PUSH_BEYOND(to_thr);
19019 		DUK_WO_NORETURN(return;);
19020 	}
19021 	src = (void *) ((duk_uint8_t *) from_thr->valstack_top - nbytes);
19022 	if (DUK_UNLIKELY(src < (void *) from_thr->valstack_bottom)) {
19023 		DUK_ERROR_RANGE_INVALID_COUNT(to_thr);
19024 		DUK_WO_NORETURN(return;);
19025 	}
19026 
19027 	/* Copy values (no overlap even if to_thr == from_thr; that's not
19028 	 * allowed now anyway).
19029 	 */
19030 	DUK_ASSERT(nbytes > 0);
19031 	duk_memcpy((void *) to_thr->valstack_top, (const void *) src, (size_t) nbytes);
19032 
19033 	p = to_thr->valstack_top;
19034 	to_thr->valstack_top = (duk_tval *) (void *) (((duk_uint8_t *) p) + nbytes);
19035 
19036 	if (is_copy) {
19037 		/* Incref copies, keep originals. */
19038 		q = to_thr->valstack_top;
19039 		while (p < q) {
19040 			DUK_TVAL_INCREF(to_thr, p);  /* no side effects */
19041 			p++;
19042 		}
19043 	} else {
19044 		/* No net refcount change. */
19045 		p = from_thr->valstack_top;
19046 		q = (duk_tval *) (void *) (((duk_uint8_t *) p) - nbytes);
19047 		from_thr->valstack_top = q;
19048 
19049 		while (p > q) {
19050 			p--;
19051 			DUK_TVAL_SET_UNDEFINED(p);
19052 			/* XXX: fast primitive to set a bunch of values to UNDEFINED */
19053 		}
19054 	}
19055 }
19056 
19057 /* Internal helper: reserve a gap of 'count' elements at 'idx_base' and return a
19058  * pointer to the gap.  Values in the gap are garbage and MUST be initialized by
19059  * the caller before any side effects may occur.  The caller must ensure there's
19060  * enough stack reserve for 'count' values.
19061  */
duk_reserve_gap(duk_hthread * thr,duk_idx_t idx_base,duk_idx_t count)19062 DUK_INTERNAL duk_tval *duk_reserve_gap(duk_hthread *thr, duk_idx_t idx_base, duk_idx_t count) {
19063 	duk_tval *tv_src;
19064 	duk_tval *tv_dst;
19065 	duk_size_t gap_bytes;
19066 	duk_size_t copy_bytes;
19067 
19068 	/* Caller is responsible for ensuring there's enough preallocated
19069 	 * value stack.
19070 	 */
19071 	DUK_ASSERT_API_ENTRY(thr);
19072 	DUK_ASSERT(count >= 0);
19073 	DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack_top) >= (duk_size_t) count);
19074 
19075 	tv_src = thr->valstack_bottom + idx_base;
19076 	gap_bytes = (duk_size_t) count * sizeof(duk_tval);
19077 	tv_dst = (duk_tval *) (void *) ((duk_uint8_t *) tv_src + gap_bytes);
19078 	copy_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) tv_src);
19079 	thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_top + gap_bytes);
19080 	duk_memmove((void *) tv_dst, (const void *) tv_src, copy_bytes);
19081 
19082 	/* Values in the gap are left as garbage: caller must fill them in
19083 	 * and INCREF them before any side effects.
19084 	 */
19085 	return tv_src;
19086 }
19087 
19088 /*
19089  *  Get/opt/require
19090  */
19091 
duk_require_undefined(duk_hthread * thr,duk_idx_t idx)19092 DUK_EXTERNAL void duk_require_undefined(duk_hthread *thr, duk_idx_t idx) {
19093 	duk_tval *tv;
19094 
19095 	DUK_ASSERT_API_ENTRY(thr);
19096 
19097 	tv = duk_get_tval_or_unused(thr, idx);
19098 	DUK_ASSERT(tv != NULL);
19099 	if (DUK_UNLIKELY(!DUK_TVAL_IS_UNDEFINED(tv))) {
19100 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "undefined", DUK_STR_NOT_UNDEFINED);
19101 		DUK_WO_NORETURN(return;);
19102 	}
19103 }
19104 
duk_require_null(duk_hthread * thr,duk_idx_t idx)19105 DUK_EXTERNAL void duk_require_null(duk_hthread *thr, duk_idx_t idx) {
19106 	duk_tval *tv;
19107 
19108 	DUK_ASSERT_API_ENTRY(thr);
19109 
19110 	tv = duk_get_tval_or_unused(thr, idx);
19111 	DUK_ASSERT(tv != NULL);
19112 	if (DUK_UNLIKELY(!DUK_TVAL_IS_NULL(tv))) {
19113 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "null", DUK_STR_NOT_NULL);
19114 		DUK_WO_NORETURN(return;);
19115 	}
19116 }
19117 
duk__get_boolean_raw(duk_hthread * thr,duk_idx_t idx,duk_bool_t def_value)19118 DUK_LOCAL DUK_ALWAYS_INLINE duk_bool_t duk__get_boolean_raw(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
19119 	duk_bool_t ret;
19120 	duk_tval *tv;
19121 
19122 	DUK_CTX_ASSERT_VALID(thr);
19123 
19124 	tv = duk_get_tval_or_unused(thr, idx);
19125 	DUK_ASSERT(tv != NULL);
19126 	if (DUK_TVAL_IS_BOOLEAN(tv)) {
19127 		ret = DUK_TVAL_GET_BOOLEAN(tv);
19128 		DUK_ASSERT(ret == 0 || ret == 1);
19129 	} else {
19130 		ret = def_value;
19131 		/* Not guaranteed to be 0 or 1. */
19132 	}
19133 
19134 	return ret;
19135 }
19136 
duk_get_boolean(duk_hthread * thr,duk_idx_t idx)19137 DUK_EXTERNAL duk_bool_t duk_get_boolean(duk_hthread *thr, duk_idx_t idx) {
19138 	DUK_ASSERT_API_ENTRY(thr);
19139 
19140 	return duk__get_boolean_raw(thr, idx, 0);  /* default: false */
19141 }
19142 
duk_get_boolean_default(duk_hthread * thr,duk_idx_t idx,duk_bool_t def_value)19143 DUK_EXTERNAL duk_bool_t duk_get_boolean_default(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
19144 	DUK_ASSERT_API_ENTRY(thr);
19145 
19146 	return duk__get_boolean_raw(thr, idx, def_value);
19147 }
19148 
duk_require_boolean(duk_hthread * thr,duk_idx_t idx)19149 DUK_EXTERNAL duk_bool_t duk_require_boolean(duk_hthread *thr, duk_idx_t idx) {
19150 	duk_tval *tv;
19151 	duk_bool_t ret;
19152 
19153 	DUK_ASSERT_API_ENTRY(thr);
19154 
19155 	tv = duk_get_tval_or_unused(thr, idx);
19156 	DUK_ASSERT(tv != NULL);
19157 	if (DUK_LIKELY(DUK_TVAL_IS_BOOLEAN(tv))) {
19158 		ret = DUK_TVAL_GET_BOOLEAN(tv);
19159 		DUK_ASSERT(ret == 0 || ret == 1);
19160 		return ret;
19161 	} else {
19162 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "boolean", DUK_STR_NOT_BOOLEAN);
19163 		DUK_WO_NORETURN(return 0;);
19164 	}
19165 }
19166 
duk_opt_boolean(duk_hthread * thr,duk_idx_t idx,duk_bool_t def_value)19167 DUK_EXTERNAL duk_bool_t duk_opt_boolean(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
19168 	DUK_ASSERT_API_ENTRY(thr);
19169 
19170 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19171 		return def_value;
19172 	}
19173 	return duk_require_boolean(thr, idx);
19174 }
19175 
duk__get_number_raw(duk_hthread * thr,duk_idx_t idx,duk_double_t def_value)19176 DUK_LOCAL DUK_ALWAYS_INLINE duk_double_t duk__get_number_raw(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
19177 	duk_double_union ret;
19178 	duk_tval *tv;
19179 
19180 	DUK_CTX_ASSERT_VALID(thr);
19181 
19182 	tv = duk_get_tval_or_unused(thr, idx);
19183 	DUK_ASSERT(tv != NULL);
19184 #if defined(DUK_USE_FASTINT)
19185 	if (DUK_TVAL_IS_FASTINT(tv)) {
19186 		ret.d = (duk_double_t) DUK_TVAL_GET_FASTINT(tv);  /* XXX: cast trick */
19187 	}
19188 	else
19189 #endif
19190 	if (DUK_TVAL_IS_DOUBLE(tv)) {
19191 		/* When using packed duk_tval, number must be in NaN-normalized form
19192 		 * for it to be a duk_tval, so no need to normalize.  NOP for unpacked
19193 		 * duk_tval.
19194 		 */
19195 		ret.d = DUK_TVAL_GET_DOUBLE(tv);
19196 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&ret));
19197 	} else {
19198 		ret.d = def_value;
19199 		/* Default value (including NaN) may not be normalized. */
19200 	}
19201 
19202 	return ret.d;
19203 }
19204 
duk_get_number(duk_hthread * thr,duk_idx_t idx)19205 DUK_EXTERNAL duk_double_t duk_get_number(duk_hthread *thr, duk_idx_t idx) {
19206 	DUK_ASSERT_API_ENTRY(thr);
19207 	return duk__get_number_raw(thr, idx, DUK_DOUBLE_NAN);  /* default: NaN */
19208 }
19209 
duk_get_number_default(duk_hthread * thr,duk_idx_t idx,duk_double_t def_value)19210 DUK_EXTERNAL duk_double_t duk_get_number_default(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
19211 	DUK_ASSERT_API_ENTRY(thr);
19212 	return duk__get_number_raw(thr, idx, def_value);
19213 }
19214 
duk_require_number(duk_hthread * thr,duk_idx_t idx)19215 DUK_EXTERNAL duk_double_t duk_require_number(duk_hthread *thr, duk_idx_t idx) {
19216 	duk_tval *tv;
19217 	duk_double_union ret;
19218 
19219 	DUK_ASSERT_API_ENTRY(thr);
19220 
19221 	tv = duk_get_tval_or_unused(thr, idx);
19222 	DUK_ASSERT(tv != NULL);
19223 	if (DUK_UNLIKELY(!DUK_TVAL_IS_NUMBER(tv))) {
19224 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
19225 		DUK_WO_NORETURN(return 0.0;);
19226 	}
19227 
19228 	ret.d = DUK_TVAL_GET_NUMBER(tv);
19229 
19230 	/* When using packed duk_tval, number must be in NaN-normalized form
19231 	 * for it to be a duk_tval, so no need to normalize.  NOP for unpacked
19232 	 * duk_tval.
19233 	 */
19234 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&ret));
19235 	return ret.d;
19236 }
19237 
duk_opt_number(duk_hthread * thr,duk_idx_t idx,duk_double_t def_value)19238 DUK_EXTERNAL duk_double_t duk_opt_number(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
19239 	DUK_ASSERT_API_ENTRY(thr);
19240 
19241 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19242 		/* User provided default is not NaN normalized. */
19243 		return def_value;
19244 	}
19245 	return duk_require_number(thr, idx);
19246 }
19247 
duk_get_int(duk_hthread * thr,duk_idx_t idx)19248 DUK_EXTERNAL duk_int_t duk_get_int(duk_hthread *thr, duk_idx_t idx) {
19249 	DUK_ASSERT_API_ENTRY(thr);
19250 
19251 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 0 /*require*/);
19252 }
19253 
duk_get_uint(duk_hthread * thr,duk_idx_t idx)19254 DUK_EXTERNAL duk_uint_t duk_get_uint(duk_hthread *thr, duk_idx_t idx) {
19255 	DUK_ASSERT_API_ENTRY(thr);
19256 
19257 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 0 /*require*/);
19258 }
19259 
duk_get_int_default(duk_hthread * thr,duk_idx_t idx,duk_int_t def_value)19260 DUK_EXTERNAL duk_int_t duk_get_int_default(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value) {
19261 	DUK_ASSERT_API_ENTRY(thr);
19262 
19263 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, def_value, 0 /*require*/);
19264 }
19265 
duk_get_uint_default(duk_hthread * thr,duk_idx_t idx,duk_uint_t def_value)19266 DUK_EXTERNAL duk_uint_t duk_get_uint_default(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value) {
19267 	DUK_ASSERT_API_ENTRY(thr);
19268 
19269 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, def_value, 0 /*require*/);
19270 }
19271 
duk_require_int(duk_hthread * thr,duk_idx_t idx)19272 DUK_EXTERNAL duk_int_t duk_require_int(duk_hthread *thr, duk_idx_t idx) {
19273 	DUK_ASSERT_API_ENTRY(thr);
19274 
19275 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 1 /*require*/);
19276 }
19277 
duk_require_uint(duk_hthread * thr,duk_idx_t idx)19278 DUK_EXTERNAL duk_uint_t duk_require_uint(duk_hthread *thr, duk_idx_t idx) {
19279 	DUK_ASSERT_API_ENTRY(thr);
19280 
19281 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 1 /*require*/);
19282 }
19283 
duk_opt_int(duk_hthread * thr,duk_idx_t idx,duk_int_t def_value)19284 DUK_EXTERNAL duk_int_t duk_opt_int(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value) {
19285 	DUK_ASSERT_API_ENTRY(thr);
19286 
19287 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19288 		return def_value;
19289 	}
19290 	return duk_require_int(thr, idx);
19291 }
19292 
duk_opt_uint(duk_hthread * thr,duk_idx_t idx,duk_uint_t def_value)19293 DUK_EXTERNAL duk_uint_t duk_opt_uint(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value) {
19294 	DUK_ASSERT_API_ENTRY(thr);
19295 
19296 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19297 		return def_value;
19298 	}
19299 	return duk_require_uint(thr, idx);
19300 }
19301 
duk_get_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)19302 DUK_EXTERNAL const char *duk_get_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
19303 	duk_hstring *h;
19304 	const char *ret;
19305 	duk_size_t len;
19306 
19307 	DUK_ASSERT_API_ENTRY(thr);
19308 
19309 	h = duk_get_hstring(thr, idx);
19310 	if (h != NULL) {
19311 		len = DUK_HSTRING_GET_BYTELEN(h);
19312 		ret = (const char *) DUK_HSTRING_GET_DATA(h);
19313 	} else {
19314 		len = 0;
19315 		ret = NULL;
19316 	}
19317 
19318 	if (out_len != NULL) {
19319 		*out_len = len;
19320 	}
19321 	return ret;
19322 }
19323 
duk_require_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)19324 DUK_EXTERNAL const char *duk_require_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
19325 	duk_hstring *h;
19326 
19327 	DUK_ASSERT_API_ENTRY(thr);
19328 
19329 	h = duk_require_hstring(thr, idx);
19330 	DUK_ASSERT(h != NULL);
19331 	if (out_len) {
19332 		*out_len = DUK_HSTRING_GET_BYTELEN(h);
19333 	}
19334 	return (const char *) DUK_HSTRING_GET_DATA(h);
19335 }
19336 
duk_require_lstring_notsymbol(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)19337 DUK_INTERNAL const char *duk_require_lstring_notsymbol(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
19338 	duk_hstring *h;
19339 
19340 	DUK_ASSERT_API_ENTRY(thr);
19341 
19342 	h = duk_require_hstring_notsymbol(thr, idx);
19343 	DUK_ASSERT(h != NULL);
19344 	if (out_len) {
19345 		*out_len = DUK_HSTRING_GET_BYTELEN(h);
19346 	}
19347 	return (const char *) DUK_HSTRING_GET_DATA(h);
19348 }
19349 
duk_get_string(duk_hthread * thr,duk_idx_t idx)19350 DUK_EXTERNAL const char *duk_get_string(duk_hthread *thr, duk_idx_t idx) {
19351 	duk_hstring *h;
19352 
19353 	DUK_ASSERT_API_ENTRY(thr);
19354 
19355 	h = duk_get_hstring(thr, idx);
19356 	if (h != NULL) {
19357 		return (const char *) DUK_HSTRING_GET_DATA(h);
19358 	} else {
19359 		return NULL;
19360 	}
19361 }
19362 
duk_opt_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len,const char * def_ptr,duk_size_t def_len)19363 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) {
19364 	DUK_ASSERT_API_ENTRY(thr);
19365 
19366 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19367 		if (out_len != NULL) {
19368 			*out_len = def_len;
19369 		}
19370 		return def_ptr;
19371 	}
19372 	return duk_require_lstring(thr, idx, out_len);
19373 }
19374 
duk_opt_string(duk_hthread * thr,duk_idx_t idx,const char * def_ptr)19375 DUK_EXTERNAL const char *duk_opt_string(duk_hthread *thr, duk_idx_t idx, const char *def_ptr) {
19376 	DUK_ASSERT_API_ENTRY(thr);
19377 
19378 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19379 		return def_ptr;
19380 	}
19381 	return duk_require_string(thr, idx);
19382 }
19383 
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)19384 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) {
19385 	duk_hstring *h;
19386 	const char *ret;
19387 	duk_size_t len;
19388 
19389 	DUK_ASSERT_API_ENTRY(thr);
19390 
19391 	h = duk_get_hstring(thr, idx);
19392 	if (h != NULL) {
19393 		len = DUK_HSTRING_GET_BYTELEN(h);
19394 		ret = (const char *) DUK_HSTRING_GET_DATA(h);
19395 	} else {
19396 		len = def_len;
19397 		ret = def_ptr;
19398 	}
19399 
19400 	if (out_len != NULL) {
19401 		*out_len = len;
19402 	}
19403 	return ret;
19404 }
19405 
duk_get_string_default(duk_hthread * thr,duk_idx_t idx,const char * def_value)19406 DUK_EXTERNAL const char *duk_get_string_default(duk_hthread *thr, duk_idx_t idx, const char *def_value) {
19407 	duk_hstring *h;
19408 
19409 	DUK_ASSERT_API_ENTRY(thr);
19410 
19411 	h = duk_get_hstring(thr, idx);
19412 	if (h != NULL) {
19413 		return (const char *) DUK_HSTRING_GET_DATA(h);
19414 	} else {
19415 		return def_value;
19416 	}
19417 }
19418 
duk_get_string_notsymbol(duk_hthread * thr,duk_idx_t idx)19419 DUK_INTERNAL const char *duk_get_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {
19420 	duk_hstring *h;
19421 
19422 	DUK_ASSERT_API_ENTRY(thr);
19423 
19424 	h = duk_get_hstring_notsymbol(thr, idx);
19425 	if (h) {
19426 		return (const char *) DUK_HSTRING_GET_DATA(h);
19427 	} else {
19428 		return NULL;
19429 	}
19430 }
19431 
duk_require_string(duk_hthread * thr,duk_idx_t idx)19432 DUK_EXTERNAL const char *duk_require_string(duk_hthread *thr, duk_idx_t idx) {
19433 	DUK_ASSERT_API_ENTRY(thr);
19434 
19435 	return duk_require_lstring(thr, idx, NULL);
19436 }
19437 
duk_require_string_notsymbol(duk_hthread * thr,duk_idx_t idx)19438 DUK_INTERNAL const char *duk_require_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {
19439 	duk_hstring *h;
19440 
19441 	DUK_ASSERT_API_ENTRY(thr);
19442 
19443 	h = duk_require_hstring_notsymbol(thr, idx);
19444 	DUK_ASSERT(h != NULL);
19445 	return (const char *) DUK_HSTRING_GET_DATA(h);
19446 }
19447 
duk_require_object(duk_hthread * thr,duk_idx_t idx)19448 DUK_EXTERNAL void duk_require_object(duk_hthread *thr, duk_idx_t idx) {
19449 	duk_tval *tv;
19450 
19451 	DUK_ASSERT_API_ENTRY(thr);
19452 
19453 	tv = duk_get_tval_or_unused(thr, idx);
19454 	DUK_ASSERT(tv != NULL);
19455 	if (DUK_UNLIKELY(!DUK_TVAL_IS_OBJECT(tv))) {
19456 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
19457 		DUK_WO_NORETURN(return;);
19458 	}
19459 }
19460 
duk__get_pointer_raw(duk_hthread * thr,duk_idx_t idx,void * def_value)19461 DUK_LOCAL void *duk__get_pointer_raw(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19462 	duk_tval *tv;
19463 	void *p;
19464 
19465 	DUK_CTX_ASSERT_VALID(thr);
19466 
19467 	tv = duk_get_tval_or_unused(thr, idx);
19468 	DUK_ASSERT(tv != NULL);
19469 	if (!DUK_TVAL_IS_POINTER(tv)) {
19470 		return def_value;
19471 	}
19472 
19473 	p = DUK_TVAL_GET_POINTER(tv);  /* may be NULL */
19474 	return p;
19475 }
19476 
duk_get_pointer(duk_hthread * thr,duk_idx_t idx)19477 DUK_EXTERNAL void *duk_get_pointer(duk_hthread *thr, duk_idx_t idx) {
19478 	DUK_ASSERT_API_ENTRY(thr);
19479 	return duk__get_pointer_raw(thr, idx, NULL /*def_value*/);
19480 }
19481 
duk_opt_pointer(duk_hthread * thr,duk_idx_t idx,void * def_value)19482 DUK_EXTERNAL void *duk_opt_pointer(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19483 	DUK_ASSERT_API_ENTRY(thr);
19484 
19485 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19486 		return def_value;
19487 	}
19488 	return duk_require_pointer(thr, idx);
19489 }
19490 
duk_get_pointer_default(duk_hthread * thr,duk_idx_t idx,void * def_value)19491 DUK_EXTERNAL void *duk_get_pointer_default(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19492 	DUK_ASSERT_API_ENTRY(thr);
19493 	return duk__get_pointer_raw(thr, idx, def_value);
19494 }
19495 
duk_require_pointer(duk_hthread * thr,duk_idx_t idx)19496 DUK_EXTERNAL void *duk_require_pointer(duk_hthread *thr, duk_idx_t idx) {
19497 	duk_tval *tv;
19498 	void *p;
19499 
19500 	DUK_ASSERT_API_ENTRY(thr);
19501 
19502 	/* Note: here we must be wary of the fact that a pointer may be
19503 	 * valid and be a NULL.
19504 	 */
19505 	tv = duk_get_tval_or_unused(thr, idx);
19506 	DUK_ASSERT(tv != NULL);
19507 	if (DUK_UNLIKELY(!DUK_TVAL_IS_POINTER(tv))) {
19508 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "pointer", DUK_STR_NOT_POINTER);
19509 		DUK_WO_NORETURN(return NULL;);
19510 	}
19511 	p = DUK_TVAL_GET_POINTER(tv);  /* may be NULL */
19512 	return p;
19513 }
19514 
19515 #if 0  /*unused*/
19516 DUK_INTERNAL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx) {
19517 	duk_tval *tv;
19518 	duk_heaphdr *h;
19519 
19520 	DUK_ASSERT_API_ENTRY(thr);
19521 
19522 	tv = duk_get_tval_or_unused(thr, idx);
19523 	DUK_ASSERT(tv != NULL);
19524 	if (!DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
19525 		return NULL;
19526 	}
19527 
19528 	h = DUK_TVAL_GET_HEAPHDR(tv);
19529 	DUK_ASSERT(h != NULL);
19530 	return (void *) h;
19531 }
19532 #endif
19533 
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)19534 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) {
19535 	duk_hbuffer *h;
19536 	void *ret;
19537 	duk_size_t len;
19538 	duk_tval *tv;
19539 
19540 	DUK_CTX_ASSERT_VALID(thr);
19541 
19542 	if (out_size != NULL) {
19543 		*out_size = 0;
19544 	}
19545 
19546 	tv = duk_get_tval_or_unused(thr, idx);
19547 	DUK_ASSERT(tv != NULL);
19548 	if (DUK_LIKELY(DUK_TVAL_IS_BUFFER(tv))) {
19549 		h = DUK_TVAL_GET_BUFFER(tv);
19550 		DUK_ASSERT(h != NULL);
19551 
19552 		len = DUK_HBUFFER_GET_SIZE(h);
19553 		ret = DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
19554 	} else {
19555 		if (throw_flag) {
19556 			DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
19557 			DUK_WO_NORETURN(return NULL;);
19558 		}
19559 		len = def_size;
19560 		ret = def_ptr;
19561 	}
19562 
19563 	if (out_size != NULL) {
19564 		*out_size = len;
19565 	}
19566 	return ret;
19567 }
19568 
duk_get_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)19569 DUK_EXTERNAL void *duk_get_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
19570 	DUK_ASSERT_API_ENTRY(thr);
19571 
19572 	return duk__get_buffer_helper(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/);
19573 }
19574 
duk_opt_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,void * def_ptr,duk_size_t def_size)19575 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) {
19576 	DUK_ASSERT_API_ENTRY(thr);
19577 
19578 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19579 		if (out_size != NULL) {
19580 			*out_size = def_size;
19581 		}
19582 		return def_ptr;
19583 	}
19584 	return duk_require_buffer(thr, idx, out_size);
19585 }
19586 
duk_get_buffer_default(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,void * def_ptr,duk_size_t def_len)19587 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) {
19588 	DUK_ASSERT_API_ENTRY(thr);
19589 
19590 	return duk__get_buffer_helper(thr, idx, out_size, def_ptr, def_len, 0 /*throw_flag*/);
19591 }
19592 
duk_require_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)19593 DUK_EXTERNAL void *duk_require_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
19594 	DUK_ASSERT_API_ENTRY(thr);
19595 
19596 	return duk__get_buffer_helper(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 1 /*throw_flag*/);
19597 }
19598 
19599 /* Get the active buffer data area for a plain buffer or a buffer object.
19600  * Return NULL if the the value is not a buffer.  Note that a buffer may
19601  * have a NULL data pointer when its size is zero, the optional 'out_isbuffer'
19602  * argument allows caller to detect this reliably.
19603  */
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)19604 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) {
19605 	duk_tval *tv;
19606 
19607 	DUK_ASSERT_API_ENTRY(thr);
19608 
19609 	if (out_isbuffer != NULL) {
19610 		*out_isbuffer = 0;
19611 	}
19612 	if (out_size != NULL) {
19613 		*out_size = def_size;
19614 	}
19615 
19616 	tv = duk_get_tval_or_unused(thr, idx);
19617 	DUK_ASSERT(tv != NULL);
19618 
19619 	if (DUK_TVAL_IS_BUFFER(tv)) {
19620 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
19621 		DUK_ASSERT(h != NULL);
19622 		if (out_size != NULL) {
19623 			*out_size = DUK_HBUFFER_GET_SIZE(h);
19624 		}
19625 		if (out_isbuffer != NULL) {
19626 			*out_isbuffer = 1;
19627 		}
19628 		return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);  /* may be NULL (but only if size is 0) */
19629 	}
19630 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
19631 	else if (DUK_TVAL_IS_OBJECT(tv)) {
19632 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
19633 		DUK_ASSERT(h != NULL);
19634 		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
19635 			/* XXX: this is probably a useful shared helper: for a
19636 			 * duk_hbufobj, get a validated buffer pointer/length.
19637 			 */
19638 			duk_hbufobj *h_bufobj = (duk_hbufobj *) h;
19639 			DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
19640 
19641 			if (h_bufobj->buf != NULL &&
19642 			    DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
19643 				duk_uint8_t *p;
19644 
19645 				p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf);
19646 				if (out_size != NULL) {
19647 					*out_size = (duk_size_t) h_bufobj->length;
19648 				}
19649 				if (out_isbuffer != NULL) {
19650 					*out_isbuffer = 1;
19651 				}
19652 				return (void *) (p + h_bufobj->offset);
19653 			}
19654 			/* if slice not fully valid, treat as error */
19655 		}
19656 	}
19657 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
19658 
19659 	if (throw_flag) {
19660 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
19661 		DUK_WO_NORETURN(return NULL;);
19662 	}
19663 	return def_ptr;
19664 }
19665 
duk_get_buffer_data(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)19666 DUK_EXTERNAL void *duk_get_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
19667 	DUK_ASSERT_API_ENTRY(thr);
19668 	return duk_get_buffer_data_raw(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, NULL);
19669 }
19670 
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)19671 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) {
19672 	DUK_ASSERT_API_ENTRY(thr);
19673 	return duk_get_buffer_data_raw(thr, idx, out_size, def_ptr, def_size, 0 /*throw_flag*/, NULL);
19674 }
19675 
duk_opt_buffer_data(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,void * def_ptr,duk_size_t def_size)19676 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) {
19677 	DUK_ASSERT_API_ENTRY(thr);
19678 
19679 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19680 		if (out_size != NULL) {
19681 			*out_size = def_size;
19682 		}
19683 		return def_ptr;
19684 	}
19685 	return duk_require_buffer_data(thr, idx, out_size);
19686 }
19687 
duk_require_buffer_data(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)19688 DUK_EXTERNAL void *duk_require_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
19689 	DUK_ASSERT_API_ENTRY(thr);
19690 	return duk_get_buffer_data_raw(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 1 /*throw_flag*/, NULL);
19691 }
19692 
19693 /* Raw helper for getting a value from the stack, checking its tag.
19694  * The tag cannot be a number because numbers don't have an internal
19695  * tag in the packed representation.
19696  */
19697 
duk__get_tagged_heaphdr_raw(duk_hthread * thr,duk_idx_t idx,duk_uint_t tag)19698 DUK_LOCAL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t tag) {
19699 	duk_tval *tv;
19700 	duk_heaphdr *ret;
19701 
19702 	DUK_CTX_ASSERT_VALID(thr);
19703 
19704 	tv = duk_get_tval_or_unused(thr, idx);
19705 	DUK_ASSERT(tv != NULL);
19706 	if (DUK_TVAL_GET_TAG(tv) != tag) {
19707 		return (duk_heaphdr *) NULL;
19708 	}
19709 
19710 	ret = DUK_TVAL_GET_HEAPHDR(tv);
19711 	DUK_ASSERT(ret != NULL);  /* tagged null pointers should never occur */
19712 	return ret;
19713 
19714 }
19715 
duk_get_hstring(duk_hthread * thr,duk_idx_t idx)19716 DUK_INTERNAL duk_hstring *duk_get_hstring(duk_hthread *thr, duk_idx_t idx) {
19717 	DUK_ASSERT_API_ENTRY(thr);
19718 	return (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
19719 }
19720 
duk_get_hstring_notsymbol(duk_hthread * thr,duk_idx_t idx)19721 DUK_INTERNAL duk_hstring *duk_get_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx) {
19722 	duk_hstring *h;
19723 
19724 	DUK_ASSERT_API_ENTRY(thr);
19725 
19726 	h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
19727 	if (DUK_UNLIKELY(h && DUK_HSTRING_HAS_SYMBOL(h))) {
19728 		return NULL;
19729 	}
19730 	return h;
19731 }
19732 
duk_require_hstring(duk_hthread * thr,duk_idx_t idx)19733 DUK_INTERNAL duk_hstring *duk_require_hstring(duk_hthread *thr, duk_idx_t idx) {
19734 	duk_hstring *h;
19735 
19736 	DUK_ASSERT_API_ENTRY(thr);
19737 
19738 	h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
19739 	if (DUK_UNLIKELY(h == NULL)) {
19740 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "string", DUK_STR_NOT_STRING);
19741 		DUK_WO_NORETURN(return NULL;);
19742 	}
19743 	return h;
19744 }
19745 
duk_require_hstring_notsymbol(duk_hthread * thr,duk_idx_t idx)19746 DUK_INTERNAL duk_hstring *duk_require_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx) {
19747 	duk_hstring *h;
19748 
19749 	DUK_ASSERT_API_ENTRY(thr);
19750 
19751 	h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
19752 	if (DUK_UNLIKELY(h == NULL || DUK_HSTRING_HAS_SYMBOL(h))) {
19753 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "string", DUK_STR_NOT_STRING);
19754 		DUK_WO_NORETURN(return NULL;);
19755 	}
19756 	return h;
19757 }
19758 
duk_get_hobject(duk_hthread * thr,duk_idx_t idx)19759 DUK_INTERNAL duk_hobject *duk_get_hobject(duk_hthread *thr, duk_idx_t idx) {
19760 	DUK_ASSERT_API_ENTRY(thr);
19761 	return (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19762 }
19763 
duk_require_hobject(duk_hthread * thr,duk_idx_t idx)19764 DUK_INTERNAL duk_hobject *duk_require_hobject(duk_hthread *thr, duk_idx_t idx) {
19765 	duk_hobject *h;
19766 
19767 	DUK_ASSERT_API_ENTRY(thr);
19768 
19769 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19770 	if (DUK_UNLIKELY(h == NULL)) {
19771 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
19772 		DUK_WO_NORETURN(return NULL;);
19773 	}
19774 	return h;
19775 }
19776 
duk_get_hbuffer(duk_hthread * thr,duk_idx_t idx)19777 DUK_INTERNAL duk_hbuffer *duk_get_hbuffer(duk_hthread *thr, duk_idx_t idx) {
19778 	DUK_ASSERT_API_ENTRY(thr);
19779 	return (duk_hbuffer *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_BUFFER);
19780 }
19781 
duk_require_hbuffer(duk_hthread * thr,duk_idx_t idx)19782 DUK_INTERNAL duk_hbuffer *duk_require_hbuffer(duk_hthread *thr, duk_idx_t idx) {
19783 	duk_hbuffer *h;
19784 
19785 	DUK_ASSERT_API_ENTRY(thr);
19786 
19787 	h = (duk_hbuffer *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_BUFFER);
19788 	if (DUK_UNLIKELY(h == NULL)) {
19789 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
19790 		DUK_WO_NORETURN(return NULL;);
19791 	}
19792 	return h;
19793 }
19794 
duk_get_hthread(duk_hthread * thr,duk_idx_t idx)19795 DUK_INTERNAL duk_hthread *duk_get_hthread(duk_hthread *thr, duk_idx_t idx) {
19796 	duk_hobject *h;
19797 
19798 	DUK_ASSERT_API_ENTRY(thr);
19799 
19800 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19801 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_THREAD(h))) {
19802 		h = NULL;
19803 	}
19804 	return (duk_hthread *) h;
19805 }
19806 
duk_require_hthread(duk_hthread * thr,duk_idx_t idx)19807 DUK_INTERNAL duk_hthread *duk_require_hthread(duk_hthread *thr, duk_idx_t idx) {
19808 	duk_hobject *h;
19809 
19810 	DUK_ASSERT_API_ENTRY(thr);
19811 
19812 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19813 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_THREAD(h)))) {
19814 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "thread", DUK_STR_NOT_THREAD);
19815 		DUK_WO_NORETURN(return NULL;);
19816 	}
19817 	return (duk_hthread *) h;
19818 }
19819 
duk_get_hcompfunc(duk_hthread * thr,duk_idx_t idx)19820 DUK_INTERNAL duk_hcompfunc *duk_get_hcompfunc(duk_hthread *thr, duk_idx_t idx) {
19821 	duk_hobject *h;
19822 
19823 	DUK_ASSERT_API_ENTRY(thr);
19824 
19825 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19826 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_COMPFUNC(h))) {
19827 		h = NULL;
19828 	}
19829 	return (duk_hcompfunc *) h;
19830 }
19831 
duk_require_hcompfunc(duk_hthread * thr,duk_idx_t idx)19832 DUK_INTERNAL duk_hcompfunc *duk_require_hcompfunc(duk_hthread *thr, duk_idx_t idx) {
19833 	duk_hobject *h;
19834 
19835 	DUK_ASSERT_API_ENTRY(thr);
19836 
19837 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19838 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_COMPFUNC(h)))) {
19839 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "compiledfunction", DUK_STR_NOT_COMPFUNC);
19840 		DUK_WO_NORETURN(return NULL;);
19841 	}
19842 	return (duk_hcompfunc *) h;
19843 }
19844 
duk_get_hnatfunc(duk_hthread * thr,duk_idx_t idx)19845 DUK_INTERNAL duk_hnatfunc *duk_get_hnatfunc(duk_hthread *thr, duk_idx_t idx) {
19846 	duk_hobject *h;
19847 
19848 	DUK_ASSERT_API_ENTRY(thr);
19849 
19850 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19851 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_NATFUNC(h))) {
19852 		h = NULL;
19853 	}
19854 	return (duk_hnatfunc *) h;
19855 }
19856 
duk_require_hnatfunc(duk_hthread * thr,duk_idx_t idx)19857 DUK_INTERNAL duk_hnatfunc *duk_require_hnatfunc(duk_hthread *thr, duk_idx_t idx) {
19858 	duk_hobject *h;
19859 
19860 	DUK_ASSERT_API_ENTRY(thr);
19861 
19862 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19863 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_NATFUNC(h)))) {
19864 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC);
19865 		DUK_WO_NORETURN(return NULL;);
19866 	}
19867 	return (duk_hnatfunc *) h;
19868 }
19869 
duk_get_c_function(duk_hthread * thr,duk_idx_t idx)19870 DUK_EXTERNAL duk_c_function duk_get_c_function(duk_hthread *thr, duk_idx_t idx) {
19871 	duk_tval *tv;
19872 	duk_hobject *h;
19873 	duk_hnatfunc *f;
19874 
19875 	DUK_ASSERT_API_ENTRY(thr);
19876 
19877 	tv = duk_get_tval_or_unused(thr, idx);
19878 	DUK_ASSERT(tv != NULL);
19879 	if (DUK_UNLIKELY(!DUK_TVAL_IS_OBJECT(tv))) {
19880 		return NULL;
19881 	}
19882 	h = DUK_TVAL_GET_OBJECT(tv);
19883 	DUK_ASSERT(h != NULL);
19884 
19885 	if (DUK_UNLIKELY(!DUK_HOBJECT_IS_NATFUNC(h))) {
19886 		return NULL;
19887 	}
19888 	DUK_ASSERT(DUK_HOBJECT_HAS_NATFUNC(h));
19889 	f = (duk_hnatfunc *) h;
19890 
19891 	return f->func;
19892 }
19893 
duk_opt_c_function(duk_hthread * thr,duk_idx_t idx,duk_c_function def_value)19894 DUK_EXTERNAL duk_c_function duk_opt_c_function(duk_hthread *thr, duk_idx_t idx, duk_c_function def_value) {
19895 	DUK_ASSERT_API_ENTRY(thr);
19896 
19897 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19898 		return def_value;
19899 	}
19900 	return duk_require_c_function(thr, idx);
19901 }
19902 
duk_get_c_function_default(duk_hthread * thr,duk_idx_t idx,duk_c_function def_value)19903 DUK_EXTERNAL duk_c_function duk_get_c_function_default(duk_hthread *thr, duk_idx_t idx, duk_c_function def_value) {
19904 	duk_c_function ret;
19905 
19906 	DUK_ASSERT_API_ENTRY(thr);
19907 
19908 	ret = duk_get_c_function(thr, idx);
19909 	if (ret != NULL) {
19910 		return ret;
19911 	}
19912 
19913 	return def_value;
19914 }
19915 
duk_require_c_function(duk_hthread * thr,duk_idx_t idx)19916 DUK_EXTERNAL duk_c_function duk_require_c_function(duk_hthread *thr, duk_idx_t idx) {
19917 	duk_c_function ret;
19918 
19919 	DUK_ASSERT_API_ENTRY(thr);
19920 
19921 	ret = duk_get_c_function(thr, idx);
19922 	if (DUK_UNLIKELY(!ret)) {
19923 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC);
19924 		DUK_WO_NORETURN(return ret;);
19925 	}
19926 	return ret;
19927 }
19928 
duk_require_function(duk_hthread * thr,duk_idx_t idx)19929 DUK_EXTERNAL void duk_require_function(duk_hthread *thr, duk_idx_t idx) {
19930 	DUK_ASSERT_API_ENTRY(thr);
19931 	if (DUK_UNLIKELY(!duk_is_function(thr, idx))) {
19932 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "function", DUK_STR_NOT_FUNCTION);
19933 		DUK_WO_NORETURN(return;);
19934 	}
19935 }
19936 
duk_require_constructable(duk_hthread * thr,duk_idx_t idx)19937 DUK_EXTERNAL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx) {
19938 	duk_hobject *h;
19939 
19940 	DUK_ASSERT_API_ENTRY(thr);
19941 
19942 	h = duk_require_hobject_accept_mask(thr, idx, DUK_TYPE_MASK_LIGHTFUNC);
19943 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_HAS_CONSTRUCTABLE(h))) {
19944 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "constructable", DUK_STR_NOT_CONSTRUCTABLE);
19945 		DUK_WO_NORETURN(return;);
19946 	}
19947 	/* Lightfuncs (h == NULL) are constructable. */
19948 }
19949 
duk_get_context(duk_hthread * thr,duk_idx_t idx)19950 DUK_EXTERNAL duk_hthread *duk_get_context(duk_hthread *thr, duk_idx_t idx) {
19951 	DUK_ASSERT_API_ENTRY(thr);
19952 
19953 	return duk_get_hthread(thr, idx);
19954 }
19955 
duk_require_context(duk_hthread * thr,duk_idx_t idx)19956 DUK_EXTERNAL duk_hthread *duk_require_context(duk_hthread *thr, duk_idx_t idx) {
19957 	DUK_ASSERT_API_ENTRY(thr);
19958 
19959 	return duk_require_hthread(thr, idx);
19960 }
19961 
duk_opt_context(duk_hthread * thr,duk_idx_t idx,duk_hthread * def_value)19962 DUK_EXTERNAL duk_hthread *duk_opt_context(duk_hthread *thr, duk_idx_t idx, duk_hthread *def_value) {
19963 	DUK_ASSERT_API_ENTRY(thr);
19964 
19965 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19966 		return def_value;
19967 	}
19968 	return duk_require_context(thr, idx);
19969 }
19970 
duk_get_context_default(duk_hthread * thr,duk_idx_t idx,duk_hthread * def_value)19971 DUK_EXTERNAL duk_hthread *duk_get_context_default(duk_hthread *thr, duk_idx_t idx, duk_hthread *def_value) {
19972 	duk_hthread *ret;
19973 
19974 	DUK_ASSERT_API_ENTRY(thr);
19975 
19976 	ret = duk_get_context(thr, idx);
19977 	if (ret != NULL) {
19978 		return ret;
19979 	}
19980 
19981 	return def_value;
19982 }
19983 
duk_get_heapptr(duk_hthread * thr,duk_idx_t idx)19984 DUK_EXTERNAL void *duk_get_heapptr(duk_hthread *thr, duk_idx_t idx) {
19985 	duk_tval *tv;
19986 	void *ret;
19987 
19988 	DUK_ASSERT_API_ENTRY(thr);
19989 
19990 	tv = duk_get_tval_or_unused(thr, idx);
19991 	DUK_ASSERT(tv != NULL);
19992 	if (DUK_UNLIKELY(!DUK_TVAL_IS_HEAP_ALLOCATED(tv))) {
19993 		return (void *) NULL;
19994 	}
19995 
19996 	ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
19997 	DUK_ASSERT(ret != NULL);
19998 	return ret;
19999 }
20000 
duk_opt_heapptr(duk_hthread * thr,duk_idx_t idx,void * def_value)20001 DUK_EXTERNAL void *duk_opt_heapptr(duk_hthread *thr, duk_idx_t idx, void *def_value) {
20002 	DUK_ASSERT_API_ENTRY(thr);
20003 
20004 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
20005 		return def_value;
20006 	}
20007 	return duk_require_heapptr(thr, idx);
20008 }
20009 
duk_get_heapptr_default(duk_hthread * thr,duk_idx_t idx,void * def_value)20010 DUK_EXTERNAL void *duk_get_heapptr_default(duk_hthread *thr, duk_idx_t idx, void *def_value) {
20011 	void *ret;
20012 
20013 	DUK_ASSERT_API_ENTRY(thr);
20014 
20015 	ret = duk_get_heapptr(thr, idx);
20016 	if (ret != NULL) {
20017 		return ret;
20018 	}
20019 
20020 	return def_value;
20021 }
20022 
duk_require_heapptr(duk_hthread * thr,duk_idx_t idx)20023 DUK_EXTERNAL void *duk_require_heapptr(duk_hthread *thr, duk_idx_t idx) {
20024 	duk_tval *tv;
20025 	void *ret;
20026 
20027 	DUK_ASSERT_API_ENTRY(thr);
20028 
20029 	tv = duk_get_tval_or_unused(thr, idx);
20030 	DUK_ASSERT(tv != NULL);
20031 	if (DUK_UNLIKELY(!DUK_TVAL_IS_HEAP_ALLOCATED(tv))) {
20032 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "heapobject", DUK_STR_UNEXPECTED_TYPE);
20033 		DUK_WO_NORETURN(return NULL;);
20034 	}
20035 
20036 	ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
20037 	DUK_ASSERT(ret != NULL);
20038 	return ret;
20039 }
20040 
20041 /* 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)20042 DUK_LOCAL duk_hobject *duk__get_hobject_promote_mask_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
20043 	duk_uint_t val_mask;
20044 	duk_hobject *res;
20045 
20046 	DUK_CTX_ASSERT_VALID(thr);
20047 
20048 	res = duk_get_hobject(thr, idx);  /* common case, not promoted */
20049 	if (DUK_LIKELY(res != NULL)) {
20050 		DUK_ASSERT(res != NULL);
20051 		return res;
20052 	}
20053 
20054 	val_mask = duk_get_type_mask(thr, idx);
20055 	if (val_mask & type_mask) {
20056 		if (type_mask & DUK_TYPE_MASK_PROMOTE) {
20057 			res = duk_to_hobject(thr, idx);
20058 			DUK_ASSERT(res != NULL);
20059 			return res;
20060 		} else {
20061 			return NULL;  /* accept without promoting */
20062 		}
20063 	}
20064 
20065 	if (type_mask & DUK_TYPE_MASK_THROW) {
20066 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
20067 		DUK_WO_NORETURN(return NULL;);
20068 	}
20069 	return NULL;
20070 }
20071 
20072 /* Get a duk_hobject * at 'idx'; if the value is not an object but matches the
20073  * supplied 'type_mask', promote it to an object and return the duk_hobject *.
20074  * This is useful for call sites which want an object but also accept a plain
20075  * buffer and/or a lightfunc which gets automatically promoted to an object.
20076  * Return value is NULL if value is neither an object nor a plain type allowed
20077  * by the mask.
20078  */
duk_get_hobject_promote_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t type_mask)20079 DUK_INTERNAL duk_hobject *duk_get_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
20080 	DUK_ASSERT_API_ENTRY(thr);
20081 	return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_PROMOTE);
20082 }
20083 
20084 /* Like duk_get_hobject_promote_mask() but throw a TypeError instead of
20085  * returning a NULL.
20086  */
duk_require_hobject_promote_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t type_mask)20087 DUK_INTERNAL duk_hobject *duk_require_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
20088 	DUK_ASSERT_API_ENTRY(thr);
20089 	return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_THROW | DUK_TYPE_MASK_PROMOTE);
20090 }
20091 
20092 /* Require a duk_hobject * at 'idx'; if the value is not an object but matches the
20093  * supplied 'type_mask', return a NULL instead.  Otherwise throw a TypeError.
20094  */
duk_require_hobject_accept_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t type_mask)20095 DUK_INTERNAL duk_hobject *duk_require_hobject_accept_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
20096 	DUK_ASSERT_API_ENTRY(thr);
20097 	return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_THROW);
20098 }
20099 
duk_get_hobject_with_class(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t classnum)20100 DUK_INTERNAL duk_hobject *duk_get_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum) {
20101 	duk_hobject *h;
20102 
20103 	DUK_ASSERT_API_ENTRY(thr);
20104 	DUK_ASSERT_DISABLE(classnum >= 0);  /* unsigned */
20105 	DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
20106 
20107 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20108 	if (DUK_UNLIKELY(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) != classnum)) {
20109 		h = NULL;
20110 	}
20111 	return h;
20112 }
20113 
duk_require_hobject_with_class(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t classnum)20114 DUK_INTERNAL duk_hobject *duk_require_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum) {
20115 	duk_hobject *h;
20116 
20117 	DUK_ASSERT_API_ENTRY(thr);
20118 	DUK_ASSERT_DISABLE(classnum >= 0);  /* unsigned */
20119 	DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
20120 
20121 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20122 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) == classnum))) {
20123 		duk_hstring *h_class;
20124 		h_class = DUK_HTHREAD_GET_STRING(thr, DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum));
20125 		DUK_UNREF(h_class);
20126 
20127 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, (const char *) DUK_HSTRING_GET_DATA(h_class), DUK_STR_UNEXPECTED_TYPE);
20128 		DUK_WO_NORETURN(return NULL;);
20129 	}
20130 	return h;
20131 }
20132 
duk_get_length(duk_hthread * thr,duk_idx_t idx)20133 DUK_EXTERNAL duk_size_t duk_get_length(duk_hthread *thr, duk_idx_t idx) {
20134 	duk_tval *tv;
20135 
20136 	DUK_ASSERT_API_ENTRY(thr);
20137 
20138 	tv = duk_get_tval_or_unused(thr, idx);
20139 	DUK_ASSERT(tv != NULL);
20140 
20141 	switch (DUK_TVAL_GET_TAG(tv)) {
20142 	case DUK_TAG_UNDEFINED:
20143 	case DUK_TAG_NULL:
20144 	case DUK_TAG_BOOLEAN:
20145 	case DUK_TAG_POINTER:
20146 		return 0;
20147 #if defined(DUK_USE_PREFER_SIZE)
20148 	/* String and buffer have a virtual non-configurable .length property
20149 	 * which is within size_t range so it can be looked up without specific
20150 	 * type checks.  Lightfuncs inherit from %NativeFunctionPrototype%
20151 	 * which provides an inherited .length accessor; it could be overwritten
20152 	 * to produce unexpected types or values, but just number convert and
20153 	 * duk_size_t cast for now.
20154 	 */
20155 	case DUK_TAG_STRING:
20156 	case DUK_TAG_BUFFER:
20157 	case DUK_TAG_LIGHTFUNC: {
20158 		duk_size_t ret;
20159 		duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
20160 		ret = (duk_size_t) duk_to_number_m1(thr);
20161 		duk_pop_unsafe(thr);
20162 		return ret;
20163 	}
20164 #else  /* DUK_USE_PREFER_SIZE */
20165 	case DUK_TAG_STRING: {
20166 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
20167 		DUK_ASSERT(h != NULL);
20168 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
20169 			return 0;
20170 		}
20171 		return (duk_size_t) DUK_HSTRING_GET_CHARLEN(h);
20172 	}
20173 	case DUK_TAG_BUFFER: {
20174 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
20175 		DUK_ASSERT(h != NULL);
20176 		return (duk_size_t) DUK_HBUFFER_GET_SIZE(h);
20177 	}
20178 	case DUK_TAG_LIGHTFUNC: {
20179 		/* We could look up the length from the lightfunc duk_tval,
20180 		 * but since Duktape 2.2 lightfunc .length comes from
20181 		 * %NativeFunctionPrototype% which can be overridden, so
20182 		 * look up the property explicitly.
20183 		 */
20184 		duk_size_t ret;
20185 		duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
20186 		ret = (duk_size_t) duk_to_number_m1(thr);
20187 		duk_pop_unsafe(thr);
20188 		return ret;
20189 	}
20190 #endif  /* DUK_USE_PREFER_SIZE */
20191 	case DUK_TAG_OBJECT: {
20192 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
20193 		DUK_ASSERT(h != NULL);
20194 		return (duk_size_t) duk_hobject_get_length(thr, h);
20195 	}
20196 #if defined(DUK_USE_FASTINT)
20197 	case DUK_TAG_FASTINT:
20198 #endif
20199 	default:
20200 		/* number or 'unused' */
20201 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv) || DUK_TVAL_IS_UNUSED(tv));
20202 		return 0;
20203 	}
20204 
20205 	DUK_UNREACHABLE();
20206 }
20207 
20208 /*
20209  *  duk_known_xxx() helpers
20210  *
20211  *  Used internally when we're 100% sure that a certain index is valid and
20212  *  contains an object of a certain type.  For example, if we duk_push_object()
20213  *  we can then safely duk_known_hobject(thr, -1).  These helpers just assert
20214  *  for the index and type, and if the assumptions are not valid, memory unsafe
20215  *  behavior happens.
20216  */
20217 
duk__known_heaphdr(duk_hthread * thr,duk_idx_t idx)20218 DUK_LOCAL duk_heaphdr *duk__known_heaphdr(duk_hthread *thr, duk_idx_t idx) {
20219 	duk_tval *tv;
20220 	duk_heaphdr *h;
20221 
20222 	DUK_CTX_ASSERT_VALID(thr);
20223 	if (idx < 0) {
20224 		tv = thr->valstack_top + idx;
20225 	} else {
20226 		tv = thr->valstack_bottom + idx;
20227 	}
20228 	DUK_ASSERT(tv >= thr->valstack_bottom);
20229 	DUK_ASSERT(tv < thr->valstack_top);
20230 	h = DUK_TVAL_GET_HEAPHDR(tv);
20231 	DUK_ASSERT(h != NULL);
20232 	return h;
20233 }
20234 
duk_known_hstring(duk_hthread * thr,duk_idx_t idx)20235 DUK_INTERNAL duk_hstring *duk_known_hstring(duk_hthread *thr, duk_idx_t idx) {
20236 	DUK_ASSERT_API_ENTRY(thr);
20237 	DUK_ASSERT(duk_get_hstring(thr, idx) != NULL);
20238 	return (duk_hstring *) duk__known_heaphdr(thr, idx);
20239 }
20240 
duk_known_hobject(duk_hthread * thr,duk_idx_t idx)20241 DUK_INTERNAL duk_hobject *duk_known_hobject(duk_hthread *thr, duk_idx_t idx) {
20242 	DUK_ASSERT_API_ENTRY(thr);
20243 	DUK_ASSERT(duk_get_hobject(thr, idx) != NULL);
20244 	return (duk_hobject *) duk__known_heaphdr(thr, idx);
20245 }
20246 
duk_known_hbuffer(duk_hthread * thr,duk_idx_t idx)20247 DUK_INTERNAL duk_hbuffer *duk_known_hbuffer(duk_hthread *thr, duk_idx_t idx) {
20248 	DUK_ASSERT_API_ENTRY(thr);
20249 	DUK_ASSERT(duk_get_hbuffer(thr, idx) != NULL);
20250 	return (duk_hbuffer *) duk__known_heaphdr(thr, idx);
20251 }
20252 
duk_known_hcompfunc(duk_hthread * thr,duk_idx_t idx)20253 DUK_INTERNAL duk_hcompfunc *duk_known_hcompfunc(duk_hthread *thr, duk_idx_t idx) {
20254 	DUK_ASSERT_API_ENTRY(thr);
20255 	DUK_ASSERT(duk_get_hcompfunc(thr, idx) != NULL);
20256 	return (duk_hcompfunc *) duk__known_heaphdr(thr, idx);
20257 }
20258 
duk_known_hnatfunc(duk_hthread * thr,duk_idx_t idx)20259 DUK_INTERNAL duk_hnatfunc *duk_known_hnatfunc(duk_hthread *thr, duk_idx_t idx) {
20260 	DUK_ASSERT_API_ENTRY(thr);
20261 	DUK_ASSERT(duk_get_hnatfunc(thr, idx) != NULL);
20262 	return (duk_hnatfunc *) duk__known_heaphdr(thr, idx);
20263 }
20264 
duk_set_length(duk_hthread * thr,duk_idx_t idx,duk_size_t len)20265 DUK_EXTERNAL void duk_set_length(duk_hthread *thr, duk_idx_t idx, duk_size_t len) {
20266 	DUK_ASSERT_API_ENTRY(thr);
20267 
20268 	idx = duk_normalize_index(thr, idx);
20269 	duk_push_uint(thr, (duk_uint_t) len);
20270 	duk_put_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
20271 }
20272 
20273 /*
20274  *  Conversions and coercions
20275  *
20276  *  The conversion/coercions are in-place operations on the value stack.
20277  *  Some operations are implemented here directly, while others call a
20278  *  helper in duk_js_ops.c after validating arguments.
20279  */
20280 
20281 /* E5 Section 8.12.8 */
20282 
duk__defaultvalue_coerce_attempt(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t func_stridx)20283 DUK_LOCAL duk_bool_t duk__defaultvalue_coerce_attempt(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t func_stridx) {
20284 	if (duk_get_prop_stridx(thr, idx, func_stridx)) {
20285 		/* [ ... func ] */
20286 		if (duk_is_callable(thr, -1)) {
20287 			duk_dup(thr, idx);         /* -> [ ... func this ] */
20288 			duk_call_method(thr, 0);     /* -> [ ... retval ] */
20289 			if (duk_is_primitive(thr, -1)) {
20290 				duk_replace(thr, idx);
20291 				return 1;
20292 			}
20293 			/* [ ... retval ]; popped below */
20294 		}
20295 	}
20296 	duk_pop_unsafe(thr);  /* [ ... func/retval ] -> [ ... ] */
20297 	return 0;
20298 }
20299 
duk_to_undefined(duk_hthread * thr,duk_idx_t idx)20300 DUK_EXTERNAL void duk_to_undefined(duk_hthread *thr, duk_idx_t idx) {
20301 	duk_tval *tv;
20302 
20303 	DUK_ASSERT_API_ENTRY(thr);
20304 
20305 	tv = duk_require_tval(thr, idx);
20306 	DUK_ASSERT(tv != NULL);
20307 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
20308 }
20309 
duk_to_null(duk_hthread * thr,duk_idx_t idx)20310 DUK_EXTERNAL void duk_to_null(duk_hthread *thr, duk_idx_t idx) {
20311 	duk_tval *tv;
20312 
20313 	DUK_ASSERT_API_ENTRY(thr);
20314 
20315 	tv = duk_require_tval(thr, idx);
20316 	DUK_ASSERT(tv != NULL);
20317 	DUK_TVAL_SET_NULL_UPDREF(thr, tv);  /* side effects */
20318 }
20319 
20320 /* E5 Section 9.1 */
20321 DUK_LOCAL const char * const duk__toprim_hint_strings[3] = {
20322 	"default", "string", "number"
20323 };
duk__to_primitive_helper(duk_hthread * thr,duk_idx_t idx,duk_int_t hint,duk_bool_t check_symbol)20324 DUK_LOCAL void duk__to_primitive_helper(duk_hthread *thr, duk_idx_t idx, duk_int_t hint, duk_bool_t check_symbol) {
20325 	/* Inline initializer for coercers[] is not allowed by old compilers like BCC. */
20326 	duk_small_uint_t coercers[2];
20327 
20328 	DUK_ASSERT_API_ENTRY(thr);
20329 	DUK_ASSERT(hint == DUK_HINT_NONE || hint == DUK_HINT_NUMBER || hint == DUK_HINT_STRING);
20330 
20331 	idx = duk_require_normalize_index(thr, idx);
20332 
20333 	/* If already primitive, return as is. */
20334 	if (!duk_check_type_mask(thr, idx, DUK_TYPE_MASK_OBJECT |
20335 	                                   DUK_TYPE_MASK_LIGHTFUNC |
20336 	                                   DUK_TYPE_MASK_BUFFER)) {
20337 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */
20338 		return;
20339 	}
20340 
20341 	/* @@toPrimitive lookup.  Also do for plain buffers and lightfuncs
20342 	 * which mimic objects.
20343 	 */
20344 	if (check_symbol && duk_get_method_stridx(thr, idx, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)) {
20345 		DUK_ASSERT(hint >= 0 && (duk_size_t) hint < sizeof(duk__toprim_hint_strings) / sizeof(const char *));
20346 		duk_dup(thr, idx);
20347 		duk_push_string(thr, duk__toprim_hint_strings[hint]);
20348 		duk_call_method(thr, 1);  /* [ ... method value hint ] -> [ ... res] */
20349 		if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
20350 	                                         DUK_TYPE_MASK_LIGHTFUNC |
20351 		                                 DUK_TYPE_MASK_BUFFER)) {
20352 			goto fail;
20353 		}
20354 		duk_replace(thr, idx);
20355 		return;
20356 	}
20357 
20358 	/* Objects are coerced based on E5 specification.
20359 	 * Lightfuncs are coerced because they behave like
20360 	 * objects even if they're internally a primitive
20361 	 * type.  Same applies to plain buffers, which behave
20362 	 * like ArrayBuffer objects since Duktape 2.x.
20363 	 */
20364 
20365 	/* Hint magic for Date is unnecessary in ES2015 because of
20366 	 * Date.prototype[@@toPrimitive].  However, it is needed if
20367 	 * symbol support is not enabled.
20368 	 */
20369 #if defined(DUK_USE_SYMBOL_BUILTIN)
20370 	if (hint == DUK_HINT_NONE) {
20371 		hint = DUK_HINT_NUMBER;
20372 	}
20373 #else  /* DUK_USE_SYMBOL_BUILTIN */
20374 	if (hint == DUK_HINT_NONE) {
20375 		duk_small_uint_t class_number;
20376 
20377 		class_number = duk_get_class_number(thr, idx);
20378 		if (class_number == DUK_HOBJECT_CLASS_DATE) {
20379 			hint = DUK_HINT_STRING;
20380 		} else {
20381 			hint = DUK_HINT_NUMBER;
20382 		}
20383 	}
20384 #endif  /* DUK_USE_SYMBOL_BUILTIN */
20385 
20386 	coercers[0] = DUK_STRIDX_VALUE_OF;
20387 	coercers[1] = DUK_STRIDX_TO_STRING;
20388 	if (hint == DUK_HINT_STRING) {
20389 		coercers[0] = DUK_STRIDX_TO_STRING;
20390 		coercers[1] = DUK_STRIDX_VALUE_OF;
20391 	}
20392 
20393 	if (duk__defaultvalue_coerce_attempt(thr, idx, coercers[0])) {
20394 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */
20395 		return;
20396 	}
20397 
20398 	if (duk__defaultvalue_coerce_attempt(thr, idx, coercers[1])) {
20399 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */
20400 		return;
20401 	}
20402 
20403  fail:
20404 	DUK_ERROR_TYPE(thr, DUK_STR_TOPRIMITIVE_FAILED);
20405 	DUK_WO_NORETURN(return;);
20406 }
20407 
duk_to_primitive(duk_hthread * thr,duk_idx_t idx,duk_int_t hint)20408 DUK_EXTERNAL void duk_to_primitive(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) {
20409 	duk__to_primitive_helper(thr, idx, hint, 1 /*check_symbol*/);
20410 }
20411 
20412 #if defined(DUK_USE_SYMBOL_BUILTIN)
duk_to_primitive_ordinary(duk_hthread * thr,duk_idx_t idx,duk_int_t hint)20413 DUK_INTERNAL void duk_to_primitive_ordinary(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) {
20414 	duk__to_primitive_helper(thr, idx, hint, 0 /*check_symbol*/);
20415 }
20416 #endif
20417 
20418 /* E5 Section 9.2 */
duk_to_boolean(duk_hthread * thr,duk_idx_t idx)20419 DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_hthread *thr, duk_idx_t idx) {
20420 	duk_tval *tv;
20421 	duk_bool_t val;
20422 
20423 	DUK_ASSERT_API_ENTRY(thr);
20424 
20425 	idx = duk_require_normalize_index(thr, idx);
20426 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
20427 	DUK_ASSERT(tv != NULL);
20428 
20429 	val = duk_js_toboolean(tv);
20430 	DUK_ASSERT(val == 0 || val == 1);
20431 
20432 	/* Note: no need to re-lookup tv, conversion is side effect free. */
20433 	DUK_ASSERT(tv != NULL);
20434 	DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, val);  /* side effects */
20435 	return val;
20436 }
20437 
duk_to_boolean_top_pop(duk_hthread * thr)20438 DUK_INTERNAL duk_bool_t duk_to_boolean_top_pop(duk_hthread *thr) {
20439 	duk_tval *tv;
20440 	duk_bool_t val;
20441 
20442 	DUK_ASSERT_API_ENTRY(thr);
20443 
20444 	tv = duk_require_tval(thr, -1);
20445 	DUK_ASSERT(tv != NULL);
20446 
20447 	val = duk_js_toboolean(tv);
20448 	DUK_ASSERT(val == 0 || val == 1);
20449 
20450 	duk_pop_unsafe(thr);
20451 	return val;
20452 }
20453 
duk_to_number(duk_hthread * thr,duk_idx_t idx)20454 DUK_EXTERNAL duk_double_t duk_to_number(duk_hthread *thr, duk_idx_t idx) {
20455 	duk_tval *tv;
20456 	duk_double_t d;
20457 
20458 	DUK_ASSERT_API_ENTRY(thr);
20459 
20460 	/* XXX: No need to normalize; the whole operation could be inlined here to
20461 	 * avoid 'tv' re-lookup.
20462 	 */
20463 	idx = duk_require_normalize_index(thr, idx);
20464 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
20465 	DUK_ASSERT(tv != NULL);
20466 	d = duk_js_tonumber(thr, tv);  /* XXX: fastint coercion? now result will always be a non-fastint */
20467 
20468 	/* ToNumber() may have side effects so must relookup 'tv'. */
20469 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
20470 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d);  /* side effects */
20471 	return d;
20472 }
20473 
duk_to_number_m1(duk_hthread * thr)20474 DUK_INTERNAL duk_double_t duk_to_number_m1(duk_hthread *thr) {
20475 	DUK_ASSERT_API_ENTRY(thr);
20476 	return duk_to_number(thr, -1);
20477 }
duk_to_number_m2(duk_hthread * thr)20478 DUK_INTERNAL duk_double_t duk_to_number_m2(duk_hthread *thr) {
20479 	DUK_ASSERT_API_ENTRY(thr);
20480 	return duk_to_number(thr, -2);
20481 }
20482 
duk_to_number_tval(duk_hthread * thr,duk_tval * tv)20483 DUK_INTERNAL duk_double_t duk_to_number_tval(duk_hthread *thr, duk_tval *tv) {
20484 #if defined(DUK_USE_PREFER_SIZE)
20485 	duk_double_t res;
20486 
20487 	DUK_ASSERT_API_ENTRY(thr);
20488 
20489 	duk_push_tval(thr, tv);
20490 	res = duk_to_number_m1(thr);
20491 	duk_pop_unsafe(thr);
20492 	return res;
20493 #else
20494 	duk_double_t res;
20495 	duk_tval *tv_dst;
20496 
20497 	DUK_ASSERT_API_ENTRY(thr);
20498 	DUK__ASSERT_SPACE();
20499 
20500 	tv_dst = thr->valstack_top++;
20501 	DUK_TVAL_SET_TVAL(tv_dst, tv);
20502 	DUK_TVAL_INCREF(thr, tv_dst);  /* decref not necessary */
20503 	res = duk_to_number_m1(thr);  /* invalidates tv_dst */
20504 
20505 	tv_dst = --thr->valstack_top;
20506 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_dst));
20507 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv_dst));  /* plain number */
20508 	DUK_TVAL_SET_UNDEFINED(tv_dst);  /* valstack init policy */
20509 
20510 	return res;
20511 #endif
20512 }
20513 
20514 /* XXX: combine all the integer conversions: they share everything
20515  * but the helper function for coercion.
20516  */
20517 
20518 typedef duk_double_t (*duk__toint_coercer)(duk_hthread *thr, duk_tval *tv);
20519 
duk__to_int_uint_helper(duk_hthread * thr,duk_idx_t idx,duk__toint_coercer coerce_func)20520 DUK_LOCAL duk_double_t duk__to_int_uint_helper(duk_hthread *thr, duk_idx_t idx, duk__toint_coercer coerce_func) {
20521 	duk_tval *tv;
20522 	duk_double_t d;
20523 
20524 	DUK_CTX_ASSERT_VALID(thr);
20525 
20526 	tv = duk_require_tval(thr, idx);
20527 	DUK_ASSERT(tv != NULL);
20528 
20529 #if defined(DUK_USE_FASTINT)
20530 	/* If argument is a fastint, guarantee that it remains one.
20531 	 * There's no downgrade check for other cases.
20532 	 */
20533 	if (DUK_TVAL_IS_FASTINT(tv)) {
20534 		/* XXX: Unnecessary conversion back and forth. */
20535 		return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
20536 	}
20537 #endif
20538 	d = coerce_func(thr, tv);
20539 
20540 	/* XXX: fastint? */
20541 
20542 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
20543 	tv = duk_require_tval(thr, idx);
20544 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d);  /* side effects */
20545 	return d;
20546 }
20547 
duk_to_int(duk_hthread * thr,duk_idx_t idx)20548 DUK_EXTERNAL duk_int_t duk_to_int(duk_hthread *thr, duk_idx_t idx) {
20549 	/* Value coercion (in stack): ToInteger(), E5 Section 9.4,
20550 	 * API return value coercion: custom.
20551 	 */
20552 	DUK_ASSERT_API_ENTRY(thr);
20553 	(void) duk__to_int_uint_helper(thr, idx, duk_js_tointeger);
20554 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 0 /*require*/);
20555 }
20556 
duk_to_uint(duk_hthread * thr,duk_idx_t idx)20557 DUK_EXTERNAL duk_uint_t duk_to_uint(duk_hthread *thr, duk_idx_t idx) {
20558 	/* Value coercion (in stack): ToInteger(), E5 Section 9.4,
20559 	 * API return value coercion: custom.
20560 	 */
20561 	DUK_ASSERT_API_ENTRY(thr);
20562 	(void) duk__to_int_uint_helper(thr, idx, duk_js_tointeger);
20563 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 0 /*require*/);
20564 }
20565 
duk_to_int32(duk_hthread * thr,duk_idx_t idx)20566 DUK_EXTERNAL duk_int32_t duk_to_int32(duk_hthread *thr, duk_idx_t idx) {
20567 	duk_tval *tv;
20568 	duk_int32_t ret;
20569 
20570 	DUK_ASSERT_API_ENTRY(thr);
20571 
20572 	tv = duk_require_tval(thr, idx);
20573 	DUK_ASSERT(tv != NULL);
20574 	ret = duk_js_toint32(thr, tv);
20575 
20576 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
20577 	tv = duk_require_tval(thr, idx);
20578 	DUK_TVAL_SET_I32_UPDREF(thr, tv, ret);  /* side effects */
20579 	return ret;
20580 }
20581 
duk_to_uint32(duk_hthread * thr,duk_idx_t idx)20582 DUK_EXTERNAL duk_uint32_t duk_to_uint32(duk_hthread *thr, duk_idx_t idx) {
20583 	duk_tval *tv;
20584 	duk_uint32_t ret;
20585 
20586 	DUK_ASSERT_API_ENTRY(thr);
20587 
20588 	tv = duk_require_tval(thr, idx);
20589 	DUK_ASSERT(tv != NULL);
20590 	ret = duk_js_touint32(thr, tv);
20591 
20592 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
20593 	tv = duk_require_tval(thr, idx);
20594 	DUK_TVAL_SET_U32_UPDREF(thr, tv, ret);  /* side effects */
20595 	return ret;
20596 }
20597 
duk_to_uint16(duk_hthread * thr,duk_idx_t idx)20598 DUK_EXTERNAL duk_uint16_t duk_to_uint16(duk_hthread *thr, duk_idx_t idx) {
20599 	duk_tval *tv;
20600 	duk_uint16_t ret;
20601 
20602 	DUK_ASSERT_API_ENTRY(thr);
20603 
20604 	tv = duk_require_tval(thr, idx);
20605 	DUK_ASSERT(tv != NULL);
20606 	ret = duk_js_touint16(thr, tv);
20607 
20608 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
20609 	tv = duk_require_tval(thr, idx);
20610 	DUK_TVAL_SET_U32_UPDREF(thr, tv, ret);  /* side effects */
20611 	return ret;
20612 }
20613 
20614 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
20615 /* Special coercion for Uint8ClampedArray. */
duk_to_uint8clamped(duk_hthread * thr,duk_idx_t idx)20616 DUK_INTERNAL duk_uint8_t duk_to_uint8clamped(duk_hthread *thr, duk_idx_t idx) {
20617 	duk_double_t d;
20618 	duk_double_t t;
20619 	duk_uint8_t ret;
20620 
20621 	DUK_ASSERT_API_ENTRY(thr);
20622 
20623 	/* XXX: Simplify this algorithm, should be possible to come up with
20624 	 * a shorter and faster algorithm by inspecting IEEE representation
20625 	 * directly.
20626 	 */
20627 
20628 	d = duk_to_number(thr, idx);
20629 	if (d <= 0.0) {
20630 		return 0;
20631 	} else if (d >= 255) {
20632 		return 255;
20633 	} else if (DUK_ISNAN(d)) {
20634 		/* Avoid NaN-to-integer coercion as it is compiler specific. */
20635 		return 0;
20636 	}
20637 
20638 	t = d - DUK_FLOOR(d);
20639 	if (t == 0.5) {
20640 		/* Exact halfway, round to even. */
20641 		ret = (duk_uint8_t) d;
20642 		ret = (ret + 1) & 0xfe;  /* Example: d=3.5, t=0.5 -> ret = (3 + 1) & 0xfe = 4 & 0xfe = 4
20643 		                          * Example: d=4.5, t=0.5 -> ret = (4 + 1) & 0xfe = 5 & 0xfe = 4
20644 		                          */
20645 	} else {
20646 		/* Not halfway, round to nearest. */
20647 		ret = (duk_uint8_t) (d + 0.5);
20648 	}
20649 	return ret;
20650 }
20651 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
20652 
duk_to_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)20653 DUK_EXTERNAL const char *duk_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
20654 	DUK_ASSERT_API_ENTRY(thr);
20655 
20656 	(void) duk_to_string(thr, idx);
20657 	DUK_ASSERT(duk_is_string(thr, idx));
20658 	return duk_require_lstring(thr, idx, out_len);
20659 }
20660 
duk__safe_to_string_raw(duk_hthread * thr,void * udata)20661 DUK_LOCAL duk_ret_t duk__safe_to_string_raw(duk_hthread *thr, void *udata) {
20662 	DUK_CTX_ASSERT_VALID(thr);
20663 	DUK_UNREF(udata);
20664 
20665 	(void) duk_to_string(thr, -1);
20666 	return 1;
20667 }
20668 
duk_safe_to_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)20669 DUK_EXTERNAL const char *duk_safe_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
20670 	DUK_ASSERT_API_ENTRY(thr);
20671 
20672 	idx = duk_require_normalize_index(thr, idx);
20673 
20674 	/* We intentionally ignore the duk_safe_call() return value and only
20675 	 * check the output type.  This way we don't also need to check that
20676 	 * the returned value is indeed a string in the success case.
20677 	 */
20678 
20679 	duk_dup(thr, idx);
20680 	(void) duk_safe_call(thr, duk__safe_to_string_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
20681 	if (!duk_is_string(thr, -1)) {
20682 		/* Error: try coercing error to string once. */
20683 		(void) duk_safe_call(thr, duk__safe_to_string_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
20684 		if (!duk_is_string(thr, -1)) {
20685 			/* Double error */
20686 			duk_pop_unsafe(thr);
20687 			duk_push_hstring_stridx(thr, DUK_STRIDX_UC_ERROR);
20688 		} else {
20689 			;
20690 		}
20691 	} else {
20692 		/* String; may be a symbol, accepted. */
20693 		;
20694 	}
20695 	DUK_ASSERT(duk_is_string(thr, -1));
20696 
20697 	duk_replace(thr, idx);
20698 	DUK_ASSERT(duk_get_string(thr, idx) != NULL);
20699 	return duk_get_lstring(thr, idx, out_len);
20700 }
20701 
duk_to_stacktrace(duk_hthread * thr,duk_idx_t idx)20702 DUK_EXTERNAL const char *duk_to_stacktrace(duk_hthread *thr, duk_idx_t idx) {
20703 	DUK_ASSERT_API_ENTRY(thr);
20704 	idx = duk_require_normalize_index(thr, idx);
20705 
20706 	/* The expected argument to the call is an Error object.  The stack
20707 	 * trace is extracted without an inheritance-based instanceof check
20708 	 * so that one can also extract the stack trace of a foreign error
20709 	 * created in another Realm.  Accept only a string .stack property.
20710 	 */
20711 	if (duk_is_object(thr, idx)) {
20712 		(void) duk_get_prop_string(thr, idx, "stack");
20713 		if (duk_is_string(thr, -1)) {
20714 			duk_replace(thr, idx);
20715 		} else {
20716 			duk_pop(thr);
20717 		}
20718 	}
20719 
20720 	return duk_to_string(thr, idx);
20721 }
20722 
duk__safe_to_stacktrace_raw(duk_hthread * thr,void * udata)20723 DUK_LOCAL duk_ret_t duk__safe_to_stacktrace_raw(duk_hthread *thr, void *udata) {
20724 	DUK_CTX_ASSERT_VALID(thr);
20725 	DUK_UNREF(udata);
20726 
20727 	(void) duk_to_stacktrace(thr, -1);
20728 
20729 	return 1;
20730 }
20731 
duk_safe_to_stacktrace(duk_hthread * thr,duk_idx_t idx)20732 DUK_EXTERNAL const char *duk_safe_to_stacktrace(duk_hthread *thr, duk_idx_t idx) {
20733 	duk_int_t rc;
20734 
20735 	DUK_ASSERT_API_ENTRY(thr);
20736 	idx = duk_require_normalize_index(thr, idx);
20737 
20738 	duk_dup(thr, idx);
20739 	rc = duk_safe_call(thr, duk__safe_to_stacktrace_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
20740 	if (rc != 0) {
20741 		/* Coercion failed.  Try to coerce the coercion itself error
20742 		 * to a stack trace once.  If that also fails, return a fixed,
20743 		 * preallocated 'Error' string to avoid potential infinite loop.
20744 		 */
20745 		rc = duk_safe_call(thr, duk__safe_to_stacktrace_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
20746 		if (rc != 0) {
20747 			duk_pop_unsafe(thr);
20748 			duk_push_hstring_stridx(thr, DUK_STRIDX_UC_ERROR);
20749 		}
20750 	}
20751 	duk_replace(thr, idx);
20752 
20753 	return duk_get_string(thr, idx);
20754 }
20755 
duk_to_property_key_hstring(duk_hthread * thr,duk_idx_t idx)20756 DUK_INTERNAL duk_hstring *duk_to_property_key_hstring(duk_hthread *thr, duk_idx_t idx) {
20757 	duk_hstring *h;
20758 
20759 	DUK_ASSERT_API_ENTRY(thr);
20760 
20761 	duk_to_primitive(thr, idx, DUK_HINT_STRING);  /* needed for e.g. Symbol objects */
20762 	h = duk_get_hstring(thr, idx);
20763 	if (h == NULL) {
20764 		/* The "is string?" check may seem unnecessary, but as things
20765 		 * are duk_to_hstring() invokes ToString() which fails for
20766 		 * symbols.  But since symbols are already strings for Duktape
20767 		 * C API, we check for that before doing the coercion.
20768 		 */
20769 		h = duk_to_hstring(thr, idx);
20770 	}
20771 	DUK_ASSERT(h != NULL);
20772 	return h;
20773 }
20774 
20775 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* only needed by debugger for now */
duk_safe_to_hstring(duk_hthread * thr,duk_idx_t idx)20776 DUK_INTERNAL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx) {
20777 	DUK_ASSERT_API_ENTRY(thr);
20778 
20779 	(void) duk_safe_to_string(thr, idx);
20780 	DUK_ASSERT(duk_is_string(thr, idx));
20781 	DUK_ASSERT(duk_get_hstring(thr, idx) != NULL);
20782 	return duk_known_hstring(thr, idx);
20783 }
20784 #endif
20785 
20786 /* Push Object.prototype.toString() output for 'tv'. */
20787 #if 0  /* See XXX note why this variant doesn't work. */
20788 DUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects) {
20789 	duk_uint_t stridx_bidx = 0;  /* (prototype_bidx << 16) + default_tag_stridx */
20790 
20791 	DUK_ASSERT_API_ENTRY(thr);
20792 
20793 	/* Conceptually for any non-undefined/null value we should do a
20794 	 * ToObject() coercion and look up @@toStringTag (from the object
20795 	 * prototype) to see if a custom tag should be used.  Avoid the
20796 	 * actual conversion by doing a prototype lookup without the object
20797 	 * coercion.  However, see problem below.
20798 	 */
20799 
20800 	duk_push_literal(thr, "[object ");  /* -> [ ... "[object" ] */
20801 
20802 	switch (DUK_TVAL_GET_TAG(tv)) {
20803 	case DUK_TAG_UNUSED:  /* Treat like 'undefined', shouldn't happen. */
20804 	case DUK_TAG_UNDEFINED: {
20805 		stridx_bidx = DUK_STRIDX_UC_UNDEFINED;
20806 		goto use_stridx;
20807 	}
20808 	case DUK_TAG_NULL: {
20809 		stridx_bidx = DUK_STRIDX_UC_NULL;
20810 		goto use_stridx;
20811 	}
20812 	case DUK_TAG_BOOLEAN: {
20813 		stridx_bidx = (DUK_BIDX_BOOLEAN_PROTOTYPE << 16) + DUK_STRIDX_UC_BOOLEAN;
20814 		goto use_proto_bidx;
20815 	}
20816 	case DUK_TAG_POINTER: {
20817 		stridx_bidx = (DUK_BIDX_POINTER_PROTOTYPE << 16) + DUK_STRIDX_UC_POINTER;
20818 		goto use_proto_bidx;
20819 	}
20820 	case DUK_TAG_LIGHTFUNC: {
20821 		stridx_bidx = (DUK_BIDX_FUNCTION_PROTOTYPE << 16) + DUK_STRIDX_UC_FUNCTION;
20822 		goto use_proto_bidx;
20823 	}
20824 	case DUK_TAG_STRING: {
20825 		duk_hstring *h;
20826 		h = DUK_TVAL_GET_STRING(tv);
20827 		DUK_ASSERT(h != NULL);
20828 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
20829 			/* Even without DUK_USE_SYMBOL_BUILTIN the Symbol
20830 			 * prototype exists so we can lookup @@toStringTag
20831 			 * and provide [object Symbol] for symbol values
20832 			 * created from C code.
20833 			 */
20834 			stridx_bidx = (DUK_BIDX_SYMBOL_PROTOTYPE << 16) + DUK_STRIDX_UC_SYMBOL;
20835 		} else {
20836 			stridx_bidx = (DUK_BIDX_STRING_PROTOTYPE << 16) + DUK_STRIDX_UC_STRING;
20837 		}
20838 		goto use_proto_bidx;
20839 	}
20840 	case DUK_TAG_OBJECT: {
20841 		duk_push_tval(thr, tv);
20842 		stridx_bidx = 0xffffffffUL;  /* Marker value. */
20843 		goto use_pushed_object;
20844 	}
20845 	case DUK_TAG_BUFFER: {
20846 		stridx_bidx = (DUK_BIDX_UINT8ARRAY_PROTOTYPE << 16) + DUK_STRIDX_UINT8_ARRAY;
20847 		goto use_proto_bidx;
20848 	}
20849 #if defined(DUK_USE_FASTINT)
20850 	case DUK_TAG_FASTINT:
20851 		/* Fall through to generic number case. */
20852 #endif
20853 	default: {
20854 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));  /* number (maybe fastint) */
20855 		stridx_bidx = (DUK_BIDX_NUMBER_PROTOTYPE << 16) + DUK_STRIDX_UC_NUMBER;
20856 		goto use_proto_bidx;
20857 	}
20858 	}
20859 	DUK_ASSERT(0);  /* Never here. */
20860 
20861  use_proto_bidx:
20862 	DUK_ASSERT_BIDX_VALID((stridx_bidx >> 16) & 0xffffUL);
20863 	duk_push_hobject(thr, thr->builtins[(stridx_bidx >> 16) & 0xffffUL]);
20864 	/* Fall through. */
20865 
20866  use_pushed_object:
20867 	/* [ ... "[object" obj ] */
20868 
20869 #if defined(DUK_USE_SYMBOL_BUILTIN)
20870 	/* XXX: better handling with avoid_side_effects == 1; lookup tval
20871 	 * without Proxy or getter side effects, and use it in sanitized
20872 	 * form if it's a string.
20873 	 */
20874 	if (!avoid_side_effects) {
20875 		/* XXX: The problem with using the prototype object as the
20876 		 * lookup base is that if @@toStringTag is a getter, its
20877 		 * 'this' binding must be the ToObject() coerced input value,
20878 		 * not the prototype object of the type.
20879 		 */
20880 		(void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG);
20881 		if (duk_is_string_notsymbol(thr, -1)) {
20882 			duk_remove_m2(thr);
20883 			goto finish;
20884 		}
20885 		duk_pop_unsafe(thr);
20886 	}
20887 #endif
20888 
20889 	if (stridx_bidx == 0xffffffffUL) {
20890 		duk_hobject *h_obj;
20891 		duk_small_uint_t classnum;
20892 
20893 		h_obj = duk_known_hobject(thr, -1);
20894 		DUK_ASSERT(h_obj != NULL);
20895 		classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
20896 		stridx_bidx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum);
20897 	} else {
20898 		/* stridx_bidx already has the desired fallback stridx. */
20899 		;
20900 	}
20901 	duk_pop_unsafe(thr);
20902 	/* Fall through. */
20903 
20904  use_stridx:
20905 	/* [ ... "[object" ] */
20906 	duk_push_hstring_stridx(thr, stridx_bidx & 0xffffUL);
20907 
20908  finish:
20909 	/* [ ... "[object" tag ] */
20910 	duk_push_literal(thr, "]");
20911 	duk_concat(thr, 3);  /* [ ... "[object" tag "]" ] -> [ ... res ] */
20912 }
20913 #endif  /* 0 */
20914 
duk_push_class_string_tval(duk_hthread * thr,duk_tval * tv,duk_bool_t avoid_side_effects)20915 DUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects) {
20916 	duk_hobject *h_obj;
20917 	duk_small_uint_t classnum;
20918 	duk_small_uint_t stridx;
20919 	duk_tval tv_tmp;
20920 
20921 	DUK_ASSERT_API_ENTRY(thr);
20922 	DUK_ASSERT(tv != NULL);
20923 
20924 	/* Stabilize 'tv', duk_push_literal() may trigger side effects. */
20925 	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
20926 	tv = &tv_tmp;
20927 
20928 	/* Conceptually for any non-undefined/null value we should do a
20929 	 * ToObject() coercion and look up @@toStringTag (from the object
20930 	 * prototype) to see if a custom result should be used.  We'd like to
20931 	 * avoid the actual conversion, but even for primitive types the
20932 	 * prototype may have @@toStringTag.  What's worse, the @@toStringTag
20933 	 * property may be a getter that must get the object coerced value
20934 	 * (not the prototype) as its 'this' binding.
20935 	 *
20936 	 * For now, do an actual object coercion.  This could be avoided by
20937 	 * doing a side effect free lookup to see if a getter would be invoked.
20938 	 * If not, the value can be read directly and the object coercion could
20939 	 * be avoided.  This may not be worth it in practice, because
20940 	 * Object.prototype.toString() is usually not performance critical.
20941 	 */
20942 
20943 	duk_push_literal(thr, "[object ");  /* -> [ ... "[object" ] */
20944 
20945 	switch (DUK_TVAL_GET_TAG(tv)) {
20946 	case DUK_TAG_UNUSED:  /* Treat like 'undefined', shouldn't happen. */
20947 	case DUK_TAG_UNDEFINED: {
20948 		duk_push_hstring_stridx(thr, DUK_STRIDX_UC_UNDEFINED);
20949 		goto finish;
20950 	}
20951 	case DUK_TAG_NULL: {
20952 		duk_push_hstring_stridx(thr, DUK_STRIDX_UC_NULL);
20953 		goto finish;
20954 	}
20955 	}
20956 
20957 	duk_push_tval(thr, tv);
20958 	tv = NULL;  /* Invalidated by ToObject(). */
20959 	duk_to_object(thr, -1);
20960 
20961 	/* [ ... "[object" obj ] */
20962 
20963 #if defined(DUK_USE_SYMBOL_BUILTIN)
20964 	/* XXX: better handling with avoid_side_effects == 1; lookup tval
20965 	 * without Proxy or getter side effects, and use it in sanitized
20966 	 * form if it's a string.
20967 	 */
20968 	if (!avoid_side_effects) {
20969 		(void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG);
20970 		if (duk_is_string_notsymbol(thr, -1)) {
20971 			duk_remove_m2(thr);
20972 			goto finish;
20973 		}
20974 		duk_pop_unsafe(thr);
20975 	}
20976 #else
20977 	DUK_UNREF(avoid_side_effects);
20978 #endif
20979 
20980 	h_obj = duk_known_hobject(thr, -1);
20981 	DUK_ASSERT(h_obj != NULL);
20982 	classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
20983 	stridx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum);
20984 	duk_pop_unsafe(thr);
20985 	duk_push_hstring_stridx(thr, stridx);
20986 
20987  finish:
20988 	/* [ ... "[object" tag ] */
20989 	duk_push_literal(thr, "]");
20990 	duk_concat(thr, 3);  /* [ ... "[object" tag "]" ] -> [ ... res ] */
20991 }
20992 
20993 /* 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)20994 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) {
20995 	duk_tval *tv;
20996 	duk_tval tv_tmp;
20997 	duk_double_t d, dmin, dmax;
20998 	duk_int_t res;
20999 	duk_bool_t clamped = 0;
21000 
21001 	DUK_ASSERT_API_ENTRY(thr);
21002 
21003 	tv = duk_require_tval(thr, idx);
21004 	DUK_ASSERT(tv != NULL);
21005 	d = duk_js_tointeger(thr, tv);  /* E5 Section 9.4, ToInteger() */
21006 
21007 	dmin = (duk_double_t) minval;
21008 	dmax = (duk_double_t) maxval;
21009 
21010 	if (d < dmin) {
21011 		clamped = 1;
21012 		res = minval;
21013 		d = dmin;
21014 	} else if (d > dmax) {
21015 		clamped = 1;
21016 		res = maxval;
21017 		d = dmax;
21018 	} else {
21019 		res = (duk_int_t) d;
21020 	}
21021 	DUK_UNREF(d);  /* SCANBUILD: with suitable dmin/dmax limits 'd' is unused */
21022 	/* 'd' and 'res' agree here */
21023 
21024 	/* Relookup in case duk_js_tointeger() ends up e.g. coercing an object. */
21025 	tv = duk_get_tval(thr, idx);
21026 	DUK_ASSERT(tv != NULL);  /* not popped by side effect */
21027 	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
21028 #if defined(DUK_USE_FASTINT)
21029 #if (DUK_INT_MAX <= 0x7fffffffL)
21030 	DUK_TVAL_SET_I32(tv, res);
21031 #else
21032 	/* Clamping needed if duk_int_t is 64 bits. */
21033 	if (res >= DUK_FASTINT_MIN && res <= DUK_FASTINT_MAX) {
21034 		DUK_TVAL_SET_FASTINT(tv, res);
21035 	} else {
21036 		DUK_TVAL_SET_NUMBER(tv, d);
21037 	}
21038 #endif
21039 #else
21040 	DUK_TVAL_SET_NUMBER(tv, d);  /* no need to incref */
21041 #endif
21042 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
21043 
21044 	if (out_clamped) {
21045 		*out_clamped = clamped;
21046 	} else {
21047 		/* coerced value is updated to value stack even when RangeError thrown */
21048 		if (clamped) {
21049 			DUK_ERROR_RANGE(thr, DUK_STR_NUMBER_OUTSIDE_RANGE);
21050 			DUK_WO_NORETURN(return 0;);
21051 		}
21052 	}
21053 
21054 	return res;
21055 }
21056 
duk_to_int_clamped(duk_hthread * thr,duk_idx_t idx,duk_idx_t minval,duk_idx_t maxval)21057 DUK_INTERNAL duk_int_t duk_to_int_clamped(duk_hthread *thr, duk_idx_t idx, duk_idx_t minval, duk_idx_t maxval) {
21058 	duk_bool_t dummy;
21059 
21060 	DUK_ASSERT_API_ENTRY(thr);
21061 
21062 	return duk_to_int_clamped_raw(thr, idx, minval, maxval, &dummy);
21063 }
21064 
duk_to_int_check_range(duk_hthread * thr,duk_idx_t idx,duk_int_t minval,duk_int_t maxval)21065 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) {
21066 	DUK_ASSERT_API_ENTRY(thr);
21067 	return duk_to_int_clamped_raw(thr, idx, minval, maxval, NULL);  /* out_clamped==NULL -> RangeError if outside range */
21068 }
21069 
duk_to_string(duk_hthread * thr,duk_idx_t idx)21070 DUK_EXTERNAL const char *duk_to_string(duk_hthread *thr, duk_idx_t idx) {
21071 	duk_tval *tv;
21072 
21073 	DUK_ASSERT_API_ENTRY(thr);
21074 
21075 	idx = duk_require_normalize_index(thr, idx);
21076 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
21077 	DUK_ASSERT(tv != NULL);
21078 
21079 	switch (DUK_TVAL_GET_TAG(tv)) {
21080 	case DUK_TAG_UNDEFINED: {
21081 		duk_push_hstring_stridx(thr, DUK_STRIDX_LC_UNDEFINED);
21082 		break;
21083 	}
21084 	case DUK_TAG_NULL: {
21085 		duk_push_hstring_stridx(thr, DUK_STRIDX_LC_NULL);
21086 		break;
21087 	}
21088 	case DUK_TAG_BOOLEAN: {
21089 		if (DUK_TVAL_GET_BOOLEAN(tv)) {
21090 			duk_push_hstring_stridx(thr, DUK_STRIDX_TRUE);
21091 		} else {
21092 			duk_push_hstring_stridx(thr, DUK_STRIDX_FALSE);
21093 		}
21094 		break;
21095 	}
21096 	case DUK_TAG_STRING: {
21097 		/* Nop for actual strings, TypeError for Symbols.
21098 		 * Because various internals rely on ToString() coercion of
21099 		 * internal strings, -allow- (NOP) string coercion for hidden
21100 		 * symbols.
21101 		 */
21102 #if 1
21103 		duk_hstring *h;
21104 		h = DUK_TVAL_GET_STRING(tv);
21105 		DUK_ASSERT(h != NULL);
21106 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
21107 			DUK_ERROR_TYPE(thr, DUK_STR_CANNOT_STRING_COERCE_SYMBOL);
21108 			DUK_WO_NORETURN(goto skip_replace;);
21109 		} else {
21110 			goto skip_replace;
21111 		}
21112 #else
21113 		goto skip_replace;
21114 #endif
21115 		break;
21116 	}
21117 	case DUK_TAG_BUFFER: /* Go through Uint8Array.prototype.toString() for coercion. */
21118 	case DUK_TAG_OBJECT: {
21119 		/* Plain buffers: go through ArrayBuffer.prototype.toString()
21120 		 * for coercion.
21121 		 *
21122 		 * Symbol objects: duk_to_primitive() results in a plain symbol
21123 		 * value, and duk_to_string() then causes a TypeError.
21124 		 */
21125 		duk_to_primitive(thr, idx, DUK_HINT_STRING);
21126 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* ToPrimitive() must guarantee */
21127 		DUK_ASSERT(!duk_is_object(thr, idx));
21128 		return duk_to_string(thr, idx);  /* Note: recursive call */
21129 	}
21130 	case DUK_TAG_POINTER: {
21131 		void *ptr = DUK_TVAL_GET_POINTER(tv);
21132 		if (ptr != NULL) {
21133 			duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) ptr);
21134 		} else {
21135 			/* Represent a null pointer as 'null' to be consistent with
21136 			 * the JX format variant.  Native '%p' format for a NULL
21137 			 * pointer may be e.g. '(nil)'.
21138 			 */
21139 			duk_push_hstring_stridx(thr, DUK_STRIDX_LC_NULL);
21140 		}
21141 		break;
21142 	}
21143 	case DUK_TAG_LIGHTFUNC: {
21144 		/* Should match Function.prototype.toString() */
21145 		duk_push_lightfunc_tostring(thr, tv);
21146 		break;
21147 	}
21148 #if defined(DUK_USE_FASTINT)
21149 	case DUK_TAG_FASTINT:
21150 #endif
21151 	default: {
21152 		/* number */
21153 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21154 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21155 		duk_push_tval(thr, tv);
21156 		duk_numconv_stringify(thr,
21157 		                      10 /*radix*/,
21158 		                      0 /*precision:shortest*/,
21159 		                      0 /*force_exponential*/);
21160 		break;
21161 	}
21162 	}
21163 
21164 	duk_replace(thr, idx);
21165 
21166  skip_replace:
21167 	DUK_ASSERT(duk_is_string(thr, idx));
21168 	return duk_require_string(thr, idx);
21169 }
21170 
duk_to_hstring(duk_hthread * thr,duk_idx_t idx)21171 DUK_INTERNAL duk_hstring *duk_to_hstring(duk_hthread *thr, duk_idx_t idx) {
21172 	duk_hstring *ret;
21173 
21174 	DUK_ASSERT_API_ENTRY(thr);
21175 
21176 	duk_to_string(thr, idx);
21177 	ret = duk_get_hstring(thr, idx);
21178 	DUK_ASSERT(ret != NULL);
21179 	return ret;
21180 }
21181 
duk_to_hstring_m1(duk_hthread * thr)21182 DUK_INTERNAL duk_hstring *duk_to_hstring_m1(duk_hthread *thr) {
21183 	DUK_ASSERT_API_ENTRY(thr);
21184 	return duk_to_hstring(thr, -1);
21185 }
21186 
duk_to_hstring_acceptsymbol(duk_hthread * thr,duk_idx_t idx)21187 DUK_INTERNAL duk_hstring *duk_to_hstring_acceptsymbol(duk_hthread *thr, duk_idx_t idx) {
21188 	duk_hstring *ret;
21189 
21190 	DUK_ASSERT_API_ENTRY(thr);
21191 
21192 	ret = duk_get_hstring(thr, idx);
21193 	if (DUK_UNLIKELY(ret && DUK_HSTRING_HAS_SYMBOL(ret))) {
21194 		return ret;
21195 	}
21196 	return duk_to_hstring(thr, idx);
21197 }
21198 
21199 /* Convert a plain buffer or any buffer object into a string, using the buffer
21200  * bytes 1:1 in the internal string representation.  For views the active byte
21201  * slice (not element slice interpreted as an initializer) is used.  This is
21202  * necessary in Duktape 2.x because ToString(plainBuffer) no longer creates a
21203  * string with the same bytes as in the buffer but rather (usually)
21204  * '[object ArrayBuffer]'.
21205  */
duk_buffer_to_string(duk_hthread * thr,duk_idx_t idx)21206 DUK_EXTERNAL const char *duk_buffer_to_string(duk_hthread *thr, duk_idx_t idx) {
21207 	void *ptr_src;
21208 	duk_size_t len;
21209 	const char *res;
21210 
21211 	DUK_ASSERT_API_ENTRY(thr);
21212 
21213 	idx = duk_require_normalize_index(thr, idx);
21214 
21215 	ptr_src = duk_require_buffer_data(thr, idx, &len);
21216 	DUK_ASSERT(ptr_src != NULL || len == 0);
21217 
21218 	res = duk_push_lstring(thr, (const char *) ptr_src, len);
21219 	duk_replace(thr, idx);
21220 	return res;
21221 }
21222 
duk_to_buffer_raw(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,duk_uint_t mode)21223 DUK_EXTERNAL void *duk_to_buffer_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, duk_uint_t mode) {
21224 	duk_hbuffer *h_buf;
21225 	const duk_uint8_t *src_data;
21226 	duk_size_t src_size;
21227 	duk_uint8_t *dst_data;
21228 
21229 	DUK_ASSERT_API_ENTRY(thr);
21230 
21231 	idx = duk_require_normalize_index(thr, idx);
21232 
21233 	h_buf = duk_get_hbuffer(thr, idx);
21234 	if (h_buf != NULL) {
21235 		/* Buffer is kept as is, with the fixed/dynamic nature of the
21236 		 * buffer only changed if requested.  An external buffer
21237 		 * is converted into a non-external dynamic buffer in a
21238 		 * duk_to_dynamic_buffer() call.
21239 		 */
21240 		duk_uint_t tmp;
21241 		duk_uint8_t *tmp_ptr;
21242 
21243 		tmp_ptr = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf);
21244 		src_data = (const duk_uint8_t *) tmp_ptr;
21245 		src_size = DUK_HBUFFER_GET_SIZE(h_buf);
21246 
21247 		tmp = (DUK_HBUFFER_HAS_DYNAMIC(h_buf) ? DUK_BUF_MODE_DYNAMIC : DUK_BUF_MODE_FIXED);
21248 		if ((tmp == mode && !DUK_HBUFFER_HAS_EXTERNAL(h_buf)) ||
21249 		    mode == DUK_BUF_MODE_DONTCARE) {
21250 			/* Note: src_data may be NULL if input is a zero-size
21251 			 * dynamic buffer.
21252 			 */
21253 			dst_data = tmp_ptr;
21254 			goto skip_copy;
21255 		}
21256 	} else {
21257 		/* Non-buffer value is first ToString() coerced, then converted
21258 		 * to a buffer (fixed buffer is used unless a dynamic buffer is
21259 		 * explicitly requested).  Symbols are rejected with a TypeError.
21260 		 * XXX: C API could maybe allow symbol-to-buffer coercion?
21261 		 */
21262 		src_data = (const duk_uint8_t *) duk_to_lstring(thr, idx, &src_size);
21263 	}
21264 
21265 	dst_data = (duk_uint8_t *) duk_push_buffer(thr, src_size, (mode == DUK_BUF_MODE_DYNAMIC) /*dynamic*/);
21266 	/* dst_data may be NULL if size is zero. */
21267 	duk_memcpy_unsafe((void *) dst_data, (const void *) src_data, (size_t) src_size);
21268 
21269 	duk_replace(thr, idx);
21270  skip_copy:
21271 
21272 	if (out_size) {
21273 		*out_size = src_size;
21274 	}
21275 	return dst_data;
21276 }
21277 
duk_to_pointer(duk_hthread * thr,duk_idx_t idx)21278 DUK_EXTERNAL void *duk_to_pointer(duk_hthread *thr, duk_idx_t idx) {
21279 	duk_tval *tv;
21280 	void *res;
21281 
21282 	DUK_ASSERT_API_ENTRY(thr);
21283 
21284 	idx = duk_require_normalize_index(thr, idx);
21285 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
21286 	DUK_ASSERT(tv != NULL);
21287 
21288 	switch (DUK_TVAL_GET_TAG(tv)) {
21289 	case DUK_TAG_UNDEFINED:
21290 	case DUK_TAG_NULL:
21291 	case DUK_TAG_BOOLEAN:
21292 		res = NULL;
21293 		break;
21294 	case DUK_TAG_POINTER:
21295 		res = DUK_TVAL_GET_POINTER(tv);
21296 		break;
21297 	case DUK_TAG_STRING:
21298 	case DUK_TAG_OBJECT:
21299 	case DUK_TAG_BUFFER:
21300 		/* Heap allocated: return heap pointer which is NOT useful
21301 		 * for the caller, except for debugging.
21302 		 */
21303 		res = (void *) DUK_TVAL_GET_HEAPHDR(tv);
21304 		break;
21305 	case DUK_TAG_LIGHTFUNC:
21306 		/* Function pointers do not always cast correctly to void *
21307 		 * (depends on memory and segmentation model for instance),
21308 		 * so they coerce to NULL.
21309 		 */
21310 		res = NULL;
21311 		break;
21312 #if defined(DUK_USE_FASTINT)
21313 	case DUK_TAG_FASTINT:
21314 #endif
21315 	default:
21316 		/* number */
21317 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21318 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21319 		res = NULL;
21320 		break;
21321 	}
21322 
21323 	duk_push_pointer(thr, res);
21324 	duk_replace(thr, idx);
21325 	return res;
21326 }
21327 
duk__push_func_from_lightfunc(duk_hthread * thr,duk_c_function func,duk_small_uint_t lf_flags)21328 DUK_LOCAL void duk__push_func_from_lightfunc(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags) {
21329 	duk_idx_t nargs;
21330 	duk_uint_t flags = 0;   /* shared flags for a subset of types */
21331 	duk_small_uint_t lf_len;
21332 	duk_hnatfunc *nf;
21333 
21334 	nargs = (duk_idx_t) DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
21335 	if (nargs == DUK_LFUNC_NARGS_VARARGS) {
21336 		nargs = (duk_idx_t) DUK_VARARGS;
21337 	}
21338 
21339 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21340 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
21341 	        DUK_HOBJECT_FLAG_CALLABLE |
21342 	        DUK_HOBJECT_FLAG_FASTREFS |
21343 	        DUK_HOBJECT_FLAG_NATFUNC |
21344 	        DUK_HOBJECT_FLAG_NEWENV |
21345 	        DUK_HOBJECT_FLAG_STRICT |
21346 	        DUK_HOBJECT_FLAG_NOTAIL |
21347 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
21348 	(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE);
21349 
21350 	lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
21351 	if ((duk_idx_t) lf_len != nargs) {
21352 		/* Explicit length is only needed if it differs from 'nargs'. */
21353 		duk_push_int(thr, (duk_int_t) lf_len);
21354 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);
21355 	}
21356 
21357 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
21358 	duk_push_lightfunc_name_raw(thr, func, lf_flags);
21359 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
21360 #endif
21361 
21362 	nf = duk_known_hnatfunc(thr, -1);
21363 	nf->magic = (duk_int16_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
21364 }
21365 
duk_to_object(duk_hthread * thr,duk_idx_t idx)21366 DUK_EXTERNAL void duk_to_object(duk_hthread *thr, duk_idx_t idx) {
21367 	duk_tval *tv;
21368 	duk_uint_t flags = 0;   /* shared flags for a subset of types */
21369 	duk_small_int_t proto = 0;
21370 
21371 	DUK_ASSERT_API_ENTRY(thr);
21372 
21373 	idx = duk_require_normalize_index(thr, idx);
21374 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
21375 	DUK_ASSERT(tv != NULL);
21376 
21377 	switch (DUK_TVAL_GET_TAG(tv)) {
21378 #if !defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21379 	case DUK_TAG_BUFFER:  /* With no bufferobject support, don't object coerce. */
21380 #endif
21381 	case DUK_TAG_UNDEFINED:
21382 	case DUK_TAG_NULL: {
21383 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);
21384 		DUK_WO_NORETURN(return;);
21385 		break;
21386 	}
21387 	case DUK_TAG_BOOLEAN: {
21388 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21389 		        DUK_HOBJECT_FLAG_FASTREFS |
21390 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BOOLEAN);
21391 		proto = DUK_BIDX_BOOLEAN_PROTOTYPE;
21392 		goto create_object;
21393 	}
21394 	case DUK_TAG_STRING: {
21395 		duk_hstring *h;
21396 		h = DUK_TVAL_GET_STRING(tv);
21397 		DUK_ASSERT(h != NULL);
21398 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
21399 			flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21400 			        DUK_HOBJECT_FLAG_FASTREFS |
21401 			        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_SYMBOL);
21402 			proto = DUK_BIDX_SYMBOL_PROTOTYPE;
21403 		} else {
21404 			flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21405 			        DUK_HOBJECT_FLAG_FASTREFS |
21406 			        DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
21407 			        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
21408 			proto = DUK_BIDX_STRING_PROTOTYPE;
21409 		}
21410 		goto create_object;
21411 	}
21412 	case DUK_TAG_OBJECT: {
21413 		/* nop */
21414 		break;
21415 	}
21416 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21417 	case DUK_TAG_BUFFER: {
21418 		/* A plain buffer object coerces to a full ArrayBuffer which
21419 		 * is not fully transparent behavior (ToObject() should be a
21420 		 * nop for an object).  This behavior matches lightfuncs which
21421 		 * also coerce to an equivalent Function object.  There are
21422 		 * also downsides to defining ToObject(plainBuffer) as a no-op;
21423 		 * for example duk_to_hobject() could result in a NULL pointer.
21424 		 */
21425 		duk_hbuffer *h_buf;
21426 
21427 		h_buf = DUK_TVAL_GET_BUFFER(tv);
21428 		DUK_ASSERT(h_buf != NULL);
21429 		duk_hbufobj_push_uint8array_from_plain(thr, h_buf);
21430 		goto replace_value;
21431 	}
21432 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21433 	case DUK_TAG_POINTER: {
21434 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21435 		        DUK_HOBJECT_FLAG_FASTREFS |
21436 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER);
21437 		proto = DUK_BIDX_POINTER_PROTOTYPE;
21438 		goto create_object;
21439 	}
21440 	case DUK_TAG_LIGHTFUNC: {
21441 		/* Lightfunc coerces to a Function instance with concrete
21442 		 * properties.  Since 'length' is virtual for Duktape/C
21443 		 * functions, don't need to define that.  The result is made
21444 		 * extensible to mimic what happens to strings in object
21445 		 * coercion:
21446 		 *
21447 		 *   > Object.isExtensible(Object('foo'))
21448 		 *   true
21449 		 */
21450 		duk_small_uint_t lf_flags;
21451 		duk_c_function func;
21452 
21453 		DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
21454 		duk__push_func_from_lightfunc(thr, func, lf_flags);
21455 		goto replace_value;
21456 	}
21457 #if defined(DUK_USE_FASTINT)
21458 	case DUK_TAG_FASTINT:
21459 #endif
21460 	default: {
21461 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21462 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21463 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21464 		        DUK_HOBJECT_FLAG_FASTREFS |
21465 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_NUMBER);
21466 		proto = DUK_BIDX_NUMBER_PROTOTYPE;
21467 		goto create_object;
21468 	}
21469 	}
21470 	DUK_ASSERT(duk_is_object(thr, idx));
21471 	return;
21472 
21473  create_object:
21474 	(void) duk_push_object_helper(thr, flags, proto);
21475 
21476 	/* Note: Boolean prototype's internal value property is not writable,
21477 	 * but duk_xdef_prop_stridx() disregards the write protection.  Boolean
21478 	 * instances are immutable.
21479 	 *
21480 	 * String and buffer special behaviors are already enabled which is not
21481 	 * ideal, but a write to the internal value is not affected by them.
21482 	 */
21483 	duk_dup(thr, idx);
21484 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
21485 
21486  replace_value:
21487 	duk_replace(thr, idx);
21488 	DUK_ASSERT(duk_is_object(thr, idx));
21489 }
21490 
duk_to_hobject(duk_hthread * thr,duk_idx_t idx)21491 DUK_INTERNAL duk_hobject *duk_to_hobject(duk_hthread *thr, duk_idx_t idx) {
21492 	duk_hobject *ret;
21493 
21494 	DUK_ASSERT_API_ENTRY(thr);
21495 
21496 	duk_to_object(thr, idx);
21497 	ret = duk_known_hobject(thr, idx);
21498 	return ret;
21499 }
21500 
21501 /*
21502  *  Type checking
21503  */
21504 
duk__tag_check(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t tag)21505 DUK_LOCAL duk_bool_t duk__tag_check(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t tag) {
21506 	duk_tval *tv;
21507 
21508 	tv = duk_get_tval_or_unused(thr, idx);
21509 	DUK_ASSERT(tv != NULL);
21510 	return (DUK_TVAL_GET_TAG(tv) == tag);
21511 }
21512 
duk__obj_flag_any_default_false(duk_hthread * thr,duk_idx_t idx,duk_uint_t flag_mask)21513 DUK_LOCAL duk_bool_t duk__obj_flag_any_default_false(duk_hthread *thr, duk_idx_t idx, duk_uint_t flag_mask) {
21514 	duk_hobject *obj;
21515 
21516 	DUK_ASSERT_API_ENTRY(thr);
21517 
21518 	obj = duk_get_hobject(thr, idx);
21519 	if (obj) {
21520 		return (DUK_HEAPHDR_CHECK_FLAG_BITS((duk_heaphdr *) obj, flag_mask) ? 1 : 0);
21521 	}
21522 	return 0;
21523 }
21524 
duk_get_type_tval(duk_tval * tv)21525 DUK_INTERNAL duk_int_t duk_get_type_tval(duk_tval *tv) {
21526 	DUK_ASSERT(tv != NULL);
21527 
21528 #if defined(DUK_USE_PACKED_TVAL)
21529 	switch (DUK_TVAL_GET_TAG(tv)) {
21530 	case DUK_TAG_UNUSED:
21531 		return DUK_TYPE_NONE;
21532 	case DUK_TAG_UNDEFINED:
21533 		return DUK_TYPE_UNDEFINED;
21534 	case DUK_TAG_NULL:
21535 		return DUK_TYPE_NULL;
21536 	case DUK_TAG_BOOLEAN:
21537 		return DUK_TYPE_BOOLEAN;
21538 	case DUK_TAG_STRING:
21539 		return DUK_TYPE_STRING;
21540 	case DUK_TAG_OBJECT:
21541 		return DUK_TYPE_OBJECT;
21542 	case DUK_TAG_BUFFER:
21543 		return DUK_TYPE_BUFFER;
21544 	case DUK_TAG_POINTER:
21545 		return DUK_TYPE_POINTER;
21546 	case DUK_TAG_LIGHTFUNC:
21547 		return DUK_TYPE_LIGHTFUNC;
21548 #if defined(DUK_USE_FASTINT)
21549 	case DUK_TAG_FASTINT:
21550 #endif
21551 	default:
21552 		/* Note: number has no explicit tag (in 8-byte representation) */
21553 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21554 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21555 		return DUK_TYPE_NUMBER;
21556 	}
21557 #else  /* DUK_USE_PACKED_TVAL */
21558 	DUK_ASSERT(DUK_TVAL_IS_VALID_TAG(tv));
21559 	DUK_ASSERT(sizeof(duk__type_from_tag) / sizeof(duk_uint_t) == DUK_TAG_MAX - DUK_TAG_MIN + 1);
21560 	return (duk_int_t) duk__type_from_tag[DUK_TVAL_GET_TAG(tv) - DUK_TAG_MIN];
21561 #endif  /* DUK_USE_PACKED_TVAL */
21562 }
21563 
duk_get_type(duk_hthread * thr,duk_idx_t idx)21564 DUK_EXTERNAL duk_int_t duk_get_type(duk_hthread *thr, duk_idx_t idx) {
21565 	duk_tval *tv;
21566 
21567 	DUK_ASSERT_API_ENTRY(thr);
21568 
21569 	tv = duk_get_tval_or_unused(thr, idx);
21570 	DUK_ASSERT(tv != NULL);
21571 
21572 	return duk_get_type_tval(tv);
21573 }
21574 
21575 #if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
21576 DUK_LOCAL const char * const duk__type_names[] = {
21577 	"none",
21578 	"undefined",
21579 	"null",
21580 	"boolean",
21581 	"number",
21582 	"string",
21583 	"object",
21584 	"buffer",
21585 	"pointer",
21586 	"lightfunc"
21587 };
21588 
duk_get_type_name(duk_hthread * thr,duk_idx_t idx)21589 DUK_INTERNAL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx) {
21590 	duk_int_t type_tag;
21591 
21592 	DUK_ASSERT_API_ENTRY(thr);
21593 
21594 	type_tag = duk_get_type(thr, idx);
21595 	DUK_ASSERT(type_tag >= DUK_TYPE_MIN && type_tag <= DUK_TYPE_MAX);
21596 	DUK_ASSERT(DUK_TYPE_MIN == 0 && sizeof(duk__type_names) / sizeof(const char *) == DUK_TYPE_MAX + 1);
21597 
21598 	return duk__type_names[type_tag];
21599 }
21600 #endif  /* DUK_USE_VERBOSE_ERRORS && DUK_USE_PARANOID_ERRORS */
21601 
duk_get_class_number(duk_hthread * thr,duk_idx_t idx)21602 DUK_INTERNAL duk_small_uint_t duk_get_class_number(duk_hthread *thr, duk_idx_t idx) {
21603 	duk_tval *tv;
21604 	duk_hobject *obj;
21605 
21606 	DUK_ASSERT_API_ENTRY(thr);
21607 
21608 	tv = duk_get_tval_or_unused(thr, idx);
21609 	DUK_ASSERT(tv != NULL);
21610 
21611 	switch (DUK_TVAL_GET_TAG(tv)) {
21612 	case DUK_TAG_OBJECT:
21613 		obj = DUK_TVAL_GET_OBJECT(tv);
21614 		DUK_ASSERT(obj != NULL);
21615 		return DUK_HOBJECT_GET_CLASS_NUMBER(obj);
21616 	case DUK_TAG_BUFFER:
21617 		/* Buffers behave like Uint8Array objects. */
21618 		return DUK_HOBJECT_CLASS_UINT8ARRAY;
21619 	case DUK_TAG_LIGHTFUNC:
21620 		/* Lightfuncs behave like Function objects. */
21621 		return DUK_HOBJECT_CLASS_FUNCTION;
21622 	default:
21623 		/* Primitive or UNUSED, no class number. */
21624 		return DUK_HOBJECT_CLASS_NONE;
21625 	}
21626 }
21627 
duk_check_type(duk_hthread * thr,duk_idx_t idx,duk_int_t type)21628 DUK_EXTERNAL duk_bool_t duk_check_type(duk_hthread *thr, duk_idx_t idx, duk_int_t type) {
21629 	DUK_ASSERT_API_ENTRY(thr);
21630 
21631 	return (duk_get_type(thr, idx) == type) ? 1 : 0;
21632 }
21633 
duk_get_type_mask_tval(duk_tval * tv)21634 DUK_INTERNAL duk_uint_t duk_get_type_mask_tval(duk_tval *tv) {
21635 	DUK_ASSERT(tv != NULL);
21636 
21637 #if defined(DUK_USE_PACKED_TVAL)
21638 	switch (DUK_TVAL_GET_TAG(tv)) {
21639 	case DUK_TAG_UNUSED:
21640 		return DUK_TYPE_MASK_NONE;
21641 	case DUK_TAG_UNDEFINED:
21642 		return DUK_TYPE_MASK_UNDEFINED;
21643 	case DUK_TAG_NULL:
21644 		return DUK_TYPE_MASK_NULL;
21645 	case DUK_TAG_BOOLEAN:
21646 		return DUK_TYPE_MASK_BOOLEAN;
21647 	case DUK_TAG_STRING:
21648 		return DUK_TYPE_MASK_STRING;
21649 	case DUK_TAG_OBJECT:
21650 		return DUK_TYPE_MASK_OBJECT;
21651 	case DUK_TAG_BUFFER:
21652 		return DUK_TYPE_MASK_BUFFER;
21653 	case DUK_TAG_POINTER:
21654 		return DUK_TYPE_MASK_POINTER;
21655 	case DUK_TAG_LIGHTFUNC:
21656 		return DUK_TYPE_MASK_LIGHTFUNC;
21657 #if defined(DUK_USE_FASTINT)
21658 	case DUK_TAG_FASTINT:
21659 #endif
21660 	default:
21661 		/* Note: number has no explicit tag (in 8-byte representation) */
21662 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21663 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21664 		return DUK_TYPE_MASK_NUMBER;
21665 	}
21666 #else  /* DUK_USE_PACKED_TVAL */
21667 	DUK_ASSERT(DUK_TVAL_IS_VALID_TAG(tv));
21668 	DUK_ASSERT(sizeof(duk__type_mask_from_tag) / sizeof(duk_uint_t) == DUK_TAG_MAX - DUK_TAG_MIN + 1);
21669 	return duk__type_mask_from_tag[DUK_TVAL_GET_TAG(tv) - DUK_TAG_MIN];
21670 #endif  /* DUK_USE_PACKED_TVAL */
21671 }
21672 
duk_get_type_mask(duk_hthread * thr,duk_idx_t idx)21673 DUK_EXTERNAL duk_uint_t duk_get_type_mask(duk_hthread *thr, duk_idx_t idx) {
21674 	duk_tval *tv;
21675 
21676 	DUK_ASSERT_API_ENTRY(thr);
21677 
21678 	tv = duk_get_tval_or_unused(thr, idx);
21679 	DUK_ASSERT(tv != NULL);
21680 
21681 	return duk_get_type_mask_tval(tv);
21682 }
21683 
duk_check_type_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t mask)21684 DUK_EXTERNAL duk_bool_t duk_check_type_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t mask) {
21685 	DUK_ASSERT_API_ENTRY(thr);
21686 
21687 	if (DUK_LIKELY((duk_get_type_mask(thr, idx) & mask) != 0U)) {
21688 		return 1;
21689 	}
21690 	if (mask & DUK_TYPE_MASK_THROW) {
21691 		DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
21692 		DUK_WO_NORETURN(return 0;);
21693 	}
21694 	return 0;
21695 }
21696 
duk_is_undefined(duk_hthread * thr,duk_idx_t idx)21697 DUK_EXTERNAL duk_bool_t duk_is_undefined(duk_hthread *thr, duk_idx_t idx) {
21698 	DUK_ASSERT_API_ENTRY(thr);
21699 	return duk__tag_check(thr, idx, DUK_TAG_UNDEFINED);
21700 }
21701 
duk_is_null(duk_hthread * thr,duk_idx_t idx)21702 DUK_EXTERNAL duk_bool_t duk_is_null(duk_hthread *thr, duk_idx_t idx) {
21703 	DUK_ASSERT_API_ENTRY(thr);
21704 	return duk__tag_check(thr, idx, DUK_TAG_NULL);
21705 }
21706 
duk_is_boolean(duk_hthread * thr,duk_idx_t idx)21707 DUK_EXTERNAL duk_bool_t duk_is_boolean(duk_hthread *thr, duk_idx_t idx) {
21708 	DUK_ASSERT_API_ENTRY(thr);
21709 	return duk__tag_check(thr, idx, DUK_TAG_BOOLEAN);
21710 }
21711 
duk_is_number(duk_hthread * thr,duk_idx_t idx)21712 DUK_EXTERNAL duk_bool_t duk_is_number(duk_hthread *thr, duk_idx_t idx) {
21713 	duk_tval *tv;
21714 
21715 	DUK_ASSERT_API_ENTRY(thr);
21716 
21717 	/*
21718 	 *  Number is special because it doesn't have a specific
21719 	 *  tag in the 8-byte representation.
21720 	 */
21721 
21722 	/* XXX: shorter version for unpacked representation? */
21723 
21724 	tv = duk_get_tval_or_unused(thr, idx);
21725 	DUK_ASSERT(tv != NULL);
21726 	return DUK_TVAL_IS_NUMBER(tv);
21727 }
21728 
duk_is_nan(duk_hthread * thr,duk_idx_t idx)21729 DUK_EXTERNAL duk_bool_t duk_is_nan(duk_hthread *thr, duk_idx_t idx) {
21730 	/* XXX: This will now return false for non-numbers, even though they would
21731 	 * coerce to NaN (as a general rule).  In particular, duk_get_number()
21732 	 * returns a NaN for non-numbers, so should this function also return
21733 	 * true for non-numbers?
21734 	 */
21735 
21736 	duk_tval *tv;
21737 
21738 	DUK_ASSERT_API_ENTRY(thr);
21739 
21740 	tv = duk_get_tval_or_unused(thr, idx);
21741 	DUK_ASSERT(tv != NULL);
21742 
21743 	/* XXX: for packed duk_tval an explicit "is number" check is unnecessary */
21744 	if (!DUK_TVAL_IS_NUMBER(tv)) {
21745 		return 0;
21746 	}
21747 	return (duk_bool_t) DUK_ISNAN(DUK_TVAL_GET_NUMBER(tv));
21748 }
21749 
duk_is_string(duk_hthread * thr,duk_idx_t idx)21750 DUK_EXTERNAL duk_bool_t duk_is_string(duk_hthread *thr, duk_idx_t idx) {
21751 	DUK_ASSERT_API_ENTRY(thr);
21752 	return duk__tag_check(thr, idx, DUK_TAG_STRING);
21753 }
21754 
duk_is_string_notsymbol(duk_hthread * thr,duk_idx_t idx)21755 DUK_INTERNAL duk_bool_t duk_is_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {
21756 	DUK_ASSERT_API_ENTRY(thr);
21757 	return duk_get_hstring_notsymbol(thr, idx) != NULL;
21758 }
21759 
duk_is_object(duk_hthread * thr,duk_idx_t idx)21760 DUK_EXTERNAL duk_bool_t duk_is_object(duk_hthread *thr, duk_idx_t idx) {
21761 	DUK_ASSERT_API_ENTRY(thr);
21762 	return duk__tag_check(thr, idx, DUK_TAG_OBJECT);
21763 }
21764 
duk_is_buffer(duk_hthread * thr,duk_idx_t idx)21765 DUK_EXTERNAL duk_bool_t duk_is_buffer(duk_hthread *thr, duk_idx_t idx) {
21766 	DUK_ASSERT_API_ENTRY(thr);
21767 	return duk__tag_check(thr, idx, DUK_TAG_BUFFER);
21768 }
21769 
21770 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_is_buffer_data(duk_hthread * thr,duk_idx_t idx)21771 DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_hthread *thr, duk_idx_t idx) {
21772 	duk_tval *tv;
21773 
21774 	DUK_ASSERT_API_ENTRY(thr);
21775 
21776 	tv = duk_get_tval_or_unused(thr, idx);
21777 	DUK_ASSERT(tv != NULL);
21778 	if (DUK_TVAL_IS_BUFFER(tv)) {
21779 		return 1;
21780 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
21781 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
21782 		DUK_ASSERT(h != NULL);
21783 		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
21784 			return 1;
21785 		}
21786 	}
21787 	return 0;
21788 }
21789 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_is_buffer_data(duk_hthread * thr,duk_idx_t idx)21790 DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_hthread *thr, duk_idx_t idx) {
21791 	DUK_ASSERT_API_ENTRY(thr);
21792 
21793 	return duk_is_buffer(thr, idx);
21794 }
21795 
21796 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21797 
duk_is_pointer(duk_hthread * thr,duk_idx_t idx)21798 DUK_EXTERNAL duk_bool_t duk_is_pointer(duk_hthread *thr, duk_idx_t idx) {
21799 	DUK_ASSERT_API_ENTRY(thr);
21800 	return duk__tag_check(thr, idx, DUK_TAG_POINTER);
21801 }
21802 
duk_is_lightfunc(duk_hthread * thr,duk_idx_t idx)21803 DUK_EXTERNAL duk_bool_t duk_is_lightfunc(duk_hthread *thr, duk_idx_t idx) {
21804 	DUK_ASSERT_API_ENTRY(thr);
21805 	return duk__tag_check(thr, idx, DUK_TAG_LIGHTFUNC);
21806 }
21807 
duk_is_symbol(duk_hthread * thr,duk_idx_t idx)21808 DUK_EXTERNAL duk_bool_t duk_is_symbol(duk_hthread *thr, duk_idx_t idx) {
21809 	duk_hstring *h;
21810 
21811 	DUK_ASSERT_API_ENTRY(thr);
21812 	h = duk_get_hstring(thr, idx);
21813 	/* Use DUK_LIKELY() here because caller may be more likely to type
21814 	 * check an expected symbol than not.
21815 	 */
21816 	if (DUK_LIKELY(h != NULL && DUK_HSTRING_HAS_SYMBOL(h))) {
21817 		return 1;
21818 	}
21819 	return 0;
21820 }
21821 
duk_is_array(duk_hthread * thr,duk_idx_t idx)21822 DUK_EXTERNAL duk_bool_t duk_is_array(duk_hthread *thr, duk_idx_t idx) {
21823 	duk_hobject *obj;
21824 
21825 	DUK_ASSERT_API_ENTRY(thr);
21826 
21827 	obj = duk_get_hobject(thr, idx);
21828 	if (obj) {
21829 		return (DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_ARRAY ? 1 : 0);
21830 	}
21831 	return 0;
21832 }
21833 
duk_is_function(duk_hthread * thr,duk_idx_t idx)21834 DUK_EXTERNAL duk_bool_t duk_is_function(duk_hthread *thr, duk_idx_t idx) {
21835 	duk_tval *tv;
21836 
21837 	DUK_ASSERT_API_ENTRY(thr);
21838 
21839 	tv = duk_get_tval_or_unused(thr, idx);
21840 	if (DUK_TVAL_IS_OBJECT(tv)) {
21841 		duk_hobject *h;
21842 		h = DUK_TVAL_GET_OBJECT(tv);
21843 		DUK_ASSERT(h != NULL);
21844 		return DUK_HOBJECT_HAS_CALLABLE(h) ? 1 : 0;
21845 	}
21846 	if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
21847 		return 1;
21848 	}
21849 	return 0;
21850 }
21851 
duk_is_callable_tval(duk_hthread * thr,duk_tval * tv)21852 DUK_INTERNAL duk_bool_t duk_is_callable_tval(duk_hthread *thr, duk_tval *tv) {
21853 	DUK_ASSERT_API_ENTRY(thr);
21854 
21855 	DUK_UNREF(thr);
21856 
21857 	if (DUK_TVAL_IS_OBJECT(tv)) {
21858 		duk_hobject *h;
21859 		h = DUK_TVAL_GET_OBJECT(tv);
21860 		DUK_ASSERT(h != NULL);
21861 		return DUK_HOBJECT_HAS_CALLABLE(h) ? 1 : 0;
21862 	}
21863 	if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
21864 		return 1;
21865 	}
21866 	return 0;
21867 }
21868 
duk_is_constructable(duk_hthread * thr,duk_idx_t idx)21869 DUK_EXTERNAL duk_bool_t duk_is_constructable(duk_hthread *thr, duk_idx_t idx) {
21870 	duk_tval *tv;
21871 
21872 	DUK_ASSERT_API_ENTRY(thr);
21873 
21874 	tv = duk_get_tval_or_unused(thr, idx);
21875 	if (DUK_TVAL_IS_OBJECT(tv)) {
21876 		duk_hobject *h;
21877 		h = DUK_TVAL_GET_OBJECT(tv);
21878 		DUK_ASSERT(h != NULL);
21879 		return DUK_HOBJECT_HAS_CONSTRUCTABLE(h) ? 1 : 0;
21880 	}
21881 	if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
21882 		return 1;
21883 	}
21884 	return 0;
21885 }
21886 
duk_is_c_function(duk_hthread * thr,duk_idx_t idx)21887 DUK_EXTERNAL duk_bool_t duk_is_c_function(duk_hthread *thr, duk_idx_t idx) {
21888 	DUK_ASSERT_API_ENTRY(thr);
21889 	return duk__obj_flag_any_default_false(thr,
21890 	                                       idx,
21891 	                                       DUK_HOBJECT_FLAG_NATFUNC);
21892 }
21893 
duk_is_ecmascript_function(duk_hthread * thr,duk_idx_t idx)21894 DUK_EXTERNAL duk_bool_t duk_is_ecmascript_function(duk_hthread *thr, duk_idx_t idx) {
21895 	DUK_ASSERT_API_ENTRY(thr);
21896 	return duk__obj_flag_any_default_false(thr,
21897 	                                       idx,
21898 	                                       DUK_HOBJECT_FLAG_COMPFUNC);
21899 }
21900 
duk_is_bound_function(duk_hthread * thr,duk_idx_t idx)21901 DUK_EXTERNAL duk_bool_t duk_is_bound_function(duk_hthread *thr, duk_idx_t idx) {
21902 	DUK_ASSERT_API_ENTRY(thr);
21903 	return duk__obj_flag_any_default_false(thr,
21904 	                                       idx,
21905 	                                       DUK_HOBJECT_FLAG_BOUNDFUNC);
21906 }
21907 
duk_is_thread(duk_hthread * thr,duk_idx_t idx)21908 DUK_EXTERNAL duk_bool_t duk_is_thread(duk_hthread *thr, duk_idx_t idx) {
21909 	duk_hobject *obj;
21910 
21911 	DUK_ASSERT_API_ENTRY(thr);
21912 
21913 	obj = duk_get_hobject(thr, idx);
21914 	if (obj) {
21915 		return (DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_THREAD ? 1 : 0);
21916 	}
21917 	return 0;
21918 }
21919 
duk_is_fixed_buffer(duk_hthread * thr,duk_idx_t idx)21920 DUK_EXTERNAL duk_bool_t duk_is_fixed_buffer(duk_hthread *thr, duk_idx_t idx) {
21921 	duk_tval *tv;
21922 
21923 	DUK_ASSERT_API_ENTRY(thr);
21924 
21925 	tv = duk_get_tval_or_unused(thr, idx);
21926 	DUK_ASSERT(tv != NULL);
21927 	if (DUK_TVAL_IS_BUFFER(tv)) {
21928 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
21929 		DUK_ASSERT(h != NULL);
21930 		return (DUK_HBUFFER_HAS_DYNAMIC(h) ? 0 : 1);
21931 	}
21932 	return 0;
21933 }
21934 
duk_is_dynamic_buffer(duk_hthread * thr,duk_idx_t idx)21935 DUK_EXTERNAL duk_bool_t duk_is_dynamic_buffer(duk_hthread *thr, duk_idx_t idx) {
21936 	duk_tval *tv;
21937 
21938 	DUK_ASSERT_API_ENTRY(thr);
21939 
21940 	tv = duk_get_tval_or_unused(thr, idx);
21941 	DUK_ASSERT(tv != NULL);
21942 	if (DUK_TVAL_IS_BUFFER(tv)) {
21943 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
21944 		DUK_ASSERT(h != NULL);
21945 		return (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
21946 	}
21947 	return 0;
21948 }
21949 
duk_is_external_buffer(duk_hthread * thr,duk_idx_t idx)21950 DUK_EXTERNAL duk_bool_t duk_is_external_buffer(duk_hthread *thr, duk_idx_t idx) {
21951 	duk_tval *tv;
21952 
21953 	DUK_ASSERT_API_ENTRY(thr);
21954 
21955 	tv = duk_get_tval_or_unused(thr, idx);
21956 	DUK_ASSERT(tv != NULL);
21957 	if (DUK_TVAL_IS_BUFFER(tv)) {
21958 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
21959 		DUK_ASSERT(h != NULL);
21960 		return (DUK_HBUFFER_HAS_DYNAMIC(h) && DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
21961 	}
21962 	return 0;
21963 }
21964 
duk_get_error_code(duk_hthread * thr,duk_idx_t idx)21965 DUK_EXTERNAL duk_errcode_t duk_get_error_code(duk_hthread *thr, duk_idx_t idx) {
21966 	duk_hobject *h;
21967 	duk_uint_t sanity;
21968 
21969 	DUK_ASSERT_API_ENTRY(thr);
21970 
21971 	h = duk_get_hobject(thr, idx);
21972 
21973 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
21974 	do {
21975 		if (!h) {
21976 			return DUK_ERR_NONE;
21977 		}
21978 
21979 		/* XXX: something more convenient? */
21980 
21981 		if (h == thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE]) {
21982 			return DUK_ERR_EVAL_ERROR;
21983 		}
21984 		if (h == thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE]) {
21985 			return DUK_ERR_RANGE_ERROR;
21986 		}
21987 		if (h == thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE]) {
21988 			return DUK_ERR_REFERENCE_ERROR;
21989 		}
21990 		if (h == thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE]) {
21991 			return DUK_ERR_SYNTAX_ERROR;
21992 		}
21993 		if (h == thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE]) {
21994 			return DUK_ERR_TYPE_ERROR;
21995 		}
21996 		if (h == thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE]) {
21997 			return DUK_ERR_URI_ERROR;
21998 		}
21999 		if (h == thr->builtins[DUK_BIDX_ERROR_PROTOTYPE]) {
22000 			return DUK_ERR_ERROR;
22001 		}
22002 
22003 		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
22004 	} while (--sanity > 0);
22005 
22006 	return DUK_ERR_NONE;
22007 }
22008 
22009 /*
22010  *  Pushers
22011  */
22012 
duk_push_tval(duk_hthread * thr,duk_tval * tv)22013 DUK_INTERNAL void duk_push_tval(duk_hthread *thr, duk_tval *tv) {
22014 	duk_tval *tv_slot;
22015 
22016 	DUK_ASSERT_API_ENTRY(thr);
22017 	DUK_ASSERT(tv != NULL);
22018 
22019 	DUK__CHECK_SPACE();
22020 	tv_slot = thr->valstack_top++;
22021 	DUK_TVAL_SET_TVAL(tv_slot, tv);
22022 	DUK_TVAL_INCREF(thr, tv);  /* no side effects */
22023 }
22024 
duk_push_undefined(duk_hthread * thr)22025 DUK_EXTERNAL void duk_push_undefined(duk_hthread *thr) {
22026 	DUK_ASSERT_API_ENTRY(thr);
22027 
22028 	DUK__CHECK_SPACE();
22029 
22030 	/* Because value stack init policy is 'undefined above top',
22031 	 * we don't need to write, just assert.
22032 	 */
22033 	thr->valstack_top++;
22034 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
22035 }
22036 
duk_push_null(duk_hthread * thr)22037 DUK_EXTERNAL void duk_push_null(duk_hthread *thr) {
22038 	duk_tval *tv_slot;
22039 
22040 	DUK_ASSERT_API_ENTRY(thr);
22041 	DUK__CHECK_SPACE();
22042 	tv_slot = thr->valstack_top++;
22043 	DUK_TVAL_SET_NULL(tv_slot);
22044 }
22045 
duk_push_boolean(duk_hthread * thr,duk_bool_t val)22046 DUK_EXTERNAL void duk_push_boolean(duk_hthread *thr, duk_bool_t val) {
22047 	duk_tval *tv_slot;
22048 	duk_small_int_t b;
22049 
22050 	DUK_ASSERT_API_ENTRY(thr);
22051 	DUK__CHECK_SPACE();
22052 	b = (val ? 1 : 0);  /* ensure value is 1 or 0 (not other non-zero) */
22053 	tv_slot = thr->valstack_top++;
22054 	DUK_TVAL_SET_BOOLEAN(tv_slot, b);
22055 }
22056 
duk_push_true(duk_hthread * thr)22057 DUK_EXTERNAL void duk_push_true(duk_hthread *thr) {
22058 	duk_tval *tv_slot;
22059 
22060 	DUK_ASSERT_API_ENTRY(thr);
22061 	DUK__CHECK_SPACE();
22062 	tv_slot = thr->valstack_top++;
22063 	DUK_TVAL_SET_BOOLEAN_TRUE(tv_slot);
22064 }
22065 
duk_push_false(duk_hthread * thr)22066 DUK_EXTERNAL void duk_push_false(duk_hthread *thr) {
22067 	duk_tval *tv_slot;
22068 
22069 	DUK_ASSERT_API_ENTRY(thr);
22070 	DUK__CHECK_SPACE();
22071 	tv_slot = thr->valstack_top++;
22072 	DUK_TVAL_SET_BOOLEAN_FALSE(tv_slot);
22073 }
22074 
22075 /* normalize NaN which may not match our canonical internal NaN */
duk_push_number(duk_hthread * thr,duk_double_t val)22076 DUK_EXTERNAL void duk_push_number(duk_hthread *thr, duk_double_t val) {
22077 	duk_tval *tv_slot;
22078 	duk_double_union du;
22079 
22080 	DUK_ASSERT_API_ENTRY(thr);
22081 	DUK__CHECK_SPACE();
22082 	du.d = val;
22083 	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
22084 	tv_slot = thr->valstack_top++;
22085 	DUK_TVAL_SET_NUMBER(tv_slot, du.d);
22086 }
22087 
duk_push_int(duk_hthread * thr,duk_int_t val)22088 DUK_EXTERNAL void duk_push_int(duk_hthread *thr, duk_int_t val) {
22089 #if defined(DUK_USE_FASTINT)
22090 	duk_tval *tv_slot;
22091 
22092 	DUK_ASSERT_API_ENTRY(thr);
22093 	DUK__CHECK_SPACE();
22094 	tv_slot = thr->valstack_top++;
22095 #if DUK_INT_MAX <= 0x7fffffffL
22096 	DUK_TVAL_SET_I32(tv_slot, (duk_int32_t) val);
22097 #else
22098 	if (val >= DUK_FASTINT_MIN && val <= DUK_FASTINT_MAX) {
22099 		DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
22100 	} else {
22101 		duk_double_t = (duk_double_t) val;
22102 		DUK_TVAL_SET_NUMBER(tv_slot, d);
22103 	}
22104 #endif
22105 #else  /* DUK_USE_FASTINT */
22106 	duk_tval *tv_slot;
22107 	duk_double_t d;
22108 
22109 	DUK_ASSERT_API_ENTRY(thr);
22110 	DUK__CHECK_SPACE();
22111 	d = (duk_double_t) val;
22112 	tv_slot = thr->valstack_top++;
22113 	DUK_TVAL_SET_NUMBER(tv_slot, d);
22114 #endif  /* DUK_USE_FASTINT */
22115 }
22116 
duk_push_uint(duk_hthread * thr,duk_uint_t val)22117 DUK_EXTERNAL void duk_push_uint(duk_hthread *thr, duk_uint_t val) {
22118 #if defined(DUK_USE_FASTINT)
22119 	duk_tval *tv_slot;
22120 
22121 	DUK_ASSERT_API_ENTRY(thr);
22122 	DUK__CHECK_SPACE();
22123 	tv_slot = thr->valstack_top++;
22124 #if DUK_UINT_MAX <= 0xffffffffUL
22125 	DUK_TVAL_SET_U32(tv_slot, (duk_uint32_t) val);
22126 #else
22127 	if (val <= DUK_FASTINT_MAX) {  /* val is unsigned so >= 0 */
22128 		/* XXX: take advantage of val being unsigned, no need to mask */
22129 		DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
22130 	} else {
22131 		duk_double_t = (duk_double_t) val;
22132 		DUK_TVAL_SET_NUMBER(tv_slot, d);
22133 	}
22134 #endif
22135 #else  /* DUK_USE_FASTINT */
22136 	duk_tval *tv_slot;
22137 	duk_double_t d;
22138 
22139 	DUK_ASSERT_API_ENTRY(thr);
22140 	DUK__CHECK_SPACE();
22141 	d = (duk_double_t) val;
22142 	tv_slot = thr->valstack_top++;
22143 	DUK_TVAL_SET_NUMBER(tv_slot, d);
22144 #endif  /* DUK_USE_FASTINT */
22145 }
22146 
duk_push_nan(duk_hthread * thr)22147 DUK_EXTERNAL void duk_push_nan(duk_hthread *thr) {
22148 	duk_tval *tv_slot;
22149 	duk_double_union du;
22150 
22151 	DUK_ASSERT_API_ENTRY(thr);
22152 	DUK__CHECK_SPACE();
22153 	DUK_DBLUNION_SET_NAN(&du);
22154 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
22155 	tv_slot = thr->valstack_top++;
22156 	DUK_TVAL_SET_NUMBER(tv_slot, du.d);
22157 }
22158 
duk_push_lstring(duk_hthread * thr,const char * str,duk_size_t len)22159 DUK_EXTERNAL const char *duk_push_lstring(duk_hthread *thr, const char *str, duk_size_t len) {
22160 	duk_hstring *h;
22161 	duk_tval *tv_slot;
22162 
22163 	DUK_ASSERT_API_ENTRY(thr);
22164 
22165 	/* Check stack before interning (avoid hanging temp). */
22166 	DUK__CHECK_SPACE();
22167 
22168 	/* NULL with zero length represents an empty string; NULL with higher
22169 	 * length is also now treated like an empty string although it is
22170 	 * a bit dubious.  This is unlike duk_push_string() which pushes a
22171 	 * 'null' if the input string is a NULL.
22172 	 */
22173 	if (DUK_UNLIKELY(str == NULL)) {
22174 		len = 0U;
22175 	}
22176 
22177 	/* Check for maximum string length. */
22178 	if (DUK_UNLIKELY(len > DUK_HSTRING_MAX_BYTELEN)) {
22179 		DUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG);
22180 		DUK_WO_NORETURN(return NULL;);
22181 	}
22182 
22183 	h = duk_heap_strtable_intern_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
22184 	DUK_ASSERT(h != NULL);
22185 
22186 	tv_slot = thr->valstack_top++;
22187 	DUK_TVAL_SET_STRING(tv_slot, h);
22188 	DUK_HSTRING_INCREF(thr, h);  /* no side effects */
22189 
22190 	return (const char *) DUK_HSTRING_GET_DATA(h);
22191 }
22192 
duk_push_string(duk_hthread * thr,const char * str)22193 DUK_EXTERNAL const char *duk_push_string(duk_hthread *thr, const char *str) {
22194 	DUK_ASSERT_API_ENTRY(thr);
22195 
22196 	if (str) {
22197 		return duk_push_lstring(thr, str, DUK_STRLEN(str));
22198 	} else {
22199 		duk_push_null(thr);
22200 		return NULL;
22201 	}
22202 }
22203 
22204 #if !defined(DUK_USE_PREFER_SIZE)
22205 #if defined(DUK_USE_LITCACHE_SIZE)
duk_push_literal_raw(duk_hthread * thr,const char * str,duk_size_t len)22206 DUK_EXTERNAL const char *duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len) {
22207 	duk_hstring *h;
22208 	duk_tval *tv_slot;
22209 
22210 	DUK_ASSERT_API_ENTRY(thr);
22211 	DUK_ASSERT(str != NULL);
22212 	DUK_ASSERT(str[len] == (char) 0);
22213 
22214 	/* Check for maximum string length. */
22215 	if (DUK_UNLIKELY(len > DUK_HSTRING_MAX_BYTELEN)) {
22216 		DUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG);
22217 		DUK_WO_NORETURN(return NULL;);
22218 	}
22219 
22220 	h = duk_heap_strtable_intern_literal_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
22221 	DUK_ASSERT(h != NULL);
22222 
22223 	tv_slot = thr->valstack_top++;
22224 	DUK_TVAL_SET_STRING(tv_slot, h);
22225 	DUK_HSTRING_INCREF(thr, h);  /* no side effects */
22226 
22227 	return (const char *) DUK_HSTRING_GET_DATA(h);
22228 }
22229 #else  /* DUK_USE_LITCACHE_SIZE */
duk_push_literal_raw(duk_hthread * thr,const char * str,duk_size_t len)22230 DUK_EXTERNAL const char *duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len) {
22231 	DUK_ASSERT_API_ENTRY(thr);
22232 	DUK_ASSERT(str != NULL);
22233 	DUK_ASSERT(str[len] == (char) 0);
22234 
22235 	return duk_push_lstring(thr, str, len);
22236 }
22237 #endif  /* DUK_USE_LITCACHE_SIZE */
22238 #endif  /* !DUK_USE_PREFER_SIZE */
22239 
duk_push_pointer(duk_hthread * thr,void * val)22240 DUK_EXTERNAL void duk_push_pointer(duk_hthread *thr, void *val) {
22241 	duk_tval *tv_slot;
22242 
22243 	DUK_ASSERT_API_ENTRY(thr);
22244 	DUK__CHECK_SPACE();
22245 	tv_slot = thr->valstack_top++;
22246 	DUK_TVAL_SET_POINTER(tv_slot, val);
22247 }
22248 
duk_push_uint_to_hstring(duk_hthread * thr,duk_uint_t i)22249 DUK_INTERNAL duk_hstring *duk_push_uint_to_hstring(duk_hthread *thr, duk_uint_t i) {
22250 	duk_hstring *h_tmp;
22251 
22252 	DUK_ASSERT_API_ENTRY(thr);
22253 
22254 	/* XXX: this could be a direct DUK_SPRINTF to a buffer followed by duk_push_string() */
22255 	duk_push_uint(thr, (duk_uint_t) i);
22256 	h_tmp = duk_to_hstring_m1(thr);
22257 	DUK_ASSERT(h_tmp != NULL);
22258 	return h_tmp;
22259 }
22260 
duk__push_this_helper(duk_hthread * thr,duk_small_uint_t check_object_coercible)22261 DUK_LOCAL void duk__push_this_helper(duk_hthread *thr, duk_small_uint_t check_object_coercible) {
22262 	duk_tval *tv_slot;
22263 
22264 	DUK__CHECK_SPACE();
22265 
22266 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* because of valstack init policy */
22267 	tv_slot = thr->valstack_top++;
22268 
22269 	if (DUK_UNLIKELY(thr->callstack_curr == NULL)) {
22270 		if (check_object_coercible) {
22271 			goto type_error;
22272 		}
22273 		/* 'undefined' already on stack top */
22274 	} else {
22275 		duk_tval *tv;
22276 
22277 		/* 'this' binding is just before current activation's bottom */
22278 		DUK_ASSERT(thr->valstack_bottom > thr->valstack);
22279 		tv = thr->valstack_bottom - 1;
22280 		if (check_object_coercible &&
22281 		    (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv))) {
22282 			/* XXX: better macro for DUK_TVAL_IS_UNDEFINED_OR_NULL(tv) */
22283 			goto type_error;
22284 		}
22285 
22286 		DUK_TVAL_SET_TVAL(tv_slot, tv);
22287 		DUK_TVAL_INCREF(thr, tv);
22288 	}
22289 	return;
22290 
22291  type_error:
22292 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);
22293 	DUK_WO_NORETURN(return;);
22294 }
22295 
duk_push_this(duk_hthread * thr)22296 DUK_EXTERNAL void duk_push_this(duk_hthread *thr) {
22297 	DUK_ASSERT_API_ENTRY(thr);
22298 
22299 	duk__push_this_helper(thr, 0 /*check_object_coercible*/);
22300 }
22301 
duk_push_this_check_object_coercible(duk_hthread * thr)22302 DUK_INTERNAL void duk_push_this_check_object_coercible(duk_hthread *thr) {
22303 	DUK_ASSERT_API_ENTRY(thr);
22304 
22305 	duk__push_this_helper(thr, 1 /*check_object_coercible*/);
22306 }
22307 
duk_push_this_coercible_to_object(duk_hthread * thr)22308 DUK_INTERNAL duk_hobject *duk_push_this_coercible_to_object(duk_hthread *thr) {
22309 	duk_hobject *h;
22310 
22311 	DUK_ASSERT_API_ENTRY(thr);
22312 
22313 	duk__push_this_helper(thr, 1 /*check_object_coercible*/);
22314 	h = duk_to_hobject(thr, -1);
22315 	DUK_ASSERT(h != NULL);
22316 	return h;
22317 }
22318 
duk_push_this_coercible_to_string(duk_hthread * thr)22319 DUK_INTERNAL duk_hstring *duk_push_this_coercible_to_string(duk_hthread *thr) {
22320 	DUK_ASSERT_API_ENTRY(thr);
22321 
22322 	duk__push_this_helper(thr, 1 /*check_object_coercible*/);
22323 	return duk_to_hstring_m1(thr);  /* This will reject all Symbol values; accepts Symbol objects. */
22324 }
22325 
duk_get_borrowed_this_tval(duk_hthread * thr)22326 DUK_INTERNAL duk_tval *duk_get_borrowed_this_tval(duk_hthread *thr) {
22327 	DUK_ASSERT_API_ENTRY(thr);
22328 
22329 	DUK_ASSERT(thr->callstack_top > 0);  /* caller required to know */
22330 	DUK_ASSERT(thr->callstack_curr != NULL);  /* caller required to know */
22331 	DUK_ASSERT(thr->valstack_bottom > thr->valstack);  /* consequence of above */
22332 	DUK_ASSERT(thr->valstack_bottom - 1 >= thr->valstack);  /* 'this' binding exists */
22333 
22334 	return thr->valstack_bottom - 1;
22335 }
22336 
duk_push_new_target(duk_hthread * thr)22337 DUK_EXTERNAL void duk_push_new_target(duk_hthread *thr) {
22338 	duk_activation *act;
22339 
22340 	DUK_ASSERT_API_ENTRY(thr);
22341 
22342 	/* https://www.ecma-international.org/ecma-262/6.0/#sec-meta-properties-runtime-semantics-evaluation
22343 	 * https://www.ecma-international.org/ecma-262/6.0/#sec-getnewtarget
22344 	 *
22345 	 * No newTarget support now, so as a first approximation
22346 	 * use the resolved (non-bound) target function.
22347 	 *
22348 	 * Check CONSTRUCT flag from current function, or if running
22349 	 * direct eval, from a non-direct-eval parent (with possibly
22350 	 * more than one nested direct eval).  An alternative to this
22351 	 * would be to store [[NewTarget]] as a hidden symbol of the
22352 	 * lexical scope, and then just look up that variable.
22353 	 *
22354 	 * Calls from the application will either be for an empty
22355 	 * call stack, or a Duktape/C function as the top activation.
22356 	 */
22357 
22358 	act = thr->callstack_curr;
22359 	for (;;) {
22360 		if (act == NULL) {
22361 			break;
22362 		}
22363 
22364 		if (act->flags & DUK_ACT_FLAG_CONSTRUCT) {
22365 			duk_push_tval(thr, &act->tv_func);
22366 			return;
22367 		} else if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
22368 			act = act->parent;
22369 		} else {
22370 			break;
22371 		}
22372 	}
22373 
22374 	duk_push_undefined(thr);
22375 }
22376 
duk_push_current_function(duk_hthread * thr)22377 DUK_EXTERNAL void duk_push_current_function(duk_hthread *thr) {
22378 	duk_activation *act;
22379 
22380 	DUK_ASSERT_API_ENTRY(thr);
22381 
22382 	act = thr->callstack_curr;
22383 	if (act != NULL) {
22384 		duk_push_tval(thr, &act->tv_func);
22385 	} else {
22386 		duk_push_undefined(thr);
22387 	}
22388 }
22389 
duk_push_current_thread(duk_hthread * thr)22390 DUK_EXTERNAL void duk_push_current_thread(duk_hthread *thr) {
22391 	DUK_ASSERT_API_ENTRY(thr);
22392 
22393 	if (thr->heap->curr_thread) {
22394 		duk_push_hobject(thr, (duk_hobject *) thr->heap->curr_thread);
22395 	} else {
22396 		duk_push_undefined(thr);
22397 	}
22398 }
22399 
duk_push_global_object(duk_hthread * thr)22400 DUK_EXTERNAL void duk_push_global_object(duk_hthread *thr) {
22401 	DUK_ASSERT_API_ENTRY(thr);
22402 
22403 	duk_push_hobject_bidx(thr, DUK_BIDX_GLOBAL);
22404 }
22405 
22406 /* XXX: size optimize */
duk__push_stash(duk_hthread * thr)22407 DUK_LOCAL void duk__push_stash(duk_hthread *thr) {
22408 	if (!duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE)) {
22409 		DUK_DDD(DUK_DDDPRINT("creating heap/global/thread stash on first use"));
22410 		duk_pop_unsafe(thr);
22411 		duk_push_bare_object(thr);
22412 		duk_dup_top(thr);
22413 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_C);  /* [ ... parent stash stash ] -> [ ... parent stash ] */
22414 	}
22415 	duk_remove_m2(thr);
22416 }
22417 
duk_push_heap_stash(duk_hthread * thr)22418 DUK_EXTERNAL void duk_push_heap_stash(duk_hthread *thr) {
22419 	duk_heap *heap;
22420 	DUK_ASSERT_API_ENTRY(thr);
22421 	heap = thr->heap;
22422 	DUK_ASSERT(heap->heap_object != NULL);
22423 	duk_push_hobject(thr, heap->heap_object);
22424 	duk__push_stash(thr);
22425 }
22426 
duk_push_global_stash(duk_hthread * thr)22427 DUK_EXTERNAL void duk_push_global_stash(duk_hthread *thr) {
22428 	DUK_ASSERT_API_ENTRY(thr);
22429 	duk_push_global_object(thr);
22430 	duk__push_stash(thr);
22431 }
22432 
duk_push_thread_stash(duk_hthread * thr,duk_hthread * target_thr)22433 DUK_EXTERNAL void duk_push_thread_stash(duk_hthread *thr, duk_hthread *target_thr) {
22434 	DUK_ASSERT_API_ENTRY(thr);
22435 	if (DUK_UNLIKELY(target_thr == NULL)) {
22436 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
22437 		DUK_WO_NORETURN(return;);
22438 	}
22439 	duk_push_hobject(thr, (duk_hobject *) target_thr);
22440 	duk__push_stash(thr);
22441 }
22442 
22443 /* 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)22444 DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_hthread *thr, void *buf, duk_size_t sz, const char *fmt, va_list ap) {
22445 	duk_int_t len;
22446 
22447 	DUK_CTX_ASSERT_VALID(thr);
22448 	DUK_UNREF(thr);
22449 
22450 	/* NUL terminator handling doesn't matter here */
22451 	len = DUK_VSNPRINTF((char *) buf, sz, fmt, ap);
22452 	if (len < (duk_int_t) sz) {
22453 		/* Return value of 'sz' or more indicates output was (potentially)
22454 		 * truncated.
22455 		 */
22456 		return (duk_int_t) len;
22457 	}
22458 	return -1;
22459 }
22460 
duk_push_vsprintf(duk_hthread * thr,const char * fmt,va_list ap)22461 DUK_EXTERNAL const char *duk_push_vsprintf(duk_hthread *thr, const char *fmt, va_list ap) {
22462 	duk_uint8_t stack_buf[DUK_PUSH_SPRINTF_INITIAL_SIZE];
22463 	duk_size_t sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
22464 	duk_bool_t pushed_buf = 0;
22465 	void *buf;
22466 	duk_int_t len;  /* XXX: duk_ssize_t */
22467 	const char *res;
22468 
22469 	DUK_ASSERT_API_ENTRY(thr);
22470 
22471 	/* special handling of fmt==NULL */
22472 	if (!fmt) {
22473 		duk_hstring *h_str;
22474 		duk_push_hstring_empty(thr);
22475 		h_str = duk_known_hstring(thr, -1);
22476 		return (const char *) DUK_HSTRING_GET_DATA(h_str);
22477 	}
22478 
22479 	/* initial estimate based on format string */
22480 	sz = DUK_STRLEN(fmt) + 16;  /* format plus something to avoid just missing */
22481 	if (sz < DUK_PUSH_SPRINTF_INITIAL_SIZE) {
22482 		sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
22483 	}
22484 	DUK_ASSERT(sz > 0);
22485 
22486 	/* Try to make do with a stack buffer to avoid allocating a temporary buffer.
22487 	 * This works 99% of the time which is quite nice.
22488 	 */
22489 	for (;;) {
22490 		va_list ap_copy;  /* copied so that 'ap' can be reused */
22491 
22492 		if (sz <= sizeof(stack_buf)) {
22493 			buf = stack_buf;
22494 		} else if (!pushed_buf) {
22495 			pushed_buf = 1;
22496 			buf = duk_push_dynamic_buffer(thr, sz);
22497 		} else {
22498 			buf = duk_resize_buffer(thr, -1, sz);
22499 		}
22500 		DUK_ASSERT(buf != NULL);
22501 
22502 		DUK_VA_COPY(ap_copy, ap);
22503 		len = duk__try_push_vsprintf(thr, buf, sz, fmt, ap_copy);
22504 		va_end(ap_copy);
22505 		if (len >= 0) {
22506 			break;
22507 		}
22508 
22509 		/* failed, resize and try again */
22510 		sz = sz * 2;
22511 		if (DUK_UNLIKELY(sz >= DUK_PUSH_SPRINTF_SANITY_LIMIT)) {
22512 			DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
22513 			DUK_WO_NORETURN(return NULL;);
22514 		}
22515 	}
22516 
22517 	/* Cannot use duk_buffer_to_string() on the buffer because it is
22518 	 * usually larger than 'len'; 'buf' is also usually a stack buffer.
22519 	 */
22520 	res = duk_push_lstring(thr, (const char *) buf, (duk_size_t) len);  /* [ buf? res ] */
22521 	if (pushed_buf) {
22522 		duk_remove_m2(thr);
22523 	}
22524 	return res;
22525 }
22526 
duk_push_sprintf(duk_hthread * thr,const char * fmt,...)22527 DUK_EXTERNAL const char *duk_push_sprintf(duk_hthread *thr, const char *fmt, ...) {
22528 	va_list ap;
22529 	const char *ret;
22530 
22531 	DUK_ASSERT_API_ENTRY(thr);
22532 
22533 	/* allow fmt==NULL */
22534 	va_start(ap, fmt);
22535 	ret = duk_push_vsprintf(thr, fmt, ap);
22536 	va_end(ap);
22537 
22538 	return ret;
22539 }
22540 
duk_push_object_helper(duk_hthread * thr,duk_uint_t hobject_flags_and_class,duk_small_int_t prototype_bidx)22541 DUK_INTERNAL duk_hobject *duk_push_object_helper(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
22542 	duk_tval *tv_slot;
22543 	duk_hobject *h;
22544 
22545 	DUK_ASSERT_API_ENTRY(thr);
22546 	DUK_ASSERT(prototype_bidx == -1 ||
22547 	           (prototype_bidx >= 0 && prototype_bidx < DUK_NUM_BUILTINS));
22548 
22549 	DUK__CHECK_SPACE();
22550 
22551 	h = duk_hobject_alloc(thr, hobject_flags_and_class);
22552 	DUK_ASSERT(h != NULL);
22553 
22554 	DUK_DDD(DUK_DDDPRINT("created object with flags: 0x%08lx", (unsigned long) h->hdr.h_flags));
22555 
22556 	tv_slot = thr->valstack_top;
22557 	DUK_TVAL_SET_OBJECT(tv_slot, h);
22558 	DUK_HOBJECT_INCREF(thr, h);  /* no side effects */
22559 	thr->valstack_top++;
22560 
22561 	/* object is now reachable */
22562 
22563 	if (prototype_bidx >= 0) {
22564 		DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, h, thr->builtins[prototype_bidx]);
22565 	} else {
22566 		DUK_ASSERT(prototype_bidx == -1);
22567 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h) == NULL);
22568 	}
22569 
22570 	return h;
22571 }
22572 
duk_push_object_helper_proto(duk_hthread * thr,duk_uint_t hobject_flags_and_class,duk_hobject * proto)22573 DUK_INTERNAL duk_hobject *duk_push_object_helper_proto(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_hobject *proto) {
22574 	duk_hobject *h;
22575 
22576 	DUK_ASSERT_API_ENTRY(thr);
22577 
22578 	h = duk_push_object_helper(thr, hobject_flags_and_class, -1);
22579 	DUK_ASSERT(h != NULL);
22580 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, h, proto);
22581 	return h;
22582 }
22583 
duk_push_object(duk_hthread * thr)22584 DUK_EXTERNAL duk_idx_t duk_push_object(duk_hthread *thr) {
22585 	DUK_ASSERT_API_ENTRY(thr);
22586 
22587 	(void) duk_push_object_helper(thr,
22588 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
22589 	                              DUK_HOBJECT_FLAG_FASTREFS |
22590 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
22591 	                              DUK_BIDX_OBJECT_PROTOTYPE);
22592 	return duk_get_top_index_unsafe(thr);
22593 }
22594 
duk_push_array(duk_hthread * thr)22595 DUK_EXTERNAL duk_idx_t duk_push_array(duk_hthread *thr) {
22596 	duk_uint_t flags;
22597 	duk_harray *obj;
22598 	duk_idx_t ret;
22599 	duk_tval *tv_slot;
22600 
22601 	DUK_ASSERT_API_ENTRY(thr);
22602 
22603 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
22604 	        DUK_HOBJECT_FLAG_FASTREFS |
22605 	        DUK_HOBJECT_FLAG_ARRAY_PART |
22606 	        DUK_HOBJECT_FLAG_EXOTIC_ARRAY |
22607 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAY);
22608 
22609 	obj = duk_harray_alloc(thr, flags);
22610 	DUK_ASSERT(obj != NULL);
22611 
22612 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_ARRAY_PROTOTYPE]);
22613 
22614 	tv_slot = thr->valstack_top;
22615 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22616 	DUK_HOBJECT_INCREF(thr, obj);  /* XXX: could preallocate with refcount = 1 */
22617 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
22618 	thr->valstack_top++;
22619 
22620 	DUK_ASSERT(obj->length == 0);  /* Array .length starts at zero. */
22621 	return ret;
22622 }
22623 
duk_push_bare_array(duk_hthread * thr)22624 DUK_EXTERNAL duk_idx_t duk_push_bare_array(duk_hthread *thr) {
22625 	duk_uint_t flags;
22626 	duk_harray *obj;
22627 	duk_idx_t ret;
22628 	duk_tval *tv_slot;
22629 
22630 	DUK_ASSERT_API_ENTRY(thr);
22631 
22632 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
22633 	        DUK_HOBJECT_FLAG_FASTREFS |
22634 	        DUK_HOBJECT_FLAG_ARRAY_PART |
22635 	        DUK_HOBJECT_FLAG_EXOTIC_ARRAY |
22636 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAY);
22637 
22638 	obj = duk_harray_alloc(thr, flags);
22639 	DUK_ASSERT(obj != NULL);
22640 
22641 	tv_slot = thr->valstack_top;
22642 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22643 	DUK_HOBJECT_INCREF(thr, obj);  /* XXX: could preallocate with refcount = 1 */
22644 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
22645 	thr->valstack_top++;
22646 
22647 	DUK_ASSERT(obj->length == 0);  /* Array .length starts at zero. */
22648 	return ret;
22649 }
22650 
duk_push_harray(duk_hthread * thr)22651 DUK_INTERNAL duk_harray *duk_push_harray(duk_hthread *thr) {
22652 	/* XXX: API call could do this directly, cast to void in API macro. */
22653 	duk_harray *a;
22654 
22655 	DUK_ASSERT_API_ENTRY(thr);
22656 
22657 	(void) duk_push_array(thr);
22658 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(thr->valstack_top - 1));
22659 	a = (duk_harray *) DUK_TVAL_GET_OBJECT(thr->valstack_top - 1);
22660 	DUK_ASSERT(a != NULL);
22661 	return a;
22662 }
22663 
22664 /* Push a duk_harray with preallocated size (.length also set to match size).
22665  * Caller may then populate array part of the duk_harray directly.
22666  */
duk_push_harray_with_size(duk_hthread * thr,duk_uint32_t size)22667 DUK_INTERNAL duk_harray *duk_push_harray_with_size(duk_hthread *thr, duk_uint32_t size) {
22668 	duk_harray *a;
22669 
22670 	DUK_ASSERT_API_ENTRY(thr);
22671 
22672 	a = duk_push_harray(thr);
22673 
22674 	duk_hobject_realloc_props(thr,
22675 	                          (duk_hobject *) a,
22676 	                          0,
22677 	                          size,
22678 	                          0,
22679 	                          0);
22680 	a->length = size;
22681 	return a;
22682 }
22683 
duk_push_harray_with_size_outptr(duk_hthread * thr,duk_uint32_t size)22684 DUK_INTERNAL duk_tval *duk_push_harray_with_size_outptr(duk_hthread *thr, duk_uint32_t size) {
22685 	duk_harray *a;
22686 
22687 	DUK_ASSERT_API_ENTRY(thr);
22688 
22689 	a = duk_push_harray_with_size(thr, size);
22690 	DUK_ASSERT(a != NULL);
22691 	return DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a);
22692 }
22693 
duk_push_thread_raw(duk_hthread * thr,duk_uint_t flags)22694 DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_hthread *thr, duk_uint_t flags) {
22695 	duk_hthread *obj;
22696 	duk_idx_t ret;
22697 	duk_tval *tv_slot;
22698 
22699 	DUK_ASSERT_API_ENTRY(thr);
22700 
22701 	DUK__CHECK_SPACE();
22702 
22703 	obj = duk_hthread_alloc(thr,
22704 	                        DUK_HOBJECT_FLAG_EXTENSIBLE |
22705 	                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
22706 	DUK_ASSERT(obj != NULL);
22707 	obj->state = DUK_HTHREAD_STATE_INACTIVE;
22708 #if defined(DUK_USE_ROM_STRINGS)
22709 	/* Nothing to initialize, strs[] is in ROM. */
22710 #else
22711 #if defined(DUK_USE_HEAPPTR16)
22712 	obj->strs16 = thr->strs16;
22713 #else
22714 	obj->strs = thr->strs;
22715 #endif
22716 #endif
22717 	DUK_DDD(DUK_DDDPRINT("created thread object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
22718 
22719 	/* make the new thread reachable */
22720 	tv_slot = thr->valstack_top;
22721 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22722 	DUK_HTHREAD_INCREF(thr, obj);
22723 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
22724 	thr->valstack_top++;
22725 
22726 	/* important to do this *after* pushing, to make the thread reachable for gc */
22727 	if (DUK_UNLIKELY(!duk_hthread_init_stacks(thr->heap, obj))) {
22728 		DUK_ERROR_ALLOC_FAILED(thr);
22729 		DUK_WO_NORETURN(return 0;);
22730 	}
22731 
22732 	/* initialize built-ins - either by copying or creating new ones */
22733 	if (flags & DUK_THREAD_NEW_GLOBAL_ENV) {
22734 		duk_hthread_create_builtin_objects(obj);
22735 	} else {
22736 		duk_hthread_copy_builtin_objects(thr, obj);
22737 	}
22738 
22739 	/* default prototype */
22740 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, obj->builtins[DUK_BIDX_THREAD_PROTOTYPE]);
22741 
22742 	/* Initial stack size satisfies the stack slack constraints so there
22743 	 * is no need to require stack here.
22744 	 */
22745 	DUK_ASSERT(DUK_VALSTACK_INITIAL_SIZE >=
22746 	           DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
22747 
22748 	return ret;
22749 }
22750 
duk_push_hcompfunc(duk_hthread * thr)22751 DUK_INTERNAL duk_hcompfunc *duk_push_hcompfunc(duk_hthread *thr) {
22752 	duk_hcompfunc *obj;
22753 	duk_tval *tv_slot;
22754 
22755 	DUK_ASSERT_API_ENTRY(thr);
22756 
22757 	DUK__CHECK_SPACE();
22758 
22759 	/* Template functions are not strictly constructable (they don't
22760 	 * have a "prototype" property for instance), so leave the
22761 	 * DUK_HOBJECT_FLAG_CONSRUCTABLE flag cleared here.
22762 	 */
22763 
22764 	obj = duk_hcompfunc_alloc(thr,
22765 	                          DUK_HOBJECT_FLAG_EXTENSIBLE |
22766 	                          DUK_HOBJECT_FLAG_CALLABLE |
22767 	                          DUK_HOBJECT_FLAG_COMPFUNC |
22768 	                          DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
22769 	if (DUK_UNLIKELY(obj == NULL)) {
22770 		DUK_ERROR_ALLOC_FAILED(thr);
22771 		DUK_WO_NORETURN(return NULL;);
22772 	}
22773 
22774 	DUK_DDD(DUK_DDDPRINT("created compiled function object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
22775 
22776 	tv_slot = thr->valstack_top;
22777 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22778 	DUK_HOBJECT_INCREF(thr, obj);
22779 	thr->valstack_top++;
22780 
22781 	/* default prototype */
22782 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) obj) == NULL);
22783 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
22784 
22785 	return obj;
22786 }
22787 
duk_push_hboundfunc(duk_hthread * thr)22788 DUK_INTERNAL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr) {
22789 	duk_hboundfunc *obj;
22790 	duk_tval *tv_slot;
22791 
22792 	DUK_ASSERT_API_ENTRY(thr);
22793 
22794 	DUK__CHECK_SPACE();
22795 	obj = duk_hboundfunc_alloc(thr->heap,
22796 	                           DUK_HOBJECT_FLAG_EXTENSIBLE |
22797 	                           DUK_HOBJECT_FLAG_BOUNDFUNC |
22798 	                           DUK_HOBJECT_FLAG_CONSTRUCTABLE |
22799 	                           DUK_HOBJECT_FLAG_CALLABLE |
22800 	                           DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
22801 	if (!obj) {
22802 		DUK_ERROR_ALLOC_FAILED(thr);
22803 		DUK_WO_NORETURN(return NULL;);
22804 	}
22805 
22806 	tv_slot = thr->valstack_top++;
22807 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22808 	DUK_HOBJECT_INCREF(thr, obj);
22809 
22810 	/* Prototype is left as NULL because the caller always sets it (and
22811 	 * it depends on the target function).
22812 	 */
22813 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) obj) == NULL);
22814 
22815 	return obj;
22816 }
22817 
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)22818 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) {
22819 	duk_hnatfunc *obj;
22820 	duk_idx_t ret;
22821 	duk_tval *tv_slot;
22822 	duk_int16_t func_nargs;
22823 
22824 	DUK_CTX_ASSERT_VALID(thr);
22825 
22826 	DUK__CHECK_SPACE();
22827 
22828 	if (DUK_UNLIKELY(func == NULL)) {
22829 		goto api_error;
22830 	}
22831 	if (nargs >= 0 && nargs < DUK_HNATFUNC_NARGS_MAX) {
22832 		func_nargs = (duk_int16_t) nargs;
22833 	} else if (nargs == DUK_VARARGS) {
22834 		func_nargs = DUK_HNATFUNC_NARGS_VARARGS;
22835 	} else {
22836 		goto api_error;
22837 	}
22838 
22839 	obj = duk_hnatfunc_alloc(thr, flags);
22840 	DUK_ASSERT(obj != NULL);
22841 
22842 	obj->func = func;
22843 	obj->nargs = func_nargs;
22844 
22845 	DUK_DDD(DUK_DDDPRINT("created native function object with flags: 0x%08lx, nargs=%ld",
22846 	                     (unsigned long) obj->obj.hdr.h_flags, (long) obj->nargs));
22847 
22848 	tv_slot = thr->valstack_top;
22849 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22850 	DUK_HOBJECT_INCREF(thr, obj);
22851 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
22852 	thr->valstack_top++;
22853 
22854 	DUK_ASSERT_BIDX_VALID(proto_bidx);
22855 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[proto_bidx]);
22856 	return ret;
22857 
22858  api_error:
22859 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
22860 	DUK_WO_NORETURN(return 0;);
22861 }
22862 
duk_push_c_function(duk_hthread * thr,duk_c_function func,duk_int_t nargs)22863 DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
22864 	duk_uint_t flags;
22865 
22866 	DUK_ASSERT_API_ENTRY(thr);
22867 
22868 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
22869 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
22870 	        DUK_HOBJECT_FLAG_CALLABLE |
22871 	        DUK_HOBJECT_FLAG_FASTREFS |
22872 	        DUK_HOBJECT_FLAG_NATFUNC |
22873 	        DUK_HOBJECT_FLAG_NEWENV |
22874 	        DUK_HOBJECT_FLAG_STRICT |
22875 	        DUK_HOBJECT_FLAG_NOTAIL |
22876 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
22877 
22878 	/* Default prototype is a Duktape specific %NativeFunctionPrototype%
22879 	 * which provides .length and .name getters.
22880 	 */
22881 	return duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE);
22882 }
22883 
duk_push_c_function_builtin(duk_hthread * thr,duk_c_function func,duk_int_t nargs)22884 DUK_INTERNAL void duk_push_c_function_builtin(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
22885 	duk_uint_t flags;
22886 
22887 	DUK_ASSERT_API_ENTRY(thr);
22888 
22889 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
22890 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
22891 	        DUK_HOBJECT_FLAG_CALLABLE |
22892 	        DUK_HOBJECT_FLAG_FASTREFS |
22893 	        DUK_HOBJECT_FLAG_NATFUNC |
22894 	        DUK_HOBJECT_FLAG_NEWENV |
22895 	        DUK_HOBJECT_FLAG_STRICT |
22896 	        DUK_HOBJECT_FLAG_NOTAIL |
22897 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
22898 
22899 	/* Must use Function.prototype for standard built-in functions. */
22900 	(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_FUNCTION_PROTOTYPE);
22901 }
22902 
duk_push_c_function_builtin_noconstruct(duk_hthread * thr,duk_c_function func,duk_int_t nargs)22903 DUK_INTERNAL void duk_push_c_function_builtin_noconstruct(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
22904 	duk_uint_t flags;
22905 
22906 	DUK_ASSERT_API_ENTRY(thr);
22907 
22908 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
22909 	        DUK_HOBJECT_FLAG_CALLABLE |
22910 	        DUK_HOBJECT_FLAG_FASTREFS |
22911 	        DUK_HOBJECT_FLAG_NATFUNC |
22912 	        DUK_HOBJECT_FLAG_NEWENV |
22913 	        DUK_HOBJECT_FLAG_STRICT |
22914 	        DUK_HOBJECT_FLAG_NOTAIL |
22915 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
22916 
22917 	/* Must use Function.prototype for standard built-in functions. */
22918 	(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_FUNCTION_PROTOTYPE);
22919 }
22920 
duk_push_c_lightfunc(duk_hthread * thr,duk_c_function func,duk_idx_t nargs,duk_idx_t length,duk_int_t magic)22921 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) {
22922 	duk_small_uint_t lf_flags;
22923 	duk_tval *tv_slot;
22924 
22925 	DUK_ASSERT_API_ENTRY(thr);
22926 
22927 	DUK__CHECK_SPACE();
22928 
22929 	if (nargs >= DUK_LFUNC_NARGS_MIN && nargs <= DUK_LFUNC_NARGS_MAX) {
22930 		/* as is */
22931 	} else if (nargs == DUK_VARARGS) {
22932 		nargs = DUK_LFUNC_NARGS_VARARGS;
22933 	} else {
22934 		goto api_error;
22935 	}
22936 	if (DUK_UNLIKELY(!(length >= DUK_LFUNC_LENGTH_MIN && length <= DUK_LFUNC_LENGTH_MAX))) {
22937 		goto api_error;
22938 	}
22939 	if (DUK_UNLIKELY(!(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX))) {
22940 		goto api_error;
22941 	}
22942 
22943 	lf_flags = DUK_LFUNC_FLAGS_PACK((duk_small_int_t) magic, (duk_small_uint_t) length, (duk_small_uint_t) nargs);
22944 	tv_slot = thr->valstack_top++;
22945 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_slot));
22946 	DUK_TVAL_SET_LIGHTFUNC(tv_slot, func, lf_flags);
22947 	DUK_ASSERT(tv_slot >= thr->valstack_bottom);
22948 	return (duk_idx_t) (tv_slot - thr->valstack_bottom);
22949 
22950  api_error:
22951 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
22952 	DUK_WO_NORETURN(return 0;);
22953 }
22954 
22955 #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)22956 DUK_INTERNAL duk_hbufobj *duk_push_bufobj_raw(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
22957 	duk_hbufobj *obj;
22958 	duk_tval *tv_slot;
22959 
22960 	DUK_ASSERT_API_ENTRY(thr);
22961 	DUK_ASSERT(prototype_bidx >= 0);
22962 
22963 	DUK__CHECK_SPACE();
22964 
22965 	obj = duk_hbufobj_alloc(thr, hobject_flags_and_class);
22966 	DUK_ASSERT(obj != NULL);
22967 
22968 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[prototype_bidx]);
22969 	DUK_HBUFOBJ_ASSERT_VALID(obj);
22970 
22971 	tv_slot = thr->valstack_top;
22972 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22973 	DUK_HOBJECT_INCREF(thr, obj);
22974 	thr->valstack_top++;
22975 
22976 	return obj;
22977 }
22978 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22979 
22980 /* XXX: There's quite a bit of overlap with buffer creation handling in
22981  * duk_bi_buffer.c.  Look for overlap and refactor.
22982  */
22983 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22984 #define DUK__PACK_ARGS(classnum,protobidx,elemtype,elemshift,istypedarray) \
22985 	(((classnum) << 24) | ((protobidx) << 16) | ((elemtype) << 8) | ((elemshift) << 4) | (istypedarray))
22986 
22987 static const duk_uint32_t duk__bufobj_flags_lookup[] = {
22988 	/* Node.js Buffers are Uint8Array instances which inherit from Buffer.prototype. */
22989 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_ARRAYBUFFER,       DUK_BIDX_ARRAYBUFFER_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_ARRAYBUFFER */
22990 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY,        DUK_BIDX_NODEJS_BUFFER_PROTOTYPE,     DUK_HBUFOBJ_ELEM_UINT8,        0, 1),  /* DUK_BUFOBJ_NODEJS_BUFFER */
22991 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_DATAVIEW,          DUK_BIDX_DATAVIEW_PROTOTYPE,          DUK_HBUFOBJ_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_DATAVIEW */
22992 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT8ARRAY,         DUK_BIDX_INT8ARRAY_PROTOTYPE,         DUK_HBUFOBJ_ELEM_INT8,         0, 1),  /* DUK_BUFOBJ_INT8ARRAY */
22993 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY,        DUK_BIDX_UINT8ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_UINT8,        0, 1),  /* DUK_BUFOBJ_UINT8ARRAY */
22994 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY, DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT8CLAMPED, 0, 1),  /* DUK_BUFOBJ_UINT8CLAMPEDARRAY */
22995 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT16ARRAY,        DUK_BIDX_INT16ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_INT16,        1, 1),  /* DUK_BUFOBJ_INT16ARRAY */
22996 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT16ARRAY,       DUK_BIDX_UINT16ARRAY_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT16,       1, 1),  /* DUK_BUFOBJ_UINT16ARRAY */
22997 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT32ARRAY,        DUK_BIDX_INT32ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_INT32,        2, 1),  /* DUK_BUFOBJ_INT32ARRAY */
22998 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT32ARRAY,       DUK_BIDX_UINT32ARRAY_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT32,       2, 1),  /* DUK_BUFOBJ_UINT32ARRAY */
22999 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT32ARRAY,      DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,      DUK_HBUFOBJ_ELEM_FLOAT32,      2, 1),  /* DUK_BUFOBJ_FLOAT32ARRAY */
23000 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT64ARRAY,      DUK_BIDX_FLOAT64ARRAY_PROTOTYPE,      DUK_HBUFOBJ_ELEM_FLOAT64,      3, 1)   /* DUK_BUFOBJ_FLOAT64ARRAY */
23001 };
23002 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23003 
23004 #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)23005 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) {
23006 	duk_hbufobj *h_bufobj;
23007 	duk_hbuffer *h_val;
23008 	duk_hobject *h_arraybuf;
23009 	duk_uint32_t tmp;
23010 	duk_uint_t classnum;
23011 	duk_uint_t protobidx;
23012 	duk_uint_t lookupidx;
23013 	duk_uint_t uint_offset, uint_length, uint_added;
23014 
23015 	DUK_ASSERT_API_ENTRY(thr);
23016 
23017 	/* The underlying types for offset/length in duk_hbufobj is
23018 	 * duk_uint_t; make sure argument values fit.
23019 	 */
23020 	uint_offset = (duk_uint_t) byte_offset;
23021 	uint_length = (duk_uint_t) byte_length;
23022 	if (sizeof(duk_size_t) != sizeof(duk_uint_t)) {
23023 		if (DUK_UNLIKELY((duk_size_t) uint_offset != byte_offset || (duk_size_t) uint_length != byte_length)) {
23024 			goto range_error;
23025 		}
23026 	}
23027 
23028 	DUK_ASSERT_DISABLE(flags >= 0);  /* flags is unsigned */
23029 	lookupidx = flags;
23030 	if (DUK_UNLIKELY(lookupidx >= sizeof(duk__bufobj_flags_lookup) / sizeof(duk_uint32_t))) {
23031 		goto arg_error;
23032 	}
23033 	tmp = duk__bufobj_flags_lookup[lookupidx];
23034 	classnum = tmp >> 24;
23035 	protobidx = (tmp >> 16) & 0xff;
23036 
23037 	h_arraybuf = duk_get_hobject(thr, idx_buffer);
23038 	if (h_arraybuf != NULL &&  /* argument is an object */
23039 	    flags != DUK_BUFOBJ_ARRAYBUFFER &&  /* creating a view */
23040 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_arraybuf) == DUK_HOBJECT_CLASS_ARRAYBUFFER  /* argument is ArrayBuffer */) {
23041 		duk_uint_t tmp_offset;
23042 
23043 		DUK_HBUFOBJ_ASSERT_VALID((duk_hbufobj *) h_arraybuf);
23044 		h_val = ((duk_hbufobj *) h_arraybuf)->buf;
23045 		if (DUK_UNLIKELY(h_val == NULL)) {
23046 			goto arg_error;
23047 		}
23048 
23049 		tmp_offset = uint_offset + ((duk_hbufobj *) h_arraybuf)->offset;
23050 		if (DUK_UNLIKELY(tmp_offset < uint_offset)) {
23051 			goto range_error;
23052 		}
23053 		uint_offset = tmp_offset;
23054 
23055 		/* Note intentional difference to new TypedArray(): we allow
23056 		 * caller to create an uncovered typed array (which is memory
23057 		 * safe); new TypedArray() rejects it.
23058 		 */
23059 	} else {
23060 		/* Handle unexpected object arguments here too, for nice error
23061 		 * messages.
23062 		 */
23063 		h_arraybuf = NULL;
23064 		h_val = duk_require_hbuffer(thr, idx_buffer);
23065 	}
23066 
23067 	/* Wrap check for offset+length. */
23068 	uint_added = uint_offset + uint_length;
23069 	if (DUK_UNLIKELY(uint_added < uint_offset)) {
23070 		goto range_error;
23071 	}
23072 	DUK_ASSERT(uint_added >= uint_offset && uint_added >= uint_length);
23073 
23074 	DUK_ASSERT(h_val != NULL);
23075 
23076 	h_bufobj = duk_push_bufobj_raw(thr,
23077 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
23078 	                               DUK_HOBJECT_FLAG_BUFOBJ |
23079 	                               DUK_HOBJECT_CLASS_AS_FLAGS(classnum),
23080 	                               (duk_small_int_t) protobidx);
23081 	DUK_ASSERT(h_bufobj != NULL);
23082 
23083 	h_bufobj->buf = h_val;
23084 	DUK_HBUFFER_INCREF(thr, h_val);
23085 	h_bufobj->buf_prop = h_arraybuf;
23086 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, h_arraybuf);
23087 	h_bufobj->offset = uint_offset;
23088 	h_bufobj->length = uint_length;
23089 	h_bufobj->shift = (tmp >> 4) & 0x0f;
23090 	h_bufobj->elem_type = (tmp >> 8) & 0xff;
23091 	h_bufobj->is_typedarray = tmp & 0x0f;
23092 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
23093 
23094 	/* TypedArray views need an automatic ArrayBuffer which must be
23095 	 * provided as .buffer property of the view.  The ArrayBuffer is
23096 	 * referenced via duk_hbufobj->buf_prop and an inherited .buffer
23097 	 * accessor returns it.  The ArrayBuffer is created lazily on first
23098 	 * access if necessary so we don't need to do anything more here.
23099 	 */
23100 	return;
23101 
23102  range_error:
23103 	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS);
23104 	DUK_WO_NORETURN(return;);
23105 
23106  arg_error:
23107 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_ARGS);
23108 	DUK_WO_NORETURN(return;);
23109 }
23110 #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)23111 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) {
23112 	DUK_ASSERT_API_ENTRY(thr);
23113 	DUK_UNREF(idx_buffer);
23114 	DUK_UNREF(byte_offset);
23115 	DUK_UNREF(byte_length);
23116 	DUK_UNREF(flags);
23117 	DUK_ERROR_UNSUPPORTED(thr);
23118 	DUK_WO_NORETURN(return;);
23119 }
23120 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23121 
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)23122 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) {
23123 	duk_hobject *proto;
23124 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
23125 	duk_small_uint_t augment_flags;
23126 #endif
23127 
23128 	DUK_ASSERT_API_ENTRY(thr);
23129 	DUK_ASSERT(thr != NULL);
23130 	DUK_UNREF(filename);
23131 	DUK_UNREF(line);
23132 
23133 	/* Error code also packs a tracedata related flag. */
23134 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
23135 	augment_flags = 0;
23136 	if (err_code & DUK_ERRCODE_FLAG_NOBLAME_FILELINE) {
23137 		augment_flags = DUK_AUGMENT_FLAG_NOBLAME_FILELINE;
23138 	}
23139 #endif
23140 	err_code = err_code & (~DUK_ERRCODE_FLAG_NOBLAME_FILELINE);
23141 
23142 	/* error gets its 'name' from the prototype */
23143 	proto = duk_error_prototype_from_code(thr, err_code);
23144 	(void) duk_push_object_helper_proto(thr,
23145 	                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
23146 	                                    DUK_HOBJECT_FLAG_FASTREFS |
23147 	                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR),
23148 	                                    proto);
23149 
23150 	/* ... and its 'message' from an instance property */
23151 	if (fmt) {
23152 		duk_push_vsprintf(thr, fmt, ap);
23153 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
23154 	} else {
23155 		/* If no explicit message given, put error code into message field
23156 		 * (as a number).  This is not fully in keeping with the ECMAScript
23157 		 * error model because messages are supposed to be strings (Error
23158 		 * constructors use ToString() on their argument).  However, it's
23159 		 * probably more useful than having a separate 'code' property.
23160 		 */
23161 		duk_push_int(thr, err_code);
23162 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
23163 	}
23164 
23165 	/* XXX: .code = err_code disabled, not sure if useful */
23166 
23167 	/* Creation time error augmentation */
23168 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
23169 	/* filename may be NULL in which case file/line is not recorded */
23170 	duk_err_augment_error_create(thr, thr, filename, line, augment_flags);  /* may throw an error */
23171 #endif
23172 
23173 	return duk_get_top_index_unsafe(thr);
23174 }
23175 
duk_push_error_object_raw(duk_hthread * thr,duk_errcode_t err_code,const char * filename,duk_int_t line,const char * fmt,...)23176 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, ...) {
23177 	va_list ap;
23178 	duk_idx_t ret;
23179 
23180 	DUK_ASSERT_API_ENTRY(thr);
23181 
23182 	va_start(ap, fmt);
23183 	ret = duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
23184 	va_end(ap);
23185 	return ret;
23186 }
23187 
23188 #if !defined(DUK_USE_VARIADIC_MACROS)
duk_push_error_object_stash(duk_hthread * thr,duk_errcode_t err_code,const char * fmt,...)23189 DUK_EXTERNAL duk_idx_t duk_push_error_object_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, ...) {
23190 	const char *filename = duk_api_global_filename;
23191 	duk_int_t line = duk_api_global_line;
23192 	va_list ap;
23193 	duk_idx_t ret;
23194 
23195 	DUK_ASSERT_API_ENTRY(thr);
23196 
23197 	duk_api_global_filename = NULL;
23198 	duk_api_global_line = 0;
23199 	va_start(ap, fmt);
23200 	ret = duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
23201 	va_end(ap);
23202 	return ret;
23203 }
23204 #endif  /* DUK_USE_VARIADIC_MACROS */
23205 
duk_push_buffer_raw(duk_hthread * thr,duk_size_t size,duk_small_uint_t flags)23206 DUK_EXTERNAL void *duk_push_buffer_raw(duk_hthread *thr, duk_size_t size, duk_small_uint_t flags) {
23207 	duk_tval *tv_slot;
23208 	duk_hbuffer *h;
23209 	void *buf_data;
23210 
23211 	DUK_ASSERT_API_ENTRY(thr);
23212 
23213 	DUK__CHECK_SPACE();
23214 
23215 	/* Check for maximum buffer length. */
23216 	if (DUK_UNLIKELY(size > DUK_HBUFFER_MAX_BYTELEN)) {
23217 		DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
23218 		DUK_WO_NORETURN(return NULL;);
23219 	}
23220 
23221 	h = duk_hbuffer_alloc(thr->heap, size, flags, &buf_data);
23222 	if (DUK_UNLIKELY(h == NULL)) {
23223 		DUK_ERROR_ALLOC_FAILED(thr);
23224 		DUK_WO_NORETURN(return NULL;);
23225 	}
23226 
23227 	tv_slot = thr->valstack_top;
23228 	DUK_TVAL_SET_BUFFER(tv_slot, h);
23229 	DUK_HBUFFER_INCREF(thr, h);
23230 	thr->valstack_top++;
23231 
23232 	return (void *) buf_data;
23233 }
23234 
duk_push_fixed_buffer_nozero(duk_hthread * thr,duk_size_t len)23235 DUK_INTERNAL void *duk_push_fixed_buffer_nozero(duk_hthread *thr, duk_size_t len) {
23236 	DUK_ASSERT_API_ENTRY(thr);
23237 	return duk_push_buffer_raw(thr, len, DUK_BUF_FLAG_NOZERO);
23238 }
23239 
duk_push_fixed_buffer_zero(duk_hthread * thr,duk_size_t len)23240 DUK_INTERNAL void *duk_push_fixed_buffer_zero(duk_hthread *thr, duk_size_t len) {
23241 	void *ptr;
23242 
23243 	DUK_ASSERT_API_ENTRY(thr);
23244 
23245 	ptr = duk_push_buffer_raw(thr, len, 0);
23246 	DUK_ASSERT(ptr != NULL);
23247 #if !defined(DUK_USE_ZERO_BUFFER_DATA)
23248 	/* ES2015 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
23249 	 * is not set.
23250 	 */
23251 	duk_memzero((void *) ptr, (size_t) len);
23252 #endif
23253 	return ptr;
23254 }
23255 
23256 #if defined(DUK_USE_ES6_PROXY)
duk_push_proxy(duk_hthread * thr,duk_uint_t proxy_flags)23257 DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags) {
23258 	duk_hobject *h_target;
23259 	duk_hobject *h_handler;
23260 	duk_hproxy *h_proxy;
23261 	duk_tval *tv_slot;
23262 	duk_uint_t flags;
23263 
23264 	DUK_ASSERT_API_ENTRY(thr);
23265 	DUK_UNREF(proxy_flags);
23266 
23267 	/* DUK__CHECK_SPACE() unnecessary because the Proxy is written to
23268 	 * value stack in-place.
23269 	 */
23270 #if 0
23271 	DUK__CHECK_SPACE();
23272 #endif
23273 
23274 	/* Reject a proxy object as the target because it would need
23275 	 * special handling in property lookups.  (ES2015 has no such
23276 	 * restriction.)
23277 	 */
23278 	h_target = duk_require_hobject_promote_mask(thr, -2, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
23279 	DUK_ASSERT(h_target != NULL);
23280 	if (DUK_HOBJECT_IS_PROXY(h_target)) {
23281 		goto fail_args;
23282 	}
23283 
23284 	/* Reject a proxy object as the handler because it would cause
23285 	 * potentially unbounded recursion.  (ES2015 has no such
23286 	 * restriction.)
23287 	 *
23288 	 * There's little practical reason to use a lightfunc or a plain
23289 	 * buffer as the handler table: one could only provide traps via
23290 	 * their prototype objects (Function.prototype and ArrayBuffer.prototype).
23291 	 * Even so, as lightfuncs and plain buffers mimic their object
23292 	 * counterparts, they're promoted and accepted here.
23293 	 */
23294 	h_handler = duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
23295 	DUK_ASSERT(h_handler != NULL);
23296 	if (DUK_HOBJECT_IS_PROXY(h_handler)) {
23297 		goto fail_args;
23298 	}
23299 
23300 	/* XXX: Proxy object currently has no prototype, so ToPrimitive()
23301 	 * coercion fails which is a bit confusing.
23302 	 */
23303 
23304 	/* CALLABLE and CONSTRUCTABLE flags are copied from the (initial)
23305 	 * target, see ES2015 Sections 9.5.15 and 9.5.13.
23306 	 */
23307 	flags = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h_target) &
23308 	        (DUK_HOBJECT_FLAG_CALLABLE | DUK_HOBJECT_FLAG_CONSTRUCTABLE);
23309 	flags |= DUK_HOBJECT_FLAG_EXTENSIBLE |
23310 	         DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ;
23311 	if (flags & DUK_HOBJECT_FLAG_CALLABLE) {
23312 		flags |= DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION) |
23313 		         DUK_HOBJECT_FLAG_SPECIAL_CALL;
23314 	} else {
23315 		flags |= DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT);
23316 	}
23317 
23318 	h_proxy = duk_hproxy_alloc(thr, flags);
23319 	DUK_ASSERT(h_proxy != NULL);
23320 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_proxy) == NULL);
23321 
23322 	/* Initialize Proxy target and handler references; avoid INCREF
23323 	 * by stealing the value stack refcounts via direct value stack
23324 	 * manipulation.  INCREF is needed for the Proxy itself however.
23325 	 */
23326 	DUK_ASSERT(h_target != NULL);
23327 	h_proxy->target = h_target;
23328 	DUK_ASSERT(h_handler != NULL);
23329 	h_proxy->handler = h_handler;
23330 	DUK_HPROXY_ASSERT_VALID(h_proxy);
23331 
23332 	DUK_ASSERT(duk_get_hobject(thr, -2) == h_target);
23333 	DUK_ASSERT(duk_get_hobject(thr, -1) == h_handler);
23334 	tv_slot = thr->valstack_top - 2;
23335 	DUK_ASSERT(tv_slot >= thr->valstack_bottom);
23336 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) h_proxy);
23337 	DUK_HOBJECT_INCREF(thr, (duk_hobject *) h_proxy);
23338 	tv_slot++;
23339 	DUK_TVAL_SET_UNDEFINED(tv_slot);  /* [ ... target handler ] -> [ ... proxy undefined ] */
23340 	thr->valstack_top = tv_slot;      /* -> [ ... proxy ] */
23341 
23342 	DUK_DD(DUK_DDPRINT("created Proxy: %!iT", duk_get_tval(thr, -1)));
23343 
23344 	return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom - 1);
23345 
23346  fail_args:
23347 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
23348 	DUK_WO_NORETURN(return 0;);
23349 }
23350 #else  /* DUK_USE_ES6_PROXY */
duk_push_proxy(duk_hthread * thr,duk_uint_t proxy_flags)23351 DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags) {
23352 	DUK_ASSERT_API_ENTRY(thr);
23353 	DUK_UNREF(proxy_flags);
23354 	DUK_ERROR_UNSUPPORTED(thr);
23355 	DUK_WO_NORETURN(return 0;);
23356 }
23357 #endif  /* DUK_USE_ES6_PROXY */
23358 
23359 #if defined(DUK_USE_ASSERTIONS)
duk__validate_push_heapptr(duk_hthread * thr,void * ptr)23360 DUK_LOCAL void duk__validate_push_heapptr(duk_hthread *thr, void *ptr) {
23361 	duk_heaphdr *h;
23362 	duk_heaphdr *curr;
23363 	duk_bool_t found = 0;
23364 
23365 	h = (duk_heaphdr *) ptr;
23366 	if (h == NULL) {
23367 		/* Allowed. */
23368 		return;
23369 	}
23370 	DUK_ASSERT(h != NULL);
23371 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
23372 
23373 	/* One particular problem case is where an object has been
23374 	 * queued for finalization but the finalizer hasn't yet been
23375 	 * executed.
23376 	 *
23377 	 * Corner case: we're running in a finalizer for object X, and
23378 	 * user code calls duk_push_heapptr() for X itself.  In this
23379 	 * case X will be in finalize_list, and we can detect the case
23380 	 * by seeing that X's FINALIZED flag is set (which is done before
23381 	 * the finalizer starts executing).
23382 	 */
23383 #if defined(DUK_USE_FINALIZER_SUPPORT)
23384 	for (curr = thr->heap->finalize_list;
23385 	     curr != NULL;
23386 	     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
23387 		/* FINALIZABLE is set for all objects on finalize_list
23388 		 * except for an object being finalized right now.  So
23389 		 * can't assert here.
23390 		 */
23391 #if 0
23392 		DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(curr));
23393 #endif
23394 
23395 		if (curr == h) {
23396 			if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h)) {
23397 				/* Object is currently being finalized. */
23398 				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23399 				found = 1;
23400 			} else {
23401 				/* Not being finalized but on finalize_list,
23402 				 * allowed since Duktape 2.1.
23403 				 */
23404 				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23405 				found = 1;
23406 			}
23407 		}
23408 	}
23409 #endif  /* DUK_USE_FINALIZER_SUPPORT */
23410 
23411 #if defined(DUK_USE_REFERENCE_COUNTING)
23412 	/* Because refzero_list is now processed to completion inline with
23413 	 * no side effects, it's always empty here.
23414 	 */
23415 	DUK_ASSERT(thr->heap->refzero_list == NULL);
23416 #endif
23417 
23418 	/* If not present in finalize_list (or refzero_list), it
23419 	 * must be either in heap_allocated or the string table.
23420 	 */
23421 	if (DUK_HEAPHDR_IS_STRING(h)) {
23422 		duk_uint32_t i;
23423 		duk_hstring *str;
23424 		duk_heap *heap = thr->heap;
23425 
23426 		DUK_ASSERT(found == 0);
23427 		for (i = 0; i < heap->st_size; i++) {
23428 #if defined(DUK_USE_STRTAB_PTRCOMP)
23429 			str = DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, heap->strtable16[i]);
23430 #else
23431 			str = heap->strtable[i];
23432 #endif
23433 			while (str != NULL) {
23434 				if (str == (duk_hstring *) h) {
23435 					DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23436 					found = 1;
23437 					break;
23438 				}
23439 				str = str->hdr.h_next;
23440 			}
23441 		}
23442 		DUK_ASSERT(found != 0);
23443 	} else {
23444 		for (curr = thr->heap->heap_allocated;
23445 		     curr != NULL;
23446 		     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
23447 			if (curr == h) {
23448 				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23449 				found = 1;
23450 			}
23451 		}
23452 		DUK_ASSERT(found != 0);
23453 	}
23454 }
23455 #endif  /* DUK_USE_ASSERTIONS */
23456 
duk_push_heapptr(duk_hthread * thr,void * ptr)23457 DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_hthread *thr, void *ptr) {
23458 	duk_idx_t ret;
23459 	duk_tval *tv;
23460 
23461 	DUK_ASSERT_API_ENTRY(thr);
23462 
23463 	/* Reviving an object using a heap pointer is a dangerous API
23464 	 * operation: if the application doesn't guarantee that the
23465 	 * pointer target is always reachable, difficult-to-diagnose
23466 	 * problems may ensue.  Try to validate the 'ptr' argument to
23467 	 * the extent possible.
23468 	 */
23469 
23470 #if defined(DUK_USE_ASSERTIONS)
23471 	duk__validate_push_heapptr(thr, ptr);
23472 #endif
23473 
23474 	DUK__CHECK_SPACE();
23475 
23476 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
23477 	tv = thr->valstack_top++;
23478 
23479 	if (ptr == NULL) {
23480 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
23481 		return ret;
23482 	}
23483 
23484 	DUK_HEAPHDR_ASSERT_VALID((duk_heaphdr *) ptr);
23485 
23486 	/* If the argument is on finalize_list it has technically been
23487 	 * unreachable before duk_push_heapptr() but it's still safe to
23488 	 * push it.  Starting from Duktape 2.1 allow application code to
23489 	 * do so.  There are two main cases:
23490 	 *
23491 	 *   (1) The object is on the finalize_list and we're called by
23492 	 *       the finalizer for the object being finalized.  In this
23493 	 *       case do nothing: finalize_list handling will deal with
23494 	 *       the object queueing.  This is detected by the object not
23495 	 *       having a FINALIZABLE flag despite being on the finalize_list;
23496 	 *       the flag is cleared for the object being finalized only.
23497 	 *
23498 	 *   (2) The object is on the finalize_list but is not currently
23499 	 *       being processed.  In this case the object can be queued
23500 	 *       back to heap_allocated with a few flags cleared, in effect
23501 	 *       cancelling the finalizer.
23502 	 */
23503 	if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) ptr))) {
23504 		duk_heaphdr *curr;
23505 
23506 		DUK_D(DUK_DPRINT("duk_push_heapptr() with a pointer on finalize_list, autorescue"));
23507 
23508 		curr = (duk_heaphdr *) ptr;
23509 		DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
23510 
23511 		/* Because FINALIZED is set prior to finalizer call, it will
23512 		 * be set for the object being currently finalized, but not
23513 		 * for other objects on finalize_list.
23514 		 */
23515 		DUK_HEAPHDR_CLEAR_FINALIZED(curr);
23516 
23517 		/* Dequeue object from finalize_list and queue it back to
23518 		 * heap_allocated.
23519 		 */
23520 #if defined(DUK_USE_REFERENCE_COUNTING)
23521 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);  /* Preincremented on finalize_list insert. */
23522 		DUK_HEAPHDR_PREDEC_REFCOUNT(curr);
23523 #endif
23524 		DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(thr->heap, curr);
23525 		DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(thr->heap, curr);
23526 
23527 		/* Continue with the rest. */
23528 	}
23529 
23530 	switch (DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr)) {
23531 	case DUK_HTYPE_STRING:
23532 		DUK_TVAL_SET_STRING(tv, (duk_hstring *) ptr);
23533 		break;
23534 	case DUK_HTYPE_OBJECT:
23535 		DUK_TVAL_SET_OBJECT(tv, (duk_hobject *) ptr);
23536 		break;
23537 	default:
23538 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr) == DUK_HTYPE_BUFFER);
23539 		DUK_TVAL_SET_BUFFER(tv, (duk_hbuffer *) ptr);
23540 		break;
23541 	}
23542 
23543 	DUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) ptr);
23544 
23545 	return ret;
23546 }
23547 
23548 /* Push object with no prototype, i.e. a "bare" object. */
duk_push_bare_object(duk_hthread * thr)23549 DUK_EXTERNAL duk_idx_t duk_push_bare_object(duk_hthread *thr) {
23550 	DUK_ASSERT_API_ENTRY(thr);
23551 
23552 	(void) duk_push_object_helper(thr,
23553 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
23554 	                              DUK_HOBJECT_FLAG_FASTREFS |
23555 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
23556 	                              -1);  /* no prototype */
23557 	return duk_get_top_index_unsafe(thr);
23558 }
23559 
duk_push_hstring(duk_hthread * thr,duk_hstring * h)23560 DUK_INTERNAL void duk_push_hstring(duk_hthread *thr, duk_hstring *h) {
23561 	duk_tval tv;
23562 
23563 	DUK_ASSERT_API_ENTRY(thr);
23564 	DUK_ASSERT(h != NULL);
23565 
23566 	DUK_TVAL_SET_STRING(&tv, h);
23567 	duk_push_tval(thr, &tv);
23568 }
23569 
duk_push_hstring_stridx(duk_hthread * thr,duk_small_uint_t stridx)23570 DUK_INTERNAL void duk_push_hstring_stridx(duk_hthread *thr, duk_small_uint_t stridx) {
23571 	DUK_ASSERT_API_ENTRY(thr);
23572 	DUK_ASSERT_STRIDX_VALID(stridx);
23573 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
23574 }
23575 
duk_push_hstring_empty(duk_hthread * thr)23576 DUK_INTERNAL void duk_push_hstring_empty(duk_hthread *thr) {
23577 	DUK_ASSERT_API_ENTRY(thr);
23578 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, DUK_STRIDX_EMPTY_STRING));
23579 }
23580 
duk_push_hobject(duk_hthread * thr,duk_hobject * h)23581 DUK_INTERNAL void duk_push_hobject(duk_hthread *thr, duk_hobject *h) {
23582 	duk_tval tv;
23583 
23584 	DUK_ASSERT_API_ENTRY(thr);
23585 	DUK_ASSERT(h != NULL);
23586 
23587 	DUK_TVAL_SET_OBJECT(&tv, h);
23588 	duk_push_tval(thr, &tv);
23589 }
23590 
duk_push_hbuffer(duk_hthread * thr,duk_hbuffer * h)23591 DUK_INTERNAL void duk_push_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
23592 	duk_tval tv;
23593 
23594 	DUK_ASSERT_API_ENTRY(thr);
23595 	DUK_ASSERT(h != NULL);
23596 
23597 	DUK_TVAL_SET_BUFFER(&tv, h);
23598 	duk_push_tval(thr, &tv);
23599 }
23600 
duk_push_hobject_bidx(duk_hthread * thr,duk_small_int_t builtin_idx)23601 DUK_INTERNAL void duk_push_hobject_bidx(duk_hthread *thr, duk_small_int_t builtin_idx) {
23602 	DUK_ASSERT_API_ENTRY(thr);
23603 	DUK_ASSERT(builtin_idx >= 0 && builtin_idx < DUK_NUM_BUILTINS);
23604 	DUK_ASSERT(thr->builtins[builtin_idx] != NULL);
23605 
23606 	duk_push_hobject(thr, thr->builtins[builtin_idx]);
23607 }
23608 
23609 /*
23610  *  Poppers
23611  */
23612 
duk__pop_n_unsafe_raw(duk_hthread * thr,duk_idx_t count)23613 DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_n_unsafe_raw(duk_hthread *thr, duk_idx_t count) {
23614 	duk_tval *tv;
23615 #if defined(DUK_USE_REFERENCE_COUNTING)
23616 	duk_tval *tv_end;
23617 #endif
23618 
23619 	DUK_CTX_ASSERT_VALID(thr);
23620 	DUK_ASSERT(count >= 0);
23621 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) count);
23622 
23623 #if defined(DUK_USE_REFERENCE_COUNTING)
23624 	tv = thr->valstack_top;
23625 	tv_end = tv - count;
23626 	while (tv != tv_end) {
23627 		tv--;
23628 		DUK_ASSERT(tv >= thr->valstack_bottom);
23629 		DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
23630 	}
23631 	thr->valstack_top = tv;
23632 	DUK_REFZERO_CHECK_FAST(thr);
23633 #else
23634 	tv = thr->valstack_top;
23635 	while (count > 0) {
23636 		count--;
23637 		tv--;
23638 		DUK_ASSERT(tv >= thr->valstack_bottom);
23639 		DUK_TVAL_SET_UNDEFINED(tv);
23640 	}
23641 	thr->valstack_top = tv;
23642 #endif
23643 
23644 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23645 }
23646 
duk_pop_n(duk_hthread * thr,duk_idx_t count)23647 DUK_EXTERNAL void duk_pop_n(duk_hthread *thr, duk_idx_t count) {
23648 	DUK_ASSERT_API_ENTRY(thr);
23649 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23650 
23651 	if (DUK_UNLIKELY((duk_uidx_t) (thr->valstack_top - thr->valstack_bottom) < (duk_uidx_t) count)) {
23652 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
23653 		DUK_WO_NORETURN(return;);
23654 	}
23655 	DUK_ASSERT(count >= 0);
23656 
23657 	duk__pop_n_unsafe_raw(thr, count);
23658 }
23659 
23660 #if defined(DUK_USE_PREFER_SIZE)
duk_pop_n_unsafe(duk_hthread * thr,duk_idx_t count)23661 DUK_INTERNAL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count) {
23662 	DUK_ASSERT_API_ENTRY(thr);
23663 	duk_pop_n(thr, count);
23664 }
23665 #else  /* DUK_USE_PREFER_SIZE */
duk_pop_n_unsafe(duk_hthread * thr,duk_idx_t count)23666 DUK_INTERNAL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count) {
23667 	DUK_ASSERT_API_ENTRY(thr);
23668 	duk__pop_n_unsafe_raw(thr, count);
23669 }
23670 #endif  /* DUK_USE_PREFER_SIZE */
23671 
23672 /* Pop N elements without DECREF (in effect "stealing" any actual refcounts). */
23673 #if defined(DUK_USE_REFERENCE_COUNTING)
duk_pop_n_nodecref_unsafe(duk_hthread * thr,duk_idx_t count)23674 DUK_INTERNAL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count) {
23675 	duk_tval *tv;
23676 
23677 	DUK_ASSERT_API_ENTRY(thr);
23678 	DUK_ASSERT(count >= 0);
23679 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23680 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) count);
23681 
23682 	tv = thr->valstack_top;
23683 	while (count > 0) {
23684 		count--;
23685 		tv--;
23686 		DUK_ASSERT(tv >= thr->valstack_bottom);
23687 		DUK_TVAL_SET_UNDEFINED(tv);
23688 	}
23689 	thr->valstack_top = tv;
23690 
23691 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23692 }
23693 #else  /* DUK_USE_REFERENCE_COUNTING */
duk_pop_n_nodecref_unsafe(duk_hthread * thr,duk_idx_t count)23694 DUK_INTERNAL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count) {
23695 	DUK_ASSERT_API_ENTRY(thr);
23696 	duk_pop_n_unsafe(thr, count);
23697 }
23698 #endif  /* DUK_USE_REFERENCE_COUNTING */
23699 
23700 /* Popping one element is called so often that when footprint is not an issue,
23701  * compile a specialized function for it.
23702  */
23703 #if defined(DUK_USE_PREFER_SIZE)
duk_pop(duk_hthread * thr)23704 DUK_EXTERNAL void duk_pop(duk_hthread *thr) {
23705 	DUK_ASSERT_API_ENTRY(thr);
23706 	duk_pop_n(thr, 1);
23707 }
duk_pop_unsafe(duk_hthread * thr)23708 DUK_INTERNAL void duk_pop_unsafe(duk_hthread *thr) {
23709 	DUK_ASSERT_API_ENTRY(thr);
23710 	duk_pop_n_unsafe(thr, 1);
23711 }
duk_pop_nodecref_unsafe(duk_hthread * thr)23712 DUK_INTERNAL void duk_pop_nodecref_unsafe(duk_hthread *thr) {
23713 	DUK_ASSERT_API_ENTRY(thr);
23714 	duk_pop_n_nodecref_unsafe(thr, 1);
23715 }
23716 #else  /* DUK_USE_PREFER_SIZE */
duk__pop_unsafe_raw(duk_hthread * thr)23717 DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_unsafe_raw(duk_hthread *thr) {
23718 	duk_tval *tv;
23719 
23720 	DUK_CTX_ASSERT_VALID(thr);
23721 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
23722 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23723 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);
23724 
23725 	tv = --thr->valstack_top;
23726 	DUK_ASSERT(tv >= thr->valstack_bottom);
23727 #if defined(DUK_USE_REFERENCE_COUNTING)
23728 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
23729 #else
23730 	DUK_TVAL_SET_UNDEFINED(tv);
23731 #endif
23732 
23733 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23734 }
duk_pop(duk_hthread * thr)23735 DUK_EXTERNAL void duk_pop(duk_hthread *thr) {
23736 	DUK_ASSERT_API_ENTRY(thr);
23737 
23738 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23739 	if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
23740 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
23741 		DUK_WO_NORETURN(return;);
23742 	}
23743 
23744 	duk__pop_unsafe_raw(thr);
23745 }
duk_pop_unsafe(duk_hthread * thr)23746 DUK_INTERNAL void duk_pop_unsafe(duk_hthread *thr) {
23747 	DUK_ASSERT_API_ENTRY(thr);
23748 	duk__pop_unsafe_raw(thr);
23749 }
duk_pop_nodecref_unsafe(duk_hthread * thr)23750 DUK_INTERNAL void duk_pop_nodecref_unsafe(duk_hthread *thr) {
23751 	duk_tval *tv;
23752 
23753 	DUK_ASSERT_API_ENTRY(thr);
23754 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
23755 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23756 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);
23757 
23758 	tv = --thr->valstack_top;
23759 	DUK_ASSERT(tv >= thr->valstack_bottom);
23760 	DUK_TVAL_SET_UNDEFINED(tv);
23761 
23762 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23763 }
23764 #endif  /* !DUK_USE_PREFER_SIZE */
23765 
23766 #if defined(DUK_USE_PREFER_SIZE)
duk_pop_undefined(duk_hthread * thr)23767 DUK_INTERNAL void duk_pop_undefined(duk_hthread *thr) {
23768 	DUK_ASSERT_API_ENTRY(thr);
23769 	duk_pop_nodecref_unsafe(thr);
23770 }
23771 #else  /* DUK_USE_PREFER_SIZE */
duk_pop_undefined(duk_hthread * thr)23772 DUK_INTERNAL void duk_pop_undefined(duk_hthread *thr) {
23773 	DUK_ASSERT_API_ENTRY(thr);
23774 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
23775 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23776 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);
23777 
23778 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
23779 	thr->valstack_top--;
23780 
23781 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23782 }
23783 #endif  /* !DUK_USE_PREFER_SIZE */
23784 
23785 #if defined(DUK_USE_PREFER_SIZE)
duk_pop_2(duk_hthread * thr)23786 DUK_EXTERNAL void duk_pop_2(duk_hthread *thr) {
23787 	DUK_ASSERT_API_ENTRY(thr);
23788 	duk_pop_n(thr, 2);
23789 }
duk_pop_2_unsafe(duk_hthread * thr)23790 DUK_INTERNAL void duk_pop_2_unsafe(duk_hthread *thr) {
23791 	DUK_ASSERT_API_ENTRY(thr);
23792 	duk_pop_n_unsafe(thr, 2);
23793 }
duk_pop_2_nodecref_unsafe(duk_hthread * thr)23794 DUK_INTERNAL void duk_pop_2_nodecref_unsafe(duk_hthread *thr) {
23795 	DUK_ASSERT_API_ENTRY(thr);
23796 	duk_pop_n_nodecref_unsafe(thr, 2);
23797 }
23798 #else
duk__pop_2_unsafe_raw(duk_hthread * thr)23799 DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_2_unsafe_raw(duk_hthread *thr) {
23800 	duk_tval *tv;
23801 
23802 	DUK_CTX_ASSERT_VALID(thr);
23803 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
23804 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23805 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 2);
23806 
23807 	tv = --thr->valstack_top;
23808 	DUK_ASSERT(tv >= thr->valstack_bottom);
23809 #if defined(DUK_USE_REFERENCE_COUNTING)
23810 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
23811 #else
23812 	DUK_TVAL_SET_UNDEFINED(tv);
23813 #endif
23814 	tv = --thr->valstack_top;
23815 	DUK_ASSERT(tv >= thr->valstack_bottom);
23816 #if defined(DUK_USE_REFERENCE_COUNTING)
23817 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
23818 #else
23819 	DUK_TVAL_SET_UNDEFINED(tv);
23820 #endif
23821 
23822 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23823 }
duk_pop_2(duk_hthread * thr)23824 DUK_EXTERNAL void duk_pop_2(duk_hthread *thr) {
23825 	DUK_ASSERT_API_ENTRY(thr);
23826 
23827 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23828 	if (DUK_UNLIKELY(thr->valstack_top - 2 < thr->valstack_bottom)) {
23829 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
23830 		DUK_WO_NORETURN(return;);
23831 	}
23832 
23833 	duk__pop_2_unsafe_raw(thr);
23834 }
duk_pop_2_unsafe(duk_hthread * thr)23835 DUK_INTERNAL void duk_pop_2_unsafe(duk_hthread *thr) {
23836 	DUK_ASSERT_API_ENTRY(thr);
23837 	duk__pop_2_unsafe_raw(thr);
23838 }
duk_pop_2_nodecref_unsafe(duk_hthread * thr)23839 DUK_INTERNAL void duk_pop_2_nodecref_unsafe(duk_hthread *thr) {
23840 	DUK_ASSERT_API_ENTRY(thr);
23841 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
23842 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23843 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 2);
23844 
23845 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
23846 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 2));
23847 	thr->valstack_top -= 2;
23848 
23849 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23850 }
23851 #endif  /* !DUK_USE_PREFER_SIZE */
23852 
duk_pop_3(duk_hthread * thr)23853 DUK_EXTERNAL void duk_pop_3(duk_hthread *thr) {
23854 	DUK_ASSERT_API_ENTRY(thr);
23855 	duk_pop_n(thr, 3);
23856 }
23857 
duk_pop_3_unsafe(duk_hthread * thr)23858 DUK_INTERNAL void duk_pop_3_unsafe(duk_hthread *thr) {
23859 	DUK_ASSERT_API_ENTRY(thr);
23860 	duk_pop_n_unsafe(thr, 3);
23861 }
23862 
duk_pop_3_nodecref_unsafe(duk_hthread * thr)23863 DUK_INTERNAL void duk_pop_3_nodecref_unsafe(duk_hthread *thr) {
23864 	DUK_ASSERT_API_ENTRY(thr);
23865 	duk_pop_n_nodecref_unsafe(thr, 3);
23866 }
23867 
23868 /*
23869  *  Pack and unpack (pack value stack entries into an array and vice versa)
23870  */
23871 
23872 /* XXX: pack index range? array index offset? */
23873 /* XXX: need ability to pack into a bare array? */
duk_pack(duk_hthread * thr,duk_idx_t count)23874 DUK_INTERNAL void duk_pack(duk_hthread *thr, duk_idx_t count) {
23875 	duk_tval *tv_src;
23876 	duk_tval *tv_dst;
23877 	duk_tval *tv_curr;
23878 	duk_tval *tv_limit;
23879 	duk_idx_t top;
23880 
23881 	DUK_ASSERT_API_ENTRY(thr);
23882 
23883 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23884 	top = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
23885 	DUK_ASSERT(top >= 0);
23886 	if (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) top)) {
23887 		/* Also handles negative count. */
23888 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
23889 		DUK_WO_NORETURN(return;);
23890 	}
23891 	DUK_ASSERT(count >= 0);
23892 
23893 	/* Wrapping is controlled by the check above: value stack top can be
23894 	 * at most DUK_USE_VALSTACK_LIMIT which is low enough so that
23895 	 * multiplying with sizeof(duk_tval) won't wrap.
23896 	 */
23897 	DUK_ASSERT(count >= 0 && count <= (duk_idx_t) DUK_USE_VALSTACK_LIMIT);
23898 	DUK_ASSERT((duk_size_t) count <= DUK_SIZE_MAX / sizeof(duk_tval));  /* no wrapping */
23899 
23900 	tv_dst = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count);  /* XXX: uninitialized would be OK */
23901 	DUK_ASSERT(count == 0 || tv_dst != NULL);
23902 	DUK_ASSERT(!duk_is_bare_object(thr, -1));
23903 
23904 	/* Copy value stack values directly to the array part without
23905 	 * any refcount updates: net refcount changes are zero.
23906 	 */
23907 	tv_src = thr->valstack_top - count - 1;
23908 	duk_memcpy_unsafe((void *) tv_dst, (const void *) tv_src, (size_t) count * sizeof(duk_tval));
23909 
23910 	/* Overwrite result array to final value stack location and wipe
23911 	 * the rest; no refcount operations needed.
23912 	 */
23913 
23914 	tv_dst = tv_src;  /* when count == 0, same as tv_src (OK) */
23915 	tv_src = thr->valstack_top - 1;
23916 	DUK_TVAL_SET_TVAL(tv_dst, tv_src);
23917 
23918 	/* XXX: internal helper to wipe a value stack segment? */
23919 	tv_curr = tv_dst + 1;
23920 	tv_limit = thr->valstack_top;
23921 	while (tv_curr != tv_limit) {
23922 		/* Wipe policy: keep as 'undefined'. */
23923 		DUK_TVAL_SET_UNDEFINED(tv_curr);
23924 		tv_curr++;
23925 	}
23926 	thr->valstack_top = tv_dst + 1;
23927 }
23928 
duk_unpack_array_like(duk_hthread * thr,duk_idx_t idx)23929 DUK_INTERNAL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx) {
23930 	duk_tval *tv;
23931 
23932 	DUK_ASSERT_API_ENTRY(thr);
23933 
23934 	tv = duk_require_tval(thr, idx);
23935 	if (DUK_LIKELY(DUK_TVAL_IS_OBJECT(tv))) {
23936 		duk_hobject *h;
23937 		duk_uint32_t len;
23938 		duk_uint32_t i;
23939 
23940 		h = DUK_TVAL_GET_OBJECT(tv);
23941 		DUK_ASSERT(h != NULL);
23942 		DUK_UNREF(h);
23943 
23944 #if defined(DUK_USE_ARRAY_FASTPATH)  /* close enough */
23945 		if (DUK_LIKELY(DUK_HOBJECT_IS_ARRAY(h) &&
23946 		               ((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h))) {
23947 			duk_harray *h_arr;
23948 			duk_tval *tv_src;
23949 			duk_tval *tv_dst;
23950 
23951 			h_arr = (duk_harray *) h;
23952 			len = h_arr->length;
23953 			if (DUK_UNLIKELY(len >= 0x80000000UL)) {
23954 				goto fail_over_2g;
23955 			}
23956 			duk_require_stack(thr, (duk_idx_t) len);
23957 
23958 			/* The potential allocation in duk_require_stack() may
23959 			 * run a finalizer which modifies the argArray so that
23960 			 * e.g. becomes sparse.  So, we need to recheck that the
23961 			 * array didn't change size and that there's still a
23962 			 * valid backing array part.
23963 			 *
23964 			 * XXX: alternatively, could prevent finalizers for the
23965 			 * duration.
23966 			 */
23967 			if (DUK_UNLIKELY(len != h_arr->length ||
23968 			                 h_arr->length > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr))) {
23969 				goto skip_fast;
23970 			}
23971 
23972 			/* Main fast path: arguments array is almost always
23973 			 * an actual array (though it might also be an arguments
23974 			 * object).
23975 			 */
23976 
23977 			DUK_DDD(DUK_DDDPRINT("fast path for %ld elements", (long) h_arr->length));
23978 			tv_src = DUK_HOBJECT_A_GET_BASE(thr->heap, h);
23979 			tv_dst = thr->valstack_top;
23980 			while (len-- > 0) {
23981 				DUK_ASSERT(tv_dst < thr->valstack_end);
23982 				if (DUK_UNLIKELY(DUK_TVAL_IS_UNUSED(tv_src))) {
23983 					/* Gaps are very unlikely.  Skip over them,
23984 					 * without an ancestor lookup (technically
23985 					 * not compliant).
23986 					 */
23987 					DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_dst));  /* valstack policy */
23988 				} else {
23989 					DUK_TVAL_SET_TVAL(tv_dst, tv_src);
23990 					DUK_TVAL_INCREF(thr, tv_dst);
23991 				}
23992 				tv_src++;
23993 				tv_dst++;
23994 			}
23995 			DUK_ASSERT(tv_dst <= thr->valstack_end);
23996 			thr->valstack_top = tv_dst;
23997 			return (duk_idx_t) h_arr->length;
23998 		}
23999 	 skip_fast:
24000 #endif  /* DUK_USE_ARRAY_FASTPATH */
24001 
24002 		/* Slow path: actual lookups.  The initial 'length' lookup
24003 		 * decides the output length, regardless of side effects that
24004 		 * may resize or change the argArray while we read the
24005 		 * indices.
24006 		 */
24007 		idx = duk_normalize_index(thr, idx);
24008 		duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
24009 		len = duk_to_uint32(thr, -1);  /* ToUint32() coercion required */
24010 		if (DUK_UNLIKELY(len >= 0x80000000UL)) {
24011 			goto fail_over_2g;
24012 		}
24013 		duk_pop_unsafe(thr);
24014 		DUK_DDD(DUK_DDDPRINT("slow path for %ld elements", (long) len));
24015 
24016 		duk_require_stack(thr, (duk_idx_t) len);
24017 		for (i = 0; i < len; i++) {
24018 			duk_get_prop_index(thr, idx, (duk_uarridx_t) i);
24019 		}
24020 		return (duk_idx_t) len;
24021 	} else if (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv)) {
24022 		return 0;
24023 	}
24024 
24025 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
24026 	DUK_WO_NORETURN(return 0;);
24027 
24028  fail_over_2g:
24029 	DUK_ERROR_RANGE_INVALID_LENGTH(thr);
24030 	DUK_WO_NORETURN(return 0;);
24031 }
24032 
24033 /*
24034  *  Error throwing
24035  */
24036 
duk_throw_raw(duk_hthread * thr)24037 DUK_EXTERNAL void duk_throw_raw(duk_hthread *thr) {
24038 	duk_tval *tv_val;
24039 
24040 	DUK_ASSERT_API_ENTRY(thr);
24041 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
24042 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24043 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
24044 
24045 	if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
24046 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
24047 		DUK_WO_NORETURN(return;);
24048 	}
24049 
24050 	/* Errors are augmented when they are created, not when they are
24051 	 * thrown or re-thrown.  The current error handler, however, runs
24052 	 * just before an error is thrown.
24053 	 */
24054 
24055 	/* Sync so that augmentation sees up-to-date activations, NULL
24056 	 * thr->ptr_curr_pc so that it's not used if side effects occur
24057 	 * in augmentation or longjmp handling.
24058 	 */
24059 	duk_hthread_sync_and_null_currpc(thr);
24060 
24061 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
24062 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (before throw augment)", (duk_tval *) duk_get_tval(thr, -1)));
24063 	duk_err_augment_error_throw(thr);
24064 #endif
24065 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (after throw augment)", (duk_tval *) duk_get_tval(thr, -1)));
24066 
24067 	tv_val = DUK_GET_TVAL_NEGIDX(thr, -1);
24068 	duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, tv_val);
24069 #if defined(DUK_USE_DEBUGGER_SUPPORT)
24070 	duk_err_check_debugger_integration(thr);
24071 #endif
24072 
24073 	/* thr->heap->lj.jmpbuf_ptr is checked by duk_err_longjmp() so we don't
24074 	 * need to check that here.  If the value is NULL, a fatal error occurs
24075 	 * because we can't return.
24076 	 */
24077 
24078 	duk_err_longjmp(thr);
24079 	DUK_UNREACHABLE();
24080 }
24081 
duk_fatal_raw(duk_hthread * thr,const char * err_msg)24082 DUK_EXTERNAL void duk_fatal_raw(duk_hthread *thr, const char *err_msg) {
24083 	DUK_ASSERT_API_ENTRY(thr);
24084 	DUK_ASSERT(thr != NULL);
24085 	DUK_ASSERT(thr->heap != NULL);
24086 	DUK_ASSERT(thr->heap->fatal_func != NULL);
24087 
24088 	DUK_D(DUK_DPRINT("fatal error occurred: %s", err_msg ? err_msg : "NULL"));
24089 
24090 	/* fatal_func should be noreturn, but noreturn declarations on function
24091 	 * pointers has a very spotty support apparently so it's not currently
24092 	 * done.
24093 	 */
24094 	thr->heap->fatal_func(thr->heap->heap_udata, err_msg);
24095 
24096 	/* If the fatal handler returns, all bets are off.  It'd be nice to
24097 	 * print something here but since we don't want to depend on stdio,
24098 	 * there's no way to do so portably.
24099 	 */
24100 	DUK_D(DUK_DPRINT("fatal error handler returned, all bets are off!"));
24101 	for (;;) {
24102 		/* loop forever, don't return (function marked noreturn) */
24103 	}
24104 }
24105 
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)24106 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) {
24107 	DUK_ASSERT_API_ENTRY(thr);
24108 
24109 	duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
24110 	(void) duk_throw(thr);
24111 	DUK_WO_NORETURN(return;);
24112 }
24113 
duk_error_raw(duk_hthread * thr,duk_errcode_t err_code,const char * filename,duk_int_t line,const char * fmt,...)24114 DUK_EXTERNAL void duk_error_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
24115 	va_list ap;
24116 
24117 	DUK_ASSERT_API_ENTRY(thr);
24118 
24119 	va_start(ap, fmt);
24120 	duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
24121 	va_end(ap);
24122 	(void) duk_throw(thr);
24123 	DUK_WO_NORETURN(return;);
24124 }
24125 
24126 #if !defined(DUK_USE_VARIADIC_MACROS)
24127 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));
24128 
duk__throw_error_from_stash(duk_hthread * thr,duk_errcode_t err_code,const char * fmt,va_list ap)24129 DUK_LOCAL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, va_list ap) {
24130 	const char *filename;
24131 	duk_int_t line;
24132 
24133 	DUK_CTX_ASSERT_VALID(thr);
24134 
24135 	filename = duk_api_global_filename;
24136 	line = duk_api_global_line;
24137 	duk_api_global_filename = NULL;
24138 	duk_api_global_line = 0;
24139 
24140 	duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
24141 	(void) duk_throw(thr);
24142 	DUK_WO_NORETURN(return;);
24143 }
24144 
24145 #define DUK__ERROR_STASH_SHARED(code) do { \
24146 		va_list ap; \
24147 		va_start(ap, fmt); \
24148 		duk__throw_error_from_stash(thr, (code), fmt, ap); \
24149 		va_end(ap); \
24150 		DUK_WO_NORETURN(return 0;); \
24151 	} while (0)
24152 
duk_error_stash(duk_hthread * thr,duk_errcode_t err_code,const char * fmt,...)24153 DUK_EXTERNAL duk_ret_t duk_error_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, ...) {
24154 	DUK_ASSERT_API_ENTRY(thr);
24155 	DUK__ERROR_STASH_SHARED(err_code);
24156 }
duk_generic_error_stash(duk_hthread * thr,const char * fmt,...)24157 DUK_EXTERNAL duk_ret_t duk_generic_error_stash(duk_hthread *thr, const char *fmt, ...) {
24158 	DUK_ASSERT_API_ENTRY(thr);
24159 	DUK__ERROR_STASH_SHARED(DUK_ERR_ERROR);
24160 }
duk_eval_error_stash(duk_hthread * thr,const char * fmt,...)24161 DUK_EXTERNAL duk_ret_t duk_eval_error_stash(duk_hthread *thr, const char *fmt, ...) {
24162 	DUK_ASSERT_API_ENTRY(thr);
24163 	DUK__ERROR_STASH_SHARED(DUK_ERR_EVAL_ERROR);
24164 }
duk_range_error_stash(duk_hthread * thr,const char * fmt,...)24165 DUK_EXTERNAL duk_ret_t duk_range_error_stash(duk_hthread *thr, const char *fmt, ...) {
24166 	DUK_ASSERT_API_ENTRY(thr);
24167 	DUK__ERROR_STASH_SHARED(DUK_ERR_RANGE_ERROR);
24168 }
duk_reference_error_stash(duk_hthread * thr,const char * fmt,...)24169 DUK_EXTERNAL duk_ret_t duk_reference_error_stash(duk_hthread *thr, const char *fmt, ...) {
24170 	DUK_ASSERT_API_ENTRY(thr);
24171 	DUK__ERROR_STASH_SHARED(DUK_ERR_REFERENCE_ERROR);
24172 }
duk_syntax_error_stash(duk_hthread * thr,const char * fmt,...)24173 DUK_EXTERNAL duk_ret_t duk_syntax_error_stash(duk_hthread *thr, const char *fmt, ...) {
24174 	DUK_ASSERT_API_ENTRY(thr);
24175 	DUK__ERROR_STASH_SHARED(DUK_ERR_SYNTAX_ERROR);
24176 }
duk_type_error_stash(duk_hthread * thr,const char * fmt,...)24177 DUK_EXTERNAL duk_ret_t duk_type_error_stash(duk_hthread *thr, const char *fmt, ...) {
24178 	DUK_ASSERT_API_ENTRY(thr);
24179 	DUK__ERROR_STASH_SHARED(DUK_ERR_TYPE_ERROR);
24180 }
duk_uri_error_stash(duk_hthread * thr,const char * fmt,...)24181 DUK_EXTERNAL duk_ret_t duk_uri_error_stash(duk_hthread *thr, const char *fmt, ...) {
24182 	DUK_ASSERT_API_ENTRY(thr);
24183 	DUK__ERROR_STASH_SHARED(DUK_ERR_URI_ERROR);
24184 }
24185 #endif  /* DUK_USE_VARIADIC_MACROS */
24186 
24187 /*
24188  *  Comparison
24189  */
24190 
duk_equals(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24191 DUK_EXTERNAL duk_bool_t duk_equals(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24192 	duk_tval *tv1, *tv2;
24193 
24194 	DUK_ASSERT_API_ENTRY(thr);
24195 
24196 	tv1 = duk_get_tval(thr, idx1);
24197 	tv2 = duk_get_tval(thr, idx2);
24198 	if ((tv1 == NULL) || (tv2 == NULL)) {
24199 		return 0;
24200 	}
24201 
24202 	/* Coercion may be needed, the helper handles that by pushing the
24203 	 * tagged values to the stack.
24204 	 */
24205 	return duk_js_equals(thr, tv1, tv2);
24206 }
24207 
duk_strict_equals(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24208 DUK_EXTERNAL duk_bool_t duk_strict_equals(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24209 	duk_tval *tv1, *tv2;
24210 
24211 	DUK_ASSERT_API_ENTRY(thr);
24212 
24213 	tv1 = duk_get_tval(thr, idx1);
24214 	tv2 = duk_get_tval(thr, idx2);
24215 	if ((tv1 == NULL) || (tv2 == NULL)) {
24216 		return 0;
24217 	}
24218 
24219 	/* No coercions or other side effects, so safe */
24220 	return duk_js_strict_equals(tv1, tv2);
24221 }
24222 
duk_samevalue(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24223 DUK_EXTERNAL duk_bool_t duk_samevalue(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24224 	duk_tval *tv1, *tv2;
24225 
24226 	DUK_ASSERT_API_ENTRY(thr);
24227 
24228 	tv1 = duk_get_tval(thr, idx1);
24229 	tv2 = duk_get_tval(thr, idx2);
24230 	if ((tv1 == NULL) || (tv2 == NULL)) {
24231 		return 0;
24232 	}
24233 
24234 	/* No coercions or other side effects, so safe */
24235 	return duk_js_samevalue(tv1, tv2);
24236 }
24237 
24238 /*
24239  *  instanceof
24240  */
24241 
duk_instanceof(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24242 DUK_EXTERNAL duk_bool_t duk_instanceof(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24243 	duk_tval *tv1, *tv2;
24244 
24245 	DUK_ASSERT_API_ENTRY(thr);
24246 
24247 	/* Index validation is strict, which differs from duk_equals().
24248 	 * The strict behavior mimics how instanceof itself works, e.g.
24249 	 * it is a TypeError if rval is not a -callable- object.  It would
24250 	 * be somewhat inconsistent if rval would be allowed to be
24251 	 * non-existent without a TypeError.
24252 	 */
24253 	tv1 = duk_require_tval(thr, idx1);
24254 	DUK_ASSERT(tv1 != NULL);
24255 	tv2 = duk_require_tval(thr, idx2);
24256 	DUK_ASSERT(tv2 != NULL);
24257 
24258 	return duk_js_instanceof(thr, tv1, tv2);
24259 }
24260 
24261 /*
24262  *  Lightfunc
24263  */
24264 
duk_push_lightfunc_name_raw(duk_hthread * thr,duk_c_function func,duk_small_uint_t lf_flags)24265 DUK_INTERNAL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags) {
24266 	/* Lightfunc name, includes Duktape/C native function pointer, which
24267 	 * can often be used to locate the function from a symbol table.
24268 	 * The name also includes the 16-bit duk_tval flags field because it
24269 	 * includes the magic value.  Because a single native function often
24270 	 * provides different functionality depending on the magic value, it
24271 	 * seems reasonably to include it in the name.
24272 	 *
24273 	 * On the other hand, a complicated name increases string table
24274 	 * pressure in low memory environments (but only when function name
24275 	 * is accessed).
24276 	 */
24277 
24278 	DUK_ASSERT_API_ENTRY(thr);
24279 
24280 	duk_push_literal(thr, "light_");
24281 	duk_push_string_funcptr(thr, (duk_uint8_t *) &func, sizeof(func));
24282 	duk_push_sprintf(thr, "_%04x", (unsigned int) lf_flags);
24283 	duk_concat(thr, 3);
24284 }
24285 
duk_push_lightfunc_name(duk_hthread * thr,duk_tval * tv)24286 DUK_INTERNAL void duk_push_lightfunc_name(duk_hthread *thr, duk_tval *tv) {
24287 	duk_c_function func;
24288 	duk_small_uint_t lf_flags;
24289 
24290 	DUK_ASSERT_API_ENTRY(thr);
24291 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));
24292 
24293 	DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
24294 	duk_push_lightfunc_name_raw(thr, func, lf_flags);
24295 }
24296 
duk_push_lightfunc_tostring(duk_hthread * thr,duk_tval * tv)24297 DUK_INTERNAL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv) {
24298 	duk_c_function func;
24299 	duk_small_uint_t lf_flags;
24300 
24301 	DUK_ASSERT_API_ENTRY(thr);
24302 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));
24303 
24304 	DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);  /* read before 'tv' potentially invalidated */
24305 	duk_push_literal(thr, "function ");
24306 	duk_push_lightfunc_name_raw(thr, func, lf_flags);
24307 	duk_push_literal(thr, "() { [lightfunc code] }");
24308 	duk_concat(thr, 3);
24309 }
24310 
24311 /*
24312  *  Function pointers
24313  *
24314  *  Printing function pointers is non-portable, so we do that by hex printing
24315  *  bytes from memory.
24316  */
24317 
duk_push_string_funcptr(duk_hthread * thr,duk_uint8_t * ptr,duk_size_t sz)24318 DUK_INTERNAL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, duk_size_t sz) {
24319 	duk_uint8_t buf[32 * 2];
24320 	duk_uint8_t *p, *q;
24321 	duk_small_uint_t i;
24322 	duk_small_uint_t t;
24323 
24324 	DUK_ASSERT_API_ENTRY(thr);
24325 	DUK_ASSERT(sz <= 32);  /* sanity limit for function pointer size */
24326 
24327 	p = buf;
24328 #if defined(DUK_USE_INTEGER_LE)
24329 	q = ptr + sz;
24330 #else
24331 	q = ptr;
24332 #endif
24333 	for (i = 0; i < sz; i++) {
24334 #if defined(DUK_USE_INTEGER_LE)
24335 		t = *(--q);
24336 #else
24337 		t = *(q++);
24338 #endif
24339 		*p++ = duk_lc_digits[t >> 4];
24340 		*p++ = duk_lc_digits[t & 0x0f];
24341 	}
24342 
24343 	duk_push_lstring(thr, (const char *) buf, sz * 2);
24344 }
24345 
24346 /*
24347  *  Push readable string summarizing duk_tval.  The operation is side effect
24348  *  free and will only throw from internal errors (e.g. out of memory).
24349  *  This is used by e.g. property access code to summarize a key/base safely,
24350  *  and is not intended to be fast (but small and safe).
24351  */
24352 
24353 /* String limits for summary strings. */
24354 #define DUK__READABLE_SUMMARY_MAXCHARS 96  /* maximum supported by helper */
24355 #define DUK__READABLE_STRING_MAXCHARS  32  /* for strings/symbols */
24356 #define DUK__READABLE_ERRMSG_MAXCHARS  96  /* for error messages */
24357 
24358 /* String sanitizer which escapes ASCII control characters and a few other
24359  * ASCII characters, passes Unicode as is, and replaces invalid UTF-8 with
24360  * question marks.  No errors are thrown for any input string, except in out
24361  * of memory situations.
24362  */
duk__push_hstring_readable_unicode(duk_hthread * thr,duk_hstring * h_input,duk_small_uint_t maxchars)24363 DUK_LOCAL void duk__push_hstring_readable_unicode(duk_hthread *thr, duk_hstring *h_input, duk_small_uint_t maxchars) {
24364 	const duk_uint8_t *p, *p_start, *p_end;
24365 	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH * DUK__READABLE_SUMMARY_MAXCHARS +
24366 	                2 /*quotes*/ + 3 /*periods*/];
24367 	duk_uint8_t *q;
24368 	duk_ucodepoint_t cp;
24369 	duk_small_uint_t nchars;
24370 
24371 	DUK_CTX_ASSERT_VALID(thr);
24372 	DUK_ASSERT(h_input != NULL);
24373 	DUK_ASSERT(maxchars <= DUK__READABLE_SUMMARY_MAXCHARS);
24374 
24375 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
24376 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
24377 	p = p_start;
24378 	q = buf;
24379 
24380 	nchars = 0;
24381 	*q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
24382 	for (;;) {
24383 		if (p >= p_end) {
24384 			break;
24385 		}
24386 		if (nchars == maxchars) {
24387 			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
24388 			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
24389 			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
24390 			break;
24391 		}
24392 		if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
24393 			if (cp < 0x20 || cp == 0x7f || cp == DUK_ASC_SINGLEQUOTE || cp == DUK_ASC_BACKSLASH) {
24394 				DUK_ASSERT(DUK_UNICODE_MAX_XUTF8_LENGTH >= 4);  /* estimate is valid */
24395 				DUK_ASSERT((cp >> 4) <= 0x0f);
24396 				*q++ = (duk_uint8_t) DUK_ASC_BACKSLASH;
24397 				*q++ = (duk_uint8_t) DUK_ASC_LC_X;
24398 				*q++ = (duk_uint8_t) duk_lc_digits[cp >> 4];
24399 				*q++ = (duk_uint8_t) duk_lc_digits[cp & 0x0f];
24400 			} else {
24401 				q += duk_unicode_encode_xutf8(cp, q);
24402 			}
24403 		} else {
24404 			p++;  /* advance manually */
24405 			*q++ = (duk_uint8_t) DUK_ASC_QUESTION;
24406 		}
24407 		nchars++;
24408 	}
24409 	*q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
24410 
24411 	duk_push_lstring(thr, (const char *) buf, (duk_size_t) (q - buf));
24412 }
24413 
duk__push_string_tval_readable(duk_hthread * thr,duk_tval * tv,duk_bool_t error_aware)24414 DUK_LOCAL const char *duk__push_string_tval_readable(duk_hthread *thr, duk_tval *tv, duk_bool_t error_aware) {
24415 	DUK_CTX_ASSERT_VALID(thr);
24416 	/* 'tv' may be NULL */
24417 
24418 	if (tv == NULL) {
24419 		duk_push_literal(thr, "none");
24420 	} else {
24421 		switch (DUK_TVAL_GET_TAG(tv)) {
24422 		case DUK_TAG_STRING: {
24423 			duk_hstring *h = DUK_TVAL_GET_STRING(tv);
24424 			if (DUK_HSTRING_HAS_SYMBOL(h)) {
24425 				/* XXX: string summary produces question marks
24426 				 * so this is not very ideal.
24427 				 */
24428 				duk_push_literal(thr, "[Symbol ");
24429 				duk_push_string(thr, duk__get_symbol_type_string(h));
24430 				duk_push_literal(thr, " ");
24431 				duk__push_hstring_readable_unicode(thr, h, DUK__READABLE_STRING_MAXCHARS);
24432 				duk_push_literal(thr, "]");
24433 				duk_concat(thr, 5);
24434 				break;
24435 			}
24436 			duk__push_hstring_readable_unicode(thr, h, DUK__READABLE_STRING_MAXCHARS);
24437 			break;
24438 		}
24439 		case DUK_TAG_OBJECT: {
24440 			duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
24441 			DUK_ASSERT(h != NULL);
24442 
24443 			if (error_aware &&
24444 			    duk_hobject_prototype_chain_contains(thr, h, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
24445 				/* Get error message in a side effect free way if
24446 				 * possible; if not, summarize as a generic object.
24447 				 * Error message currently gets quoted.
24448 				 */
24449 				/* XXX: better internal getprop call; get without side effects
24450 				 * but traverse inheritance chain.
24451 				 */
24452 				duk_tval *tv_msg;
24453 				tv_msg = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, h, DUK_STRIDX_MESSAGE);
24454 				if (tv_msg != NULL && DUK_TVAL_IS_STRING(tv_msg)) {
24455 					/* It's critical to avoid recursion so
24456 					 * only summarize a string .message.
24457 					 */
24458 					duk__push_hstring_readable_unicode(thr, DUK_TVAL_GET_STRING(tv_msg), DUK__READABLE_ERRMSG_MAXCHARS);
24459 					break;
24460 				}
24461 			}
24462 			duk_push_class_string_tval(thr, tv, 1 /*avoid_side_effects*/);
24463 			break;
24464 		}
24465 		case DUK_TAG_BUFFER: {
24466 			/* While plain buffers mimic Uint8Arrays, they summarize differently.
24467 			 * This is useful so that the summarized string accurately reflects the
24468 			 * internal type which may matter for figuring out bugs etc.
24469 			 */
24470 			/* XXX: Hex encoded, length limited buffer summary here? */
24471 			duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
24472 			DUK_ASSERT(h != NULL);
24473 			duk_push_sprintf(thr, "[buffer:%ld]", (long) DUK_HBUFFER_GET_SIZE(h));
24474 			break;
24475 		}
24476 		case DUK_TAG_POINTER: {
24477 			/* Surround with parentheses like in JX, ensures NULL pointer
24478 			 * is distinguishable from null value ("(null)" vs "null").
24479 			 */
24480 			duk_push_tval(thr, tv);
24481 			duk_push_sprintf(thr, "(%s)", duk_to_string(thr, -1));
24482 			duk_remove_m2(thr);
24483 			break;
24484 		}
24485 		default: {
24486 			duk_push_tval(thr, tv);
24487 			break;
24488 		}
24489 		}
24490 	}
24491 
24492 	return duk_to_string(thr, -1);
24493 }
duk_push_string_tval_readable(duk_hthread * thr,duk_tval * tv)24494 DUK_INTERNAL const char *duk_push_string_tval_readable(duk_hthread *thr, duk_tval *tv) {
24495 	DUK_ASSERT_API_ENTRY(thr);
24496 	return duk__push_string_tval_readable(thr, tv, 0 /*error_aware*/);
24497 }
24498 
duk_push_string_readable(duk_hthread * thr,duk_idx_t idx)24499 DUK_INTERNAL const char *duk_push_string_readable(duk_hthread *thr, duk_idx_t idx) {
24500 	DUK_ASSERT_API_ENTRY(thr);
24501 	return duk_push_string_tval_readable(thr, duk_get_tval(thr, idx));
24502 }
24503 
duk_push_string_tval_readable_error(duk_hthread * thr,duk_tval * tv)24504 DUK_INTERNAL const char *duk_push_string_tval_readable_error(duk_hthread *thr, duk_tval *tv) {
24505 	DUK_ASSERT_API_ENTRY(thr);
24506 	return duk__push_string_tval_readable(thr, tv, 1 /*error_aware*/);
24507 }
24508 
duk_push_symbol_descriptive_string(duk_hthread * thr,duk_hstring * h)24509 DUK_INTERNAL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstring *h) {
24510 	const duk_uint8_t *p;
24511 	const duk_uint8_t *p_end;
24512 	const duk_uint8_t *q;
24513 
24514 	DUK_ASSERT_API_ENTRY(thr);
24515 
24516 	/* .toString() */
24517 	duk_push_literal(thr, "Symbol(");
24518 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
24519 	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
24520 	DUK_ASSERT(p[0] == 0xff || (p[0] & 0xc0) == 0x80);
24521 	p++;
24522 	for (q = p; q < p_end; q++) {
24523 		if (*q == 0xffU) {
24524 			/* Terminate either at end-of-string (but NUL MUST
24525 			 * be accepted without terminating description) or
24526 			 * 0xFF, which is used to mark start of unique trailer
24527 			 * (and cannot occur in CESU-8 / extended UTF-8).
24528 			 */
24529 			break;
24530 		}
24531 	}
24532 	duk_push_lstring(thr, (const char *) p, (duk_size_t) (q - p));
24533 	duk_push_literal(thr, ")");
24534 	duk_concat(thr, 3);
24535 }
24536 
24537 /*
24538  *  Functions
24539  */
24540 
24541 #if 0  /* not used yet */
24542 DUK_INTERNAL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h) {
24543 	duk_c_function func;
24544 
24545 	DUK_ASSERT_API_ENTRY(thr);
24546 	DUK_ASSERT(h != NULL);
24547 	DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h));
24548 
24549 	duk_push_sprintf(thr, "native_");
24550 	func = h->func;
24551 	duk_push_string_funcptr(thr, (duk_uint8_t *) &func, sizeof(func));
24552 	duk_push_sprintf(thr, "_%04x_%04x",
24553 	                 (unsigned int) (duk_uint16_t) h->nargs,
24554 	                 (unsigned int) (duk_uint16_t) h->magic);
24555 	duk_concat(thr, 3);
24556 }
24557 #endif
24558 
24559 /*
24560  *  duk_tval slice copy
24561  */
24562 
duk_copy_tvals_incref(duk_hthread * thr,duk_tval * tv_dst,duk_tval * tv_src,duk_size_t count)24563 DUK_INTERNAL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_size_t count) {
24564 	duk_tval *tv;
24565 
24566 	DUK_ASSERT_API_ENTRY(thr);
24567 	DUK_UNREF(thr);
24568 	DUK_ASSERT(count * sizeof(duk_tval) >= count);  /* no wrap */
24569 
24570 	duk_memcpy_unsafe((void *) tv_dst, (const void *) tv_src, count * sizeof(duk_tval));
24571 
24572 	tv = tv_dst;
24573 	while (count-- > 0) {
24574 		DUK_TVAL_INCREF(thr, tv);
24575 		tv++;
24576 	}
24577 }
24578 
24579 /* automatic undefs */
24580 #undef DUK__ASSERT_SPACE
24581 #undef DUK__CHECK_SPACE
24582 #undef DUK__ERROR_STASH_SHARED
24583 #undef DUK__PACK_ARGS
24584 #undef DUK__READABLE_ERRMSG_MAXCHARS
24585 #undef DUK__READABLE_STRING_MAXCHARS
24586 #undef DUK__READABLE_SUMMARY_MAXCHARS
24587 /*
24588  *  String manipulation
24589  */
24590 
24591 /* #include duk_internal.h -> already included */
24592 
duk__concat_and_join_helper(duk_hthread * thr,duk_idx_t count_in,duk_bool_t is_join)24593 DUK_LOCAL void duk__concat_and_join_helper(duk_hthread *thr, duk_idx_t count_in, duk_bool_t is_join) {
24594 	duk_uint_t count;
24595 	duk_uint_t i;
24596 	duk_size_t idx;
24597 	duk_size_t len;
24598 	duk_hstring *h;
24599 	duk_uint8_t *buf;
24600 
24601 	DUK_CTX_ASSERT_VALID(thr);
24602 
24603 	if (DUK_UNLIKELY(count_in <= 0)) {
24604 		if (count_in < 0) {
24605 			DUK_ERROR_RANGE_INVALID_COUNT(thr);
24606 			DUK_WO_NORETURN(return;);
24607 		}
24608 		DUK_ASSERT(count_in == 0);
24609 		duk_push_hstring_empty(thr);
24610 		return;
24611 	}
24612 	count = (duk_uint_t) count_in;
24613 
24614 	if (is_join) {
24615 		duk_size_t t1, t2, limit;
24616 		h = duk_to_hstring(thr, -((duk_idx_t) count) - 1);
24617 		DUK_ASSERT(h != NULL);
24618 
24619 		/* A bit tricky overflow test, see doc/code-issues.rst. */
24620 		t1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
24621 		t2 = (duk_size_t) (count - 1);
24622 		limit = (duk_size_t) DUK_HSTRING_MAX_BYTELEN;
24623 		if (DUK_UNLIKELY(t2 != 0 && t1 > limit / t2)) {
24624 			/* Combined size of separators already overflows. */
24625 			goto error_overflow;
24626 		}
24627 		len = (duk_size_t) (t1 * t2);
24628 	} else {
24629 		len = (duk_size_t) 0;
24630 	}
24631 
24632 	for (i = count; i >= 1; i--) {
24633 		duk_size_t new_len;
24634 		h = duk_to_hstring(thr, -((duk_idx_t) i));
24635 		new_len = len + (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
24636 
24637 		/* Impose a string maximum length, need to handle overflow
24638 		 * correctly.
24639 		 */
24640 		if (new_len < len ||  /* wrapped */
24641 		    new_len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN) {
24642 			goto error_overflow;
24643 		}
24644 		len = new_len;
24645 	}
24646 
24647 	DUK_DDD(DUK_DDDPRINT("join/concat %lu strings, total length %lu bytes",
24648 	                     (unsigned long) count, (unsigned long) len));
24649 
24650 	/* Use stack allocated buffer to ensure reachability in errors
24651 	 * (e.g. intern error).
24652 	 */
24653 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len);
24654 	DUK_ASSERT(buf != NULL);
24655 
24656 	/* [ ... (sep) str1 str2 ... strN buf ] */
24657 
24658 	idx = 0;
24659 	for (i = count; i >= 1; i--) {
24660 		if (is_join && i != count) {
24661 			h = duk_require_hstring(thr, -((duk_idx_t) count) - 2);  /* extra -1 for buffer */
24662 			duk_memcpy(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
24663 			idx += DUK_HSTRING_GET_BYTELEN(h);
24664 		}
24665 		h = duk_require_hstring(thr, -((duk_idx_t) i) - 1);  /* extra -1 for buffer */
24666 		duk_memcpy(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
24667 		idx += DUK_HSTRING_GET_BYTELEN(h);
24668 	}
24669 
24670 	DUK_ASSERT(idx == len);
24671 
24672 	/* [ ... (sep) str1 str2 ... strN buf ] */
24673 
24674 	/* Get rid of the strings early to minimize memory use before intern. */
24675 
24676 	if (is_join) {
24677 		duk_replace(thr, -((duk_idx_t) count) - 2);  /* overwrite sep */
24678 		duk_pop_n(thr, (duk_idx_t) count);
24679 	} else {
24680 		duk_replace(thr, -((duk_idx_t) count) - 1);  /* overwrite str1 */
24681 		duk_pop_n(thr, (duk_idx_t) (count - 1));
24682 	}
24683 
24684 	/* [ ... buf ] */
24685 
24686 	(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */
24687 
24688 	/* [ ... res ] */
24689 	return;
24690 
24691  error_overflow:
24692 	DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
24693 	DUK_WO_NORETURN(return;);
24694 }
24695 
duk_concat(duk_hthread * thr,duk_idx_t count)24696 DUK_EXTERNAL void duk_concat(duk_hthread *thr, duk_idx_t count) {
24697 	DUK_ASSERT_API_ENTRY(thr);
24698 
24699 	duk__concat_and_join_helper(thr, count, 0 /*is_join*/);
24700 }
24701 
24702 #if defined(DUK_USE_PREFER_SIZE)
duk_concat_2(duk_hthread * thr)24703 DUK_INTERNAL void duk_concat_2(duk_hthread *thr) {
24704 	DUK_ASSERT_API_ENTRY(thr);
24705 	duk_concat(thr, 2);
24706 }
24707 #else  /* DUK_USE_PREFER_SIZE */
duk_concat_2(duk_hthread * thr)24708 DUK_INTERNAL void duk_concat_2(duk_hthread *thr) {
24709 	duk_hstring *h1;
24710 	duk_hstring *h2;
24711 	duk_uint8_t *buf;
24712 	duk_size_t len1;
24713 	duk_size_t len2;
24714 	duk_size_t len;
24715 
24716 	DUK_ASSERT_API_ENTRY(thr);
24717 	DUK_ASSERT(duk_get_top(thr) >= 2);  /* Trusted caller. */
24718 
24719 	h1 = duk_to_hstring(thr, -2);
24720 	h2 = duk_to_hstring(thr, -1);
24721 	len1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
24722 	len2 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
24723 	len = len1 + len2;
24724 	if (DUK_UNLIKELY(len < len1 ||  /* wrapped */
24725 	                 len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN)) {
24726 		goto error_overflow;
24727 	}
24728 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len);
24729 	DUK_ASSERT(buf != NULL);
24730 
24731 	duk_memcpy((void *) buf, (const void *) DUK_HSTRING_GET_DATA(h1), (size_t) len1);
24732 	duk_memcpy((void *) (buf + len1), (const void *) DUK_HSTRING_GET_DATA(h2), (size_t) len2);
24733 	(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */
24734 
24735 	/* [ ... str1 str2 buf ] */
24736 
24737 	duk_replace(thr, -3);
24738 	duk_pop_unsafe(thr);
24739 	return;
24740 
24741  error_overflow:
24742 	DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
24743 	DUK_WO_NORETURN(return;);
24744 }
24745 #endif  /* DUK_USE_PREFER_SIZE */
24746 
duk_join(duk_hthread * thr,duk_idx_t count)24747 DUK_EXTERNAL void duk_join(duk_hthread *thr, duk_idx_t count) {
24748 	DUK_ASSERT_API_ENTRY(thr);
24749 
24750 	duk__concat_and_join_helper(thr, count, 1 /*is_join*/);
24751 }
24752 
24753 /* XXX: could map/decode be unified with duk_unicode_support.c code?
24754  * Case conversion needs also the character surroundings though.
24755  */
24756 
duk_decode_string(duk_hthread * thr,duk_idx_t idx,duk_decode_char_function callback,void * udata)24757 DUK_EXTERNAL void duk_decode_string(duk_hthread *thr, duk_idx_t idx, duk_decode_char_function callback, void *udata) {
24758 	duk_hstring *h_input;
24759 	const duk_uint8_t *p, *p_start, *p_end;
24760 	duk_codepoint_t cp;
24761 
24762 	DUK_ASSERT_API_ENTRY(thr);
24763 
24764 	h_input = duk_require_hstring(thr, idx);  /* Accept symbols. */
24765 	DUK_ASSERT(h_input != NULL);
24766 
24767 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
24768 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
24769 	p = p_start;
24770 
24771 	for (;;) {
24772 		if (p >= p_end) {
24773 			break;
24774 		}
24775 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
24776 		callback(udata, cp);
24777 	}
24778 }
24779 
duk_map_string(duk_hthread * thr,duk_idx_t idx,duk_map_char_function callback,void * udata)24780 DUK_EXTERNAL void duk_map_string(duk_hthread *thr, duk_idx_t idx, duk_map_char_function callback, void *udata) {
24781 	duk_hstring *h_input;
24782 	duk_bufwriter_ctx bw_alloc;
24783 	duk_bufwriter_ctx *bw;
24784 	const duk_uint8_t *p, *p_start, *p_end;
24785 	duk_codepoint_t cp;
24786 
24787 	DUK_ASSERT_API_ENTRY(thr);
24788 
24789 	idx = duk_normalize_index(thr, idx);
24790 
24791 	h_input = duk_require_hstring(thr, idx);  /* Accept symbols. */
24792 	DUK_ASSERT(h_input != NULL);
24793 
24794 	bw = &bw_alloc;
24795 	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* Reasonable output estimate. */
24796 
24797 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
24798 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
24799 	p = p_start;
24800 
24801 	for (;;) {
24802 		/* XXX: could write output in chunks with fewer ensure calls,
24803 		 * but relative benefit would be small here.
24804 		 */
24805 
24806 		if (p >= p_end) {
24807 			break;
24808 		}
24809 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
24810 		cp = callback(udata, cp);
24811 
24812 		DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
24813 	}
24814 
24815 	DUK_BW_COMPACT(thr, bw);
24816 	(void) duk_buffer_to_string(thr, -1);  /* Safe, extended UTF-8 encoded. */
24817 	duk_replace(thr, idx);
24818 }
24819 
duk_substring(duk_hthread * thr,duk_idx_t idx,duk_size_t start_offset,duk_size_t end_offset)24820 DUK_EXTERNAL void duk_substring(duk_hthread *thr, duk_idx_t idx, duk_size_t start_offset, duk_size_t end_offset) {
24821 	duk_hstring *h;
24822 	duk_hstring *res;
24823 	duk_size_t start_byte_offset;
24824 	duk_size_t end_byte_offset;
24825 	duk_size_t charlen;
24826 
24827 	DUK_ASSERT_API_ENTRY(thr);
24828 
24829 	idx = duk_require_normalize_index(thr, idx);  /* Accept symbols. */
24830 	h = duk_require_hstring(thr, idx);
24831 	DUK_ASSERT(h != NULL);
24832 
24833 	charlen = DUK_HSTRING_GET_CHARLEN(h);
24834 	if (end_offset >= charlen) {
24835 		end_offset = charlen;
24836 	}
24837 	if (start_offset > end_offset) {
24838 		start_offset = end_offset;
24839 	}
24840 
24841 	DUK_ASSERT_DISABLE(start_offset >= 0);
24842 	DUK_ASSERT(start_offset <= end_offset && start_offset <= DUK_HSTRING_GET_CHARLEN(h));
24843 	DUK_ASSERT_DISABLE(end_offset >= 0);
24844 	DUK_ASSERT(end_offset >= start_offset && end_offset <= DUK_HSTRING_GET_CHARLEN(h));
24845 
24846 	/* Guaranteed by string limits. */
24847 	DUK_ASSERT(start_offset <= DUK_UINT32_MAX);
24848 	DUK_ASSERT(end_offset <= DUK_UINT32_MAX);
24849 
24850 	start_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) start_offset);
24851 	end_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) end_offset);
24852 
24853 	DUK_ASSERT(end_byte_offset >= start_byte_offset);
24854 	DUK_ASSERT(end_byte_offset - start_byte_offset <= DUK_UINT32_MAX);  /* Guaranteed by string limits. */
24855 
24856 	/* No size check is necessary. */
24857 	res = duk_heap_strtable_intern_checked(thr,
24858 	                                       DUK_HSTRING_GET_DATA(h) + start_byte_offset,
24859 	                                       (duk_uint32_t) (end_byte_offset - start_byte_offset));
24860 
24861 	duk_push_hstring(thr, res);
24862 	duk_replace(thr, idx);
24863 }
24864 
24865 /* XXX: this is quite clunky.  Add Unicode helpers to scan backwards and
24866  * forwards with a callback to process codepoints?
24867  */
duk_trim(duk_hthread * thr,duk_idx_t idx)24868 DUK_EXTERNAL void duk_trim(duk_hthread *thr, duk_idx_t idx) {
24869 	duk_hstring *h;
24870 	const duk_uint8_t *p, *p_start, *p_end, *p_tmp1, *p_tmp2;  /* pointers for scanning */
24871 	const duk_uint8_t *q_start, *q_end;  /* start (incl) and end (excl) of trimmed part */
24872 	duk_codepoint_t cp;
24873 
24874 	DUK_ASSERT_API_ENTRY(thr);
24875 
24876 	idx = duk_require_normalize_index(thr, idx);  /* Accept symbols. */
24877 	h = duk_require_hstring(thr, idx);
24878 	DUK_ASSERT(h != NULL);
24879 
24880 	p_start = DUK_HSTRING_GET_DATA(h);
24881 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
24882 
24883 	p = p_start;
24884 	while (p < p_end) {
24885 		p_tmp1 = p;
24886 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp1, p_start, p_end);
24887 		if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
24888 			break;
24889 		}
24890 		p = p_tmp1;
24891 	}
24892 	q_start = p;
24893 	if (p == p_end) {
24894 		/* Entire string is whitespace. */
24895 		q_end = p;
24896 		goto scan_done;
24897 	}
24898 
24899 	p = p_end;
24900 	while (p > p_start) {
24901 		p_tmp1 = p;
24902 		while (p > p_start) {
24903 			p--;
24904 			if (((*p) & 0xc0) != 0x80) {
24905 				break;
24906 			}
24907 		}
24908 		p_tmp2 = p;
24909 
24910 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp2, p_start, p_end);
24911 		if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
24912 			p = p_tmp1;
24913 			break;
24914 		}
24915 	}
24916 	q_end = p;
24917 
24918  scan_done:
24919 	/* This may happen when forward and backward scanning disagree
24920 	 * (possible for non-extended-UTF-8 strings).
24921 	 */
24922 	if (q_end < q_start) {
24923 		q_end = q_start;
24924 	}
24925 
24926 	DUK_ASSERT(q_start >= p_start && q_start <= p_end);
24927 	DUK_ASSERT(q_end >= p_start && q_end <= p_end);
24928 	DUK_ASSERT(q_end >= q_start);
24929 
24930 	DUK_DDD(DUK_DDDPRINT("trim: p_start=%p, p_end=%p, q_start=%p, q_end=%p",
24931 	                     (const void *) p_start, (const void *) p_end,
24932 	                     (const void *) q_start, (const void *) q_end));
24933 
24934 	if (q_start == p_start && q_end == p_end) {
24935 		DUK_DDD(DUK_DDDPRINT("nothing was trimmed: avoid interning (hashing etc)"));
24936 		return;
24937 	}
24938 
24939 	duk_push_lstring(thr, (const char *) q_start, (duk_size_t) (q_end - q_start));
24940 	duk_replace(thr, idx);
24941 }
24942 
duk_char_code_at(duk_hthread * thr,duk_idx_t idx,duk_size_t char_offset)24943 DUK_EXTERNAL duk_codepoint_t duk_char_code_at(duk_hthread *thr, duk_idx_t idx, duk_size_t char_offset) {
24944 	duk_hstring *h;
24945 	duk_ucodepoint_t cp;
24946 
24947 	DUK_ASSERT_API_ENTRY(thr);
24948 
24949 	/* XXX: Share code with String.prototype.charCodeAt?  Main difference
24950 	 * is handling of clamped offsets.
24951 	 */
24952 
24953 	h = duk_require_hstring(thr, idx);  /* Accept symbols. */
24954 	DUK_ASSERT(h != NULL);
24955 
24956 	DUK_ASSERT_DISABLE(char_offset >= 0);  /* Always true, arg is unsigned. */
24957 	if (char_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
24958 		return 0;
24959 	}
24960 
24961 	DUK_ASSERT(char_offset <= DUK_UINT_MAX);  /* Guaranteed by string limits. */
24962 	cp = duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) char_offset, 0 /*surrogate_aware*/);
24963 	return (duk_codepoint_t) cp;
24964 }
24965 /*
24966  *  Date/time.
24967  */
24968 
24969 /* #include duk_internal.h -> already included */
24970 
duk_time_get_ecmascript_time(duk_hthread * thr)24971 DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr) {
24972 	/* ECMAScript time, with millisecond fractions.  Exposed via
24973 	 * duk_get_now() for example.
24974 	 */
24975 	DUK_UNREF(thr);
24976 	return (duk_double_t) DUK_USE_DATE_GET_NOW(thr);
24977 }
24978 
duk_time_get_ecmascript_time_nofrac(duk_hthread * thr)24979 DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr) {
24980 	/* ECMAScript time without millisecond fractions.  Exposed via
24981 	 * the Date built-in which doesn't allow fractions.
24982 	 */
24983 	DUK_UNREF(thr);
24984 	return (duk_double_t) DUK_FLOOR(DUK_USE_DATE_GET_NOW(thr));
24985 }
24986 
duk_time_get_monotonic_time(duk_hthread * thr)24987 DUK_INTERNAL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr) {
24988 	DUK_UNREF(thr);
24989 #if defined(DUK_USE_GET_MONOTONIC_TIME)
24990 	return (duk_double_t) DUK_USE_GET_MONOTONIC_TIME(thr);
24991 #else
24992 	return (duk_double_t) DUK_USE_DATE_GET_NOW(thr);
24993 #endif
24994 }
24995 
duk_get_now(duk_hthread * thr)24996 DUK_EXTERNAL duk_double_t duk_get_now(duk_hthread *thr) {
24997 	DUK_ASSERT_API_ENTRY(thr);
24998 	DUK_UNREF(thr);
24999 
25000 	/* This API intentionally allows millisecond fractions. */
25001 	return duk_time_get_ecmascript_time(thr);
25002 }
25003 
25004 #if 0  /* XXX: worth exposing? */
25005 DUK_EXTERNAL duk_double_t duk_get_monotonic_time(duk_hthread *thr) {
25006 	DUK_ASSERT_API_ENTRY(thr);
25007 	DUK_UNREF(thr);
25008 
25009 	return duk_time_get_monotonic_time(thr);
25010 }
25011 #endif
25012 
duk_time_to_components(duk_hthread * thr,duk_double_t timeval,duk_time_components * comp)25013 DUK_EXTERNAL void duk_time_to_components(duk_hthread *thr, duk_double_t timeval, duk_time_components *comp) {
25014 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
25015 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
25016 	duk_uint_t flags;
25017 
25018 	DUK_ASSERT_API_ENTRY(thr);
25019 	DUK_ASSERT(comp != NULL);  /* XXX: or check? */
25020 	DUK_UNREF(thr);
25021 
25022 	/* Convert as one-based, but change month to zero-based to match the
25023 	 * ECMAScript Date built-in behavior 1:1.
25024 	 */
25025 	flags = DUK_DATE_FLAG_ONEBASED | DUK_DATE_FLAG_NAN_TO_ZERO;
25026 
25027 	duk_bi_date_timeval_to_parts(timeval, parts, dparts, flags);
25028 
25029 	/* XXX: sub-millisecond accuracy for the API */
25030 
25031 	DUK_ASSERT(dparts[DUK_DATE_IDX_MONTH] >= 1.0 && dparts[DUK_DATE_IDX_MONTH] <= 12.0);
25032 	comp->year = dparts[DUK_DATE_IDX_YEAR];
25033 	comp->month = dparts[DUK_DATE_IDX_MONTH] - 1.0;
25034 	comp->day = dparts[DUK_DATE_IDX_DAY];
25035 	comp->hours = dparts[DUK_DATE_IDX_HOUR];
25036 	comp->minutes = dparts[DUK_DATE_IDX_MINUTE];
25037 	comp->seconds = dparts[DUK_DATE_IDX_SECOND];
25038 	comp->milliseconds = dparts[DUK_DATE_IDX_MILLISECOND];
25039 	comp->weekday = dparts[DUK_DATE_IDX_WEEKDAY];
25040 }
25041 
duk_components_to_time(duk_hthread * thr,duk_time_components * comp)25042 DUK_EXTERNAL duk_double_t duk_components_to_time(duk_hthread *thr, duk_time_components *comp) {
25043 	duk_double_t d;
25044 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
25045 	duk_uint_t flags;
25046 
25047 	DUK_ASSERT_API_ENTRY(thr);
25048 	DUK_ASSERT(comp != NULL);  /* XXX: or check? */
25049 	DUK_UNREF(thr);
25050 
25051 	/* Match Date constructor behavior (with UTC time).  Month is given
25052 	 * as zero-based.  Day-of-month is given as one-based so normalize
25053 	 * it to zero-based as the internal conversion helpers expects all
25054 	 * components to be zero-based.
25055 	 */
25056 	flags = 0;
25057 
25058 	/* XXX: expensive conversion; use array format in API instead, or unify
25059 	 * time provider and time API to use same struct?
25060 	 */
25061 
25062 	dparts[DUK_DATE_IDX_YEAR] = comp->year;
25063 	dparts[DUK_DATE_IDX_MONTH] = comp->month;
25064 	dparts[DUK_DATE_IDX_DAY] = comp->day - 1.0;
25065 	dparts[DUK_DATE_IDX_HOUR] = comp->hours;
25066 	dparts[DUK_DATE_IDX_MINUTE] = comp->minutes;
25067 	dparts[DUK_DATE_IDX_SECOND] = comp->seconds;
25068 	dparts[DUK_DATE_IDX_MILLISECOND] = comp->milliseconds;
25069 	dparts[DUK_DATE_IDX_WEEKDAY] = 0;  /* ignored */
25070 
25071 	d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
25072 
25073 	return d;
25074 }
25075 /*
25076  *  Array built-ins
25077  *
25078  *  Most Array built-ins are intentionally generic in ECMAScript, and are
25079  *  intended to work even when the 'this' binding is not an Array instance.
25080  *  This ECMAScript feature is also used by much real world code.  For this
25081  *  reason the implementations here don't assume exotic Array behavior or
25082  *  e.g. presence of a .length property.  However, some algorithms have a
25083  *  fast path for duk_harray backed actual Array instances, enabled when
25084  *  footprint is not a concern.
25085  *
25086  *  XXX: the "Throw" flag should be set for (almost?) all [[Put]] and
25087  *  [[Delete]] operations, but it's currently false throughout.  Go through
25088  *  all put/delete cases and check throw flag use.  Need a new API primitive
25089  *  which allows throws flag to be specified.
25090  *
25091  *  XXX: array lengths above 2G won't work reliably.  There are many places
25092  *  where one needs a full signed 32-bit range ([-0xffffffff, 0xffffffff],
25093  *  i.e. -33- bits).  Although array 'length' cannot be written to be outside
25094  *  the unsigned 32-bit range (E5.1 Section 15.4.5.1 throws a RangeError if so)
25095  *  some intermediate values may be above 0xffffffff and this may not be always
25096  *  correctly handled now (duk_uint32_t is not enough for all algorithms).
25097  *  For instance, push() can legitimately write entries beyond length 0xffffffff
25098  *  and cause a RangeError only at the end.  To do this properly, the current
25099  *  push() implementation tracks the array index using a 'double' instead of a
25100  *  duk_uint32_t (which is somewhat awkward).  See test-bi-array-push-maxlen.js.
25101  *
25102  *  On using "put" vs. "def" prop
25103  *  =============================
25104  *
25105  *  Code below must be careful to use the appropriate primitive as it matters
25106  *  for compliance.  When using "put" there may be inherited properties in
25107  *  Array.prototype which cause side effects when values are written.  When
25108  *  using "define" there are no such side effects, and many test262 test cases
25109  *  check for this (for real world code, such side effects are very rare).
25110  *  Both "put" and "define" are used in the E5.1 specification; as a rule,
25111  *  "put" is used when modifying an existing array (or a non-array 'this'
25112  *  binding) and "define" for setting values into a fresh result array.
25113  */
25114 
25115 /* #include duk_internal.h -> already included */
25116 
25117 /* Perform an intermediate join when this many elements have been pushed
25118  * on the value stack.
25119  */
25120 #define  DUK__ARRAY_MID_JOIN_LIMIT  4096
25121 
25122 #if defined(DUK_USE_ARRAY_BUILTIN)
25123 
25124 /*
25125  *  Shared helpers.
25126  */
25127 
25128 /* Shared entry code for many Array built-ins: the 'this' binding is pushed
25129  * on the value stack and object coerced, and the current .length is returned.
25130  * Note that length is left on stack (it could be popped, but that's not
25131  * usually necessary because call handling will clean it up automatically).
25132  */
duk__push_this_obj_len_u32(duk_hthread * thr)25133 DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32(duk_hthread *thr) {
25134 	duk_uint32_t len;
25135 
25136 	/* XXX: push more directly? */
25137 	(void) duk_push_this_coercible_to_object(thr);
25138 	DUK_HOBJECT_ASSERT_VALID(duk_get_hobject(thr, -1));
25139 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_LENGTH);
25140 	len = duk_to_uint32(thr, -1);
25141 
25142 	/* -> [ ... ToObject(this) ToUint32(length) ] */
25143 	return len;
25144 }
25145 
duk__push_this_obj_len_u32_limited(duk_hthread * thr)25146 DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32_limited(duk_hthread *thr) {
25147 	/* Range limited to [0, 0x7fffffff] range, i.e. range that can be
25148 	 * represented with duk_int32_t.  Use this when the method doesn't
25149 	 * handle the full 32-bit unsigned range correctly.
25150 	 */
25151 	duk_uint32_t ret = duk__push_this_obj_len_u32(thr);
25152 	if (DUK_UNLIKELY(ret >= 0x80000000UL)) {
25153 		DUK_ERROR_RANGE_INVALID_LENGTH(thr);
25154 		DUK_WO_NORETURN(return 0U;);
25155 	}
25156 	return ret;
25157 }
25158 
25159 #if defined(DUK_USE_ARRAY_FASTPATH)
25160 /* Check if 'this' binding is an Array instance (duk_harray) which satisfies
25161  * a few other guarantees for fast path operation.  The fast path doesn't
25162  * need to handle all operations, even for duk_harrays, but must handle a
25163  * significant fraction to improve performance.  Return a non-NULL duk_harray
25164  * pointer when all fast path criteria are met, NULL otherwise.
25165  */
duk__arraypart_fastpath_this(duk_hthread * thr)25166 DUK_LOCAL duk_harray *duk__arraypart_fastpath_this(duk_hthread *thr) {
25167 	duk_tval *tv;
25168 	duk_hobject *h;
25169 	duk_uint_t flags_mask, flags_bits, flags_value;
25170 
25171 	DUK_ASSERT(thr->valstack_bottom > thr->valstack);  /* because call in progress */
25172 	tv = DUK_GET_THIS_TVAL_PTR(thr);
25173 
25174 	/* Fast path requires that 'this' is a duk_harray.  Read only arrays
25175 	 * (ROM backed) are also rejected for simplicity.
25176 	 */
25177 	if (!DUK_TVAL_IS_OBJECT(tv)) {
25178 		DUK_DD(DUK_DDPRINT("reject array fast path: not an object"));
25179 		return NULL;
25180 	}
25181 	h = DUK_TVAL_GET_OBJECT(tv);
25182 	DUK_ASSERT(h != NULL);
25183 	flags_mask = DUK_HOBJECT_FLAG_ARRAY_PART | \
25184 	             DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
25185 	             DUK_HEAPHDR_FLAG_READONLY;
25186 	flags_bits = DUK_HOBJECT_FLAG_ARRAY_PART | \
25187 	             DUK_HOBJECT_FLAG_EXOTIC_ARRAY;
25188 	flags_value = DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) h);
25189 	if ((flags_value & flags_mask) != flags_bits) {
25190 		DUK_DD(DUK_DDPRINT("reject array fast path: object flag check failed"));
25191 		return NULL;
25192 	}
25193 
25194 	/* In some cases a duk_harray's 'length' may be larger than the
25195 	 * current array part allocation.  Avoid the fast path in these
25196 	 * cases, so that all fast path code can safely assume that all
25197 	 * items in the range [0,length[ are backed by the current array
25198 	 * part allocation.
25199 	 */
25200 	if (((duk_harray *) h)->length > DUK_HOBJECT_GET_ASIZE(h)) {
25201 		DUK_DD(DUK_DDPRINT("reject array fast path: length > array part size"));
25202 		return NULL;
25203 	}
25204 
25205 	/* Guarantees for fast path. */
25206 	DUK_ASSERT(h != NULL);
25207 	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0 || DUK_HOBJECT_A_GET_BASE(thr->heap, h) != NULL);
25208 	DUK_ASSERT(((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h));
25209 
25210 	DUK_DD(DUK_DDPRINT("array fast path allowed for: %!O", (duk_heaphdr *) h));
25211 	return (duk_harray *) h;
25212 }
25213 #endif  /* DUK_USE_ARRAY_FASTPATH */
25214 
25215 /*
25216  *  Constructor
25217  */
25218 
duk_bi_array_constructor(duk_hthread * thr)25219 DUK_INTERNAL duk_ret_t duk_bi_array_constructor(duk_hthread *thr) {
25220 	duk_idx_t nargs;
25221 	duk_harray *a;
25222 	duk_double_t d;
25223 	duk_uint32_t len;
25224 	duk_uint32_t len_prealloc;
25225 
25226 	nargs = duk_get_top(thr);
25227 
25228 	if (nargs == 1 && duk_is_number(thr, 0)) {
25229 		/* XXX: expensive check (also shared elsewhere - so add a shared internal API call?) */
25230 		d = duk_get_number(thr, 0);
25231 		len = duk_to_uint32(thr, 0);
25232 		if (((duk_double_t) len) != d) {
25233 			DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
25234 		}
25235 
25236 		/* For small lengths create a dense preallocated array.
25237 		 * For large arrays preallocate an initial part.
25238 		 */
25239 		len_prealloc = len < 64 ? len : 64;
25240 		a = duk_push_harray_with_size(thr, len_prealloc);
25241 		DUK_ASSERT(a != NULL);
25242 		DUK_ASSERT(!duk_is_bare_object(thr, -1));
25243 		a->length = len;
25244 		return 1;
25245 	}
25246 
25247 	duk_pack(thr, nargs);
25248 	return 1;
25249 }
25250 
25251 /*
25252  *  isArray()
25253  */
25254 
duk_bi_array_constructor_is_array(duk_hthread * thr)25255 DUK_INTERNAL duk_ret_t duk_bi_array_constructor_is_array(duk_hthread *thr) {
25256 	duk_hobject *h;
25257 
25258 	h = duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_ARRAY);
25259 	duk_push_boolean(thr, (h != NULL));
25260 	return 1;
25261 }
25262 
25263 /*
25264  *  toString()
25265  */
25266 
duk_bi_array_prototype_to_string(duk_hthread * thr)25267 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_to_string(duk_hthread *thr) {
25268 	(void) duk_push_this_coercible_to_object(thr);
25269 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_JOIN);
25270 
25271 	/* [ ... this func ] */
25272 	if (!duk_is_callable(thr, -1)) {
25273 		/* Fall back to the initial (original) Object.toString().  We don't
25274 		 * currently have pointers to the built-in functions, only the top
25275 		 * level global objects (like "Array") so this is now done in a bit
25276 		 * of a hacky manner.  It would be cleaner to push the (original)
25277 		 * function and use duk_call_method().
25278 		 */
25279 
25280 		/* XXX: 'this' will be ToObject() coerced twice, which is incorrect
25281 		 * but should have no visible side effects.
25282 		 */
25283 		DUK_DDD(DUK_DDDPRINT("this.join is not callable, fall back to (original) Object.toString"));
25284 		duk_set_top(thr, 0);
25285 		return duk_bi_object_prototype_to_string(thr);  /* has access to 'this' binding */
25286 	}
25287 
25288 	/* [ ... this func ] */
25289 
25290 	duk_insert(thr, -2);
25291 
25292 	/* [ ... func this ] */
25293 
25294 	DUK_DDD(DUK_DDDPRINT("calling: func=%!iT, this=%!iT",
25295 	                     (duk_tval *) duk_get_tval(thr, -2),
25296 	                     (duk_tval *) duk_get_tval(thr, -1)));
25297 	duk_call_method(thr, 0);
25298 
25299 	return 1;
25300 }
25301 
25302 /*
25303  *  concat()
25304  */
25305 
duk_bi_array_prototype_concat(duk_hthread * thr)25306 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_concat(duk_hthread *thr) {
25307 	duk_idx_t i, n;
25308 	duk_uint32_t j, idx, len;
25309 	duk_hobject *h;
25310 	duk_size_t tmp_len;
25311 
25312 	/* XXX: In ES2015 Array .length can be up to 2^53-1.  The current
25313 	 * implementation is limited to 2^32-1.
25314 	 */
25315 
25316 	/* XXX: Fast path for array 'this' and array element. */
25317 
25318 	/* XXX: The insert here is a bit expensive if there are a lot of items.
25319 	 * It could also be special cased in the outermost for loop quite easily
25320 	 * (as the element is dup()'d anyway).
25321 	 */
25322 
25323 	(void) duk_push_this_coercible_to_object(thr);
25324 	duk_insert(thr, 0);
25325 	n = duk_get_top(thr);
25326 	duk_push_array(thr);  /* -> [ ToObject(this) item1 ... itemN arr ] */
25327 
25328 	/* NOTE: The Array special behaviors are NOT invoked by duk_xdef_prop_index()
25329 	 * (which differs from the official algorithm).  If no error is thrown, this
25330 	 * doesn't matter as the length is updated at the end.  However, if an error
25331 	 * is thrown, the length will be unset.  That shouldn't matter because the
25332 	 * caller won't get a reference to the intermediate value.
25333 	 */
25334 
25335 	idx = 0;
25336 	for (i = 0; i < n; i++) {
25337 		duk_bool_t spreadable;
25338 		duk_bool_t need_has_check;
25339 
25340 		DUK_ASSERT_TOP(thr, n + 1);
25341 
25342 		/* [ ToObject(this) item1 ... itemN arr ] */
25343 
25344 		h = duk_get_hobject(thr, i);
25345 
25346 		if (h == NULL) {
25347 			spreadable = 0;
25348 		} else {
25349 #if defined(DUK_USE_SYMBOL_BUILTIN)
25350 			duk_get_prop_stridx(thr, i, DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE);
25351 			if (duk_is_undefined(thr, -1)) {
25352 				spreadable = (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY);
25353 			} else {
25354 				spreadable = duk_to_boolean(thr, -1);
25355 			}
25356 			duk_pop_nodecref_unsafe(thr);
25357 #else
25358 			spreadable = (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY);
25359 #endif
25360 		}
25361 
25362 		if (!spreadable) {
25363 			duk_dup(thr, i);
25364 			duk_xdef_prop_index_wec(thr, -2, idx);
25365 			idx++;
25366 			if (DUK_UNLIKELY(idx == 0U)) {
25367 				/* Index after update is 0, and index written
25368 				 * was 0xffffffffUL which is no longer a valid
25369 				 * array index.
25370 				 */
25371 				goto fail_wrap;
25372 			}
25373 			continue;
25374 		}
25375 
25376 		DUK_ASSERT(duk_is_object(thr, i));
25377 		need_has_check = (DUK_HOBJECT_IS_PROXY(h) != 0);  /* Always 0 w/o Proxy support. */
25378 
25379 		/* [ ToObject(this) item1 ... itemN arr ] */
25380 
25381 		tmp_len = duk_get_length(thr, i);
25382 		len = (duk_uint32_t) tmp_len;
25383 		if (DUK_UNLIKELY(tmp_len != (duk_size_t) len)) {
25384 			goto fail_wrap;
25385 		}
25386 		if (DUK_UNLIKELY(idx + len < idx)) {
25387 			/* Result length must be at most 0xffffffffUL to be
25388 			 * a valid 32-bit array index.
25389 			 */
25390 			goto fail_wrap;
25391 		}
25392 		for (j = 0; j < len; j++) {
25393 			/* For a Proxy element, an explicit 'has' check is
25394 			 * needed to allow the Proxy to present gaps.
25395 			 */
25396 			if (need_has_check) {
25397 				if (duk_has_prop_index(thr, i, j)) {
25398 					duk_get_prop_index(thr, i, j);
25399 					duk_xdef_prop_index_wec(thr, -2, idx);
25400 				}
25401 			} else {
25402 				if (duk_get_prop_index(thr, i, j)) {
25403 					duk_xdef_prop_index_wec(thr, -2, idx);
25404 				} else {
25405 					duk_pop_undefined(thr);
25406 				}
25407 			}
25408 			idx++;
25409 			DUK_ASSERT(idx != 0U);  /* Wrap check above. */
25410 		}
25411 	}
25412 
25413 	/* ES5.1 has a specification "bug" in that nonexistent trailing
25414 	 * elements don't affect the result .length.  Test262 and other
25415 	 * engines disagree, and the specification bug was fixed in ES2015
25416 	 * (see NOTE 1 in https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.concat).
25417 	 */
25418 	duk_push_uarridx(thr, idx);
25419 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
25420 
25421 	DUK_ASSERT_TOP(thr, n + 1);
25422 	return 1;
25423 
25424  fail_wrap:
25425 	DUK_ERROR_RANGE_INVALID_LENGTH(thr);
25426 	DUK_WO_NORETURN(return 0;);
25427 }
25428 
25429 /*
25430  *  join(), toLocaleString()
25431  *
25432  *  Note: checking valstack is necessary, but only in the per-element loop.
25433  *
25434  *  Note: the trivial approach of pushing all the elements on the value stack
25435  *  and then calling duk_join() fails when the array contains a large number
25436  *  of elements.  This problem can't be offloaded to duk_join() because the
25437  *  elements to join must be handled here and have special handling.  Current
25438  *  approach is to do intermediate joins with very large number of elements.
25439  *  There is no fancy handling; the prefix gets re-joined multiple times.
25440  */
25441 
duk_bi_array_prototype_join_shared(duk_hthread * thr)25442 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_join_shared(duk_hthread *thr) {
25443 	duk_uint32_t len, count;
25444 	duk_uint32_t idx;
25445 	duk_small_int_t to_locale_string = duk_get_current_magic(thr);
25446 	duk_idx_t valstack_required;
25447 
25448 	/* For join(), nargs is 1.  For toLocaleString(), nargs is 0 and
25449 	 * setting the top essentially pushes an undefined to the stack,
25450 	 * thus defaulting to a comma separator.
25451 	 */
25452 	duk_set_top(thr, 1);
25453 	if (duk_is_undefined(thr, 0)) {
25454 		duk_pop_undefined(thr);
25455 		duk_push_hstring_stridx(thr, DUK_STRIDX_COMMA);
25456 	} else {
25457 		duk_to_string(thr, 0);
25458 	}
25459 
25460 	len = duk__push_this_obj_len_u32(thr);
25461 
25462 	/* [ sep ToObject(this) len ] */
25463 
25464 	DUK_DDD(DUK_DDDPRINT("sep=%!T, this=%!T, len=%lu",
25465 	                     (duk_tval *) duk_get_tval(thr, 0),
25466 	                     (duk_tval *) duk_get_tval(thr, 1),
25467 	                     (unsigned long) len));
25468 
25469 	/* The extra (+4) is tight. */
25470 	valstack_required = (duk_idx_t) ((len >= DUK__ARRAY_MID_JOIN_LIMIT ?
25471 	                                  DUK__ARRAY_MID_JOIN_LIMIT : len) + 4);
25472 	duk_require_stack(thr, valstack_required);
25473 
25474 	duk_dup_0(thr);
25475 
25476 	/* [ sep ToObject(this) len sep ] */
25477 
25478 	count = 0;
25479 	idx = 0;
25480 	for (;;) {
25481 		DUK_DDD(DUK_DDDPRINT("join idx=%ld", (long) idx));
25482 		if (count >= DUK__ARRAY_MID_JOIN_LIMIT ||   /* intermediate join to avoid valstack overflow */
25483 		    idx >= len) { /* end of loop (careful with len==0) */
25484 			/* [ sep ToObject(this) len sep str0 ... str(count-1) ] */
25485 			DUK_DDD(DUK_DDDPRINT("mid/final join, count=%ld, idx=%ld, len=%ld",
25486 			                     (long) count, (long) idx, (long) len));
25487 			duk_join(thr, (duk_idx_t) count);  /* -> [ sep ToObject(this) len str ] */
25488 			duk_dup_0(thr);                    /* -> [ sep ToObject(this) len str sep ] */
25489 			duk_insert(thr, -2);               /* -> [ sep ToObject(this) len sep str ] */
25490 			count = 1;
25491 		}
25492 		if (idx >= len) {
25493 			/* if true, the stack already contains the final result */
25494 			break;
25495 		}
25496 
25497 		duk_get_prop_index(thr, 1, (duk_uarridx_t) idx);
25498 		if (duk_is_null_or_undefined(thr, -1)) {
25499 			duk_pop_nodecref_unsafe(thr);
25500 			duk_push_hstring_empty(thr);
25501 		} else {
25502 			if (to_locale_string) {
25503 				duk_to_object(thr, -1);
25504 				duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_LOCALE_STRING);
25505 				duk_insert(thr, -2);  /* -> [ ... toLocaleString ToObject(val) ] */
25506 				duk_call_method(thr, 0);
25507 			}
25508 			duk_to_string(thr, -1);
25509 		}
25510 
25511 		count++;
25512 		idx++;
25513 	}
25514 
25515 	/* [ sep ToObject(this) len sep result ] */
25516 
25517 	return 1;
25518 }
25519 
25520 /*
25521  *  pop(), push()
25522  */
25523 
25524 #if defined(DUK_USE_ARRAY_FASTPATH)
duk__array_pop_fastpath(duk_hthread * thr,duk_harray * h_arr)25525 DUK_LOCAL duk_ret_t duk__array_pop_fastpath(duk_hthread *thr, duk_harray *h_arr) {
25526 	duk_tval *tv_arraypart;
25527 	duk_tval *tv_val;
25528 	duk_uint32_t len;
25529 
25530 	tv_arraypart = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);
25531 	len = h_arr->length;
25532 	if (len <= 0) {
25533 		/* nop, return undefined */
25534 		return 0;
25535 	}
25536 
25537 	len--;
25538 	h_arr->length = len;
25539 
25540 	/* Fast path doesn't check for an index property inherited from
25541 	 * Array.prototype.  This is quite often acceptable; if not,
25542 	 * disable fast path.
25543 	 */
25544 	DUK_ASSERT_VS_SPACE(thr);
25545 	tv_val = tv_arraypart + len;
25546 	if (DUK_TVAL_IS_UNUSED(tv_val)) {
25547 		/* No net refcount change.  Value stack already has
25548 		 * 'undefined' based on value stack init policy.
25549 		 */
25550 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
25551 		DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv_val));
25552 	} else {
25553 		/* No net refcount change. */
25554 		DUK_TVAL_SET_TVAL(thr->valstack_top, tv_val);
25555 		DUK_TVAL_SET_UNUSED(tv_val);
25556 	}
25557 	thr->valstack_top++;
25558 
25559 	/* XXX: there's no shrink check in the fast path now */
25560 
25561 	return 1;
25562 }
25563 #endif  /* DUK_USE_ARRAY_FASTPATH */
25564 
duk_bi_array_prototype_pop(duk_hthread * thr)25565 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_pop(duk_hthread *thr) {
25566 	duk_uint32_t len;
25567 	duk_uint32_t idx;
25568 #if defined(DUK_USE_ARRAY_FASTPATH)
25569 	duk_harray *h_arr;
25570 #endif
25571 
25572 	DUK_ASSERT_TOP(thr, 0);
25573 
25574 #if defined(DUK_USE_ARRAY_FASTPATH)
25575 	h_arr = duk__arraypart_fastpath_this(thr);
25576 	if (h_arr) {
25577 		return duk__array_pop_fastpath(thr, h_arr);
25578 	}
25579 #endif
25580 
25581 	/* XXX: Merge fastpath check into a related call (push this, coerce length, etc)? */
25582 
25583 	len = duk__push_this_obj_len_u32(thr);
25584 	if (len == 0) {
25585 		duk_push_int(thr, 0);
25586 		duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
25587 		return 0;
25588 	}
25589 	idx = len - 1;
25590 
25591 	duk_get_prop_index(thr, 0, (duk_uarridx_t) idx);
25592 	duk_del_prop_index(thr, 0, (duk_uarridx_t) idx);
25593 	duk_push_u32(thr, idx);
25594 	duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
25595 	return 1;
25596 }
25597 
25598 #if defined(DUK_USE_ARRAY_FASTPATH)
duk__array_push_fastpath(duk_hthread * thr,duk_harray * h_arr)25599 DUK_LOCAL duk_ret_t duk__array_push_fastpath(duk_hthread *thr, duk_harray *h_arr) {
25600 	duk_tval *tv_arraypart;
25601 	duk_tval *tv_src;
25602 	duk_tval *tv_dst;
25603 	duk_uint32_t len;
25604 	duk_idx_t i, n;
25605 
25606 	len = h_arr->length;
25607 	tv_arraypart = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);
25608 
25609 	n = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
25610 	DUK_ASSERT(n >= 0);
25611 	DUK_ASSERT((duk_uint32_t) n <= DUK_UINT32_MAX);
25612 	if (DUK_UNLIKELY(len + (duk_uint32_t) n < len)) {
25613 		DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
25614 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);  /* != 0 return value returned as is by caller */
25615 	}
25616 	if (len + (duk_uint32_t) n > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr)) {
25617 		/* Array part would need to be extended.  Rely on slow path
25618 		 * for now.
25619 		 *
25620 		 * XXX: Rework hobject code a bit and add extend support.
25621 		 */
25622 		return 0;
25623 	}
25624 
25625 	tv_src = thr->valstack_bottom;
25626 	tv_dst = tv_arraypart + len;
25627 	for (i = 0; i < n; i++) {
25628 		/* No net refcount change; reset value stack values to
25629 		 * undefined to satisfy value stack init policy.
25630 		 */
25631 		DUK_TVAL_SET_TVAL(tv_dst, tv_src);
25632 		DUK_TVAL_SET_UNDEFINED(tv_src);
25633 		tv_src++;
25634 		tv_dst++;
25635 	}
25636 	thr->valstack_top = thr->valstack_bottom;
25637 	len += (duk_uint32_t) n;
25638 	h_arr->length = len;
25639 
25640 	DUK_ASSERT((duk_uint_t) len == len);
25641 	duk_push_uint(thr, (duk_uint_t) len);
25642 	return 1;
25643 }
25644 #endif  /* DUK_USE_ARRAY_FASTPATH */
25645 
duk_bi_array_prototype_push(duk_hthread * thr)25646 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_push(duk_hthread *thr) {
25647 	/* Note: 'this' is not necessarily an Array object.  The push()
25648 	 * algorithm is supposed to work for other kinds of objects too,
25649 	 * so the algorithm has e.g. an explicit update for the 'length'
25650 	 * property which is normally "magical" in arrays.
25651 	 */
25652 
25653 	duk_uint32_t len;
25654 	duk_idx_t i, n;
25655 #if defined(DUK_USE_ARRAY_FASTPATH)
25656 	duk_harray *h_arr;
25657 #endif
25658 
25659 #if defined(DUK_USE_ARRAY_FASTPATH)
25660 	h_arr = duk__arraypart_fastpath_this(thr);
25661 	if (h_arr) {
25662 		duk_ret_t rc;
25663 		rc = duk__array_push_fastpath(thr, h_arr);
25664 		if (rc != 0) {
25665 			return rc;
25666 		}
25667 		DUK_DD(DUK_DDPRINT("array push() fast path exited, resize case"));
25668 	}
25669 #endif
25670 
25671 	n = duk_get_top(thr);
25672 	len = duk__push_this_obj_len_u32(thr);
25673 
25674 	/* [ arg1 ... argN obj length ] */
25675 
25676 	/* Technically Array.prototype.push() can create an Array with length
25677 	 * longer than 2^32-1, i.e. outside the 32-bit range.  The final length
25678 	 * is *not* wrapped to 32 bits in the specification.
25679 	 *
25680 	 * This implementation tracks length with a uint32 because it's much
25681 	 * more practical.
25682 	 *
25683 	 * See: test-bi-array-push-maxlen.js.
25684 	 */
25685 
25686 	if (len + (duk_uint32_t) n < len) {
25687 		DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
25688 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
25689 	}
25690 
25691 	for (i = 0; i < n; i++) {
25692 		duk_dup(thr, i);
25693 		duk_put_prop_index(thr, -3, (duk_uarridx_t) (len + (duk_uint32_t) i));
25694 	}
25695 	len += (duk_uint32_t) n;
25696 
25697 	duk_push_u32(thr, len);
25698 	duk_dup_top(thr);
25699 	duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);
25700 
25701 	/* [ arg1 ... argN obj length new_length ] */
25702 	return 1;
25703 }
25704 
25705 /*
25706  *  sort()
25707  *
25708  *  Currently qsort with random pivot.  This is now really, really slow,
25709  *  because there is no fast path for array parts.
25710  *
25711  *  Signed indices are used because qsort() leaves and degenerate cases
25712  *  may use a negative offset.
25713  */
25714 
duk__array_sort_compare(duk_hthread * thr,duk_int_t idx1,duk_int_t idx2)25715 DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_hthread *thr, duk_int_t idx1, duk_int_t idx2) {
25716 	duk_bool_t have1, have2;
25717 	duk_bool_t undef1, undef2;
25718 	duk_small_int_t ret;
25719 	duk_idx_t idx_obj = 1;  /* fixed offsets in valstack */
25720 	duk_idx_t idx_fn = 0;
25721 	duk_hstring *h1, *h2;
25722 
25723 	/* Fast exit if indices are identical.  This is valid for a non-existent property,
25724 	 * for an undefined value, and almost always for ToString() coerced comparison of
25725 	 * arbitrary values (corner cases where this is not the case include e.g. a an
25726 	 * object with varying ToString() coercion).
25727 	 *
25728 	 * The specification does not prohibit "caching" of values read from the array, so
25729 	 * assuming equality for comparing an index with itself falls into the category of
25730 	 * "caching".
25731 	 *
25732 	 * Also, compareFn may be inconsistent, so skipping a call to compareFn here may
25733 	 * have an effect on the final result.  The specification does not require any
25734 	 * specific behavior for inconsistent compare functions, so again, this fast path
25735 	 * is OK.
25736 	 */
25737 
25738 	if (idx1 == idx2) {
25739 		DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld -> indices identical, quick exit",
25740 		                     (long) idx1, (long) idx2));
25741 		return 0;
25742 	}
25743 
25744 	have1 = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) idx1);
25745 	have2 = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) idx2);
25746 
25747 	DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld, have1=%ld, have2=%ld, val1=%!T, val2=%!T",
25748 	                     (long) idx1, (long) idx2, (long) have1, (long) have2,
25749 	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
25750 
25751 	if (have1) {
25752 		if (have2) {
25753 			;
25754 		} else {
25755 			ret = -1;
25756 			goto pop_ret;
25757 		}
25758 	} else {
25759 		if (have2) {
25760 			ret = 1;
25761 			goto pop_ret;
25762 		} else {
25763 			ret = 0;
25764 			goto pop_ret;
25765 		}
25766 	}
25767 
25768 	undef1 = duk_is_undefined(thr, -2);
25769 	undef2 = duk_is_undefined(thr, -1);
25770 	if (undef1) {
25771 		if (undef2) {
25772 			ret = 0;
25773 			goto pop_ret;
25774 		} else {
25775 			ret = 1;
25776 			goto pop_ret;
25777 		}
25778 	} else {
25779 		if (undef2) {
25780 			ret = -1;
25781 			goto pop_ret;
25782 		} else {
25783 			;
25784 		}
25785 	}
25786 
25787 	if (!duk_is_undefined(thr, idx_fn)) {
25788 		duk_double_t d;
25789 
25790 		/* No need to check callable; duk_call() will do that. */
25791 		duk_dup(thr, idx_fn);    /* -> [ ... x y fn ] */
25792 		duk_insert(thr, -3);     /* -> [ ... fn x y ] */
25793 		duk_call(thr, 2);        /* -> [ ... res ] */
25794 
25795 		/* ES5 is a bit vague about what to do if the return value is
25796 		 * not a number.  ES2015 provides a concrete description:
25797 		 * http://www.ecma-international.org/ecma-262/6.0/#sec-sortcompare.
25798 		 */
25799 
25800 		d = duk_to_number_m1(thr);
25801 		if (d < 0.0) {
25802 			ret = -1;
25803 		} else if (d > 0.0) {
25804 			ret = 1;
25805 		} else {
25806 			/* Because NaN compares to false, NaN is handled here
25807 			 * without an explicit check above.
25808 			 */
25809 			ret = 0;
25810 		}
25811 
25812 		duk_pop_nodecref_unsafe(thr);
25813 		DUK_DDD(DUK_DDDPRINT("-> result %ld (from comparefn, after coercion)", (long) ret));
25814 		return ret;
25815 	}
25816 
25817 	/* string compare is the default (a bit oddly) */
25818 
25819 	/* XXX: any special handling for plain array; causes repeated coercion now? */
25820 	h1 = duk_to_hstring(thr, -2);
25821 	h2 = duk_to_hstring_m1(thr);
25822 	DUK_ASSERT(h1 != NULL);
25823 	DUK_ASSERT(h2 != NULL);
25824 
25825 	ret = duk_js_string_compare(h1, h2);  /* retval is directly usable */
25826 	goto pop_ret;
25827 
25828  pop_ret:
25829 	duk_pop_2_unsafe(thr);
25830 	DUK_DDD(DUK_DDDPRINT("-> result %ld", (long) ret));
25831 	return ret;
25832 }
25833 
duk__array_sort_swap(duk_hthread * thr,duk_int_t l,duk_int_t r)25834 DUK_LOCAL void duk__array_sort_swap(duk_hthread *thr, duk_int_t l, duk_int_t r) {
25835 	duk_bool_t have_l, have_r;
25836 	duk_idx_t idx_obj = 1;  /* fixed offset in valstack */
25837 
25838 	if (l == r) {
25839 		return;
25840 	}
25841 
25842 	/* swap elements; deal with non-existent elements correctly */
25843 	have_l = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) l);
25844 	have_r = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) r);
25845 
25846 	if (have_r) {
25847 		/* right exists, [[Put]] regardless whether or not left exists */
25848 		duk_put_prop_index(thr, idx_obj, (duk_uarridx_t) l);
25849 	} else {
25850 		duk_del_prop_index(thr, idx_obj, (duk_uarridx_t) l);
25851 		duk_pop_undefined(thr);
25852 	}
25853 
25854 	if (have_l) {
25855 		duk_put_prop_index(thr, idx_obj, (duk_uarridx_t) r);
25856 	} else {
25857 		duk_del_prop_index(thr, idx_obj, (duk_uarridx_t) r);
25858 		duk_pop_undefined(thr);
25859 	}
25860 }
25861 
25862 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
25863 /* 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)25864 DUK_LOCAL void duk__debuglog_qsort_state(duk_hthread *thr, duk_int_t lo, duk_int_t hi, duk_int_t pivot) {
25865 	char buf[4096];
25866 	char *ptr = buf;
25867 	duk_int_t i, n;
25868 	n = (duk_int_t) duk_get_length(thr, 1);
25869 	if (n > 4000) {
25870 		n = 4000;
25871 	}
25872 	*ptr++ = '[';
25873 	for (i = 0; i < n; i++) {
25874 		if (i == pivot) {
25875 			*ptr++ = '|';
25876 		} else if (i == lo) {
25877 			*ptr++ = '<';
25878 		} else if (i == hi) {
25879 			*ptr++ = '>';
25880 		} else if (i >= lo && i <= hi) {
25881 			*ptr++ = '-';
25882 		} else {
25883 			*ptr++ = ' ';
25884 		}
25885 	}
25886 	*ptr++ = ']';
25887 	*ptr++ = '\0';
25888 
25889 	DUK_DDD(DUK_DDDPRINT("%s   (lo=%ld, hi=%ld, pivot=%ld)",
25890 	                     (const char *) buf, (long) lo, (long) hi, (long) pivot));
25891 }
25892 #endif
25893 
duk__array_qsort(duk_hthread * thr,duk_int_t lo,duk_int_t hi)25894 DUK_LOCAL void duk__array_qsort(duk_hthread *thr, duk_int_t lo, duk_int_t hi) {
25895 	duk_int_t p, l, r;
25896 
25897 	/* The lo/hi indices may be crossed and hi < 0 is possible at entry. */
25898 
25899 	DUK_DDD(DUK_DDDPRINT("duk__array_qsort: lo=%ld, hi=%ld, obj=%!T",
25900 	                     (long) lo, (long) hi, (duk_tval *) duk_get_tval(thr, 1)));
25901 
25902 	DUK_ASSERT_TOP(thr, 3);
25903 
25904 	/* In some cases it may be that lo > hi, or hi < 0; these
25905 	 * degenerate cases happen e.g. for empty arrays, and in
25906 	 * recursion leaves.
25907 	 */
25908 
25909 	/* trivial cases */
25910 	if (hi - lo < 1) {
25911 		DUK_DDD(DUK_DDDPRINT("degenerate case, return immediately"));
25912 		return;
25913 	}
25914 	DUK_ASSERT(hi > lo);
25915 	DUK_ASSERT(hi - lo + 1 >= 2);
25916 
25917 	/* randomized pivot selection */
25918 	p = lo + (duk_int_t) (DUK_UTIL_GET_RANDOM_DOUBLE(thr) * (duk_double_t) (hi - lo + 1));
25919 	DUK_ASSERT(p >= lo && p <= hi);
25920 	DUK_DDD(DUK_DDDPRINT("lo=%ld, hi=%ld, chose pivot p=%ld", (long) lo, (long) hi, (long) p));
25921 
25922 	/* move pivot out of the way */
25923 	duk__array_sort_swap(thr, p, lo);
25924 	p = lo;
25925 	DUK_DDD(DUK_DDDPRINT("pivot moved out of the way: %!T", (duk_tval *) duk_get_tval(thr, 1)));
25926 
25927 	l = lo + 1;
25928 	r = hi;
25929 	for (;;) {
25930 		/* find elements to swap */
25931 		for (;;) {
25932 			DUK_DDD(DUK_DDDPRINT("left scan: l=%ld, r=%ld, p=%ld",
25933 			                     (long) l, (long) r, (long) p));
25934 			if (l >= hi) {
25935 				break;
25936 			}
25937 			if (duk__array_sort_compare(thr, l, p) >= 0) {  /* !(l < p) */
25938 				break;
25939 			}
25940 			l++;
25941 		}
25942 		for (;;) {
25943 			DUK_DDD(DUK_DDDPRINT("right scan: l=%ld, r=%ld, p=%ld",
25944 			                     (long) l, (long) r, (long) p));
25945 			if (r <= lo) {
25946 				break;
25947 			}
25948 			if (duk__array_sort_compare(thr, p, r) >= 0) {  /* !(p < r) */
25949 				break;
25950 			}
25951 			r--;
25952 		}
25953 		if (l >= r) {
25954 			goto done;
25955 		}
25956 		DUK_ASSERT(l < r);
25957 
25958 		DUK_DDD(DUK_DDDPRINT("swap %ld and %ld", (long) l, (long) r));
25959 
25960 		duk__array_sort_swap(thr, l, r);
25961 
25962 		DUK_DDD(DUK_DDDPRINT("after swap: %!T", (duk_tval *) duk_get_tval(thr, 1)));
25963 		l++;
25964 		r--;
25965 	}
25966  done:
25967 	/* Note that 'l' and 'r' may cross, i.e. r < l */
25968 	DUK_ASSERT(l >= lo && l <= hi);
25969 	DUK_ASSERT(r >= lo && r <= hi);
25970 
25971 	/* XXX: there's no explicit recursion bound here now.  For the average
25972 	 * qsort recursion depth O(log n) that's not really necessary: e.g. for
25973 	 * 2**32 recursion depth would be about 32 which is OK.  However, qsort
25974 	 * worst case recursion depth is O(n) which may be a problem.
25975 	 */
25976 
25977 	/* move pivot to its final place */
25978 	DUK_DDD(DUK_DDDPRINT("before final pivot swap: %!T", (duk_tval *) duk_get_tval(thr, 1)));
25979 	duk__array_sort_swap(thr, lo, r);
25980 
25981 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
25982 	duk__debuglog_qsort_state(thr, lo, hi, r);
25983 #endif
25984 
25985 	DUK_DDD(DUK_DDDPRINT("recurse: pivot=%ld, obj=%!T", (long) r, (duk_tval *) duk_get_tval(thr, 1)));
25986 	duk__array_qsort(thr, lo, r - 1);
25987 	duk__array_qsort(thr, r + 1, hi);
25988 }
25989 
duk_bi_array_prototype_sort(duk_hthread * thr)25990 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_sort(duk_hthread *thr) {
25991 	duk_uint32_t len;
25992 
25993 	/* XXX: len >= 0x80000000 won't work below because a signed type
25994 	 * is needed by qsort.
25995 	 */
25996 	len = duk__push_this_obj_len_u32_limited(thr);
25997 
25998 	/* stack[0] = compareFn
25999 	 * stack[1] = ToObject(this)
26000 	 * stack[2] = ToUint32(length)
26001 	 */
26002 
26003 	if (len > 0) {
26004 		/* avoid degenerate cases, so that (len - 1) won't underflow */
26005 		duk__array_qsort(thr, (duk_int_t) 0, (duk_int_t) (len - 1));
26006 	}
26007 
26008 	DUK_ASSERT_TOP(thr, 3);
26009 	duk_pop_nodecref_unsafe(thr);
26010 	return 1;  /* return ToObject(this) */
26011 }
26012 
26013 /*
26014  *  splice()
26015  */
26016 
26017 /* XXX: this compiles to over 500 bytes now, even without special handling
26018  * for an array part.  Uses signed ints so does not handle full array range correctly.
26019  */
26020 
26021 /* XXX: can shift() / unshift() use the same helper?
26022  *   shift() is (close to?) <--> splice(0, 1)
26023  *   unshift is (close to?) <--> splice(0, 0, [items])?
26024  */
26025 
duk_bi_array_prototype_splice(duk_hthread * thr)26026 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_splice(duk_hthread *thr) {
26027 	duk_idx_t nargs;
26028 	duk_uint32_t len_u32;
26029 	duk_int_t len;
26030 	duk_bool_t have_delcount;
26031 	duk_int_t item_count;
26032 	duk_int_t act_start;
26033 	duk_int_t del_count;
26034 	duk_int_t i, n;
26035 
26036 	DUK_UNREF(have_delcount);
26037 
26038 	nargs = duk_get_top(thr);
26039 	if (nargs < 2) {
26040 		duk_set_top(thr, 2);
26041 		nargs = 2;
26042 		have_delcount = 0;
26043 	} else {
26044 		have_delcount = 1;
26045 	}
26046 
26047 	/* XXX: len >= 0x80000000 won't work below because we need to be
26048 	 * able to represent -len.
26049 	 */
26050 	len_u32 = duk__push_this_obj_len_u32_limited(thr);
26051 	len = (duk_int_t) len_u32;
26052 	DUK_ASSERT(len >= 0);
26053 
26054 	act_start = duk_to_int_clamped(thr, 0, -len, len);
26055 	if (act_start < 0) {
26056 		act_start = len + act_start;
26057 	}
26058 	DUK_ASSERT(act_start >= 0 && act_start <= len);
26059 
26060 #if defined(DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT)
26061 	if (have_delcount) {
26062 #endif
26063 		del_count = duk_to_int_clamped(thr, 1, 0, len - act_start);
26064 #if defined(DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT)
26065 	} else {
26066 		/* E5.1 standard behavior when deleteCount is not given would be
26067 		 * to treat it just like if 'undefined' was given, which coerces
26068 		 * ultimately to 0.  Real world behavior is to splice to the end
26069 		 * of array, see test-bi-array-proto-splice-no-delcount.js.
26070 		 */
26071 		del_count = len - act_start;
26072 	}
26073 #endif
26074 
26075 	DUK_ASSERT(nargs >= 2);
26076 	item_count = (duk_int_t) (nargs - 2);
26077 
26078 	DUK_ASSERT(del_count >= 0 && del_count <= len - act_start);
26079 	DUK_ASSERT(del_count + act_start <= len);
26080 
26081 	/* For now, restrict result array into 32-bit length range. */
26082 	if (((duk_double_t) len) - ((duk_double_t) del_count) + ((duk_double_t) item_count) > (duk_double_t) DUK_UINT32_MAX) {
26083 		DUK_D(DUK_DPRINT("Array.prototype.splice() would go beyond 32-bit length, throw"));
26084 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
26085 	}
26086 
26087 	duk_push_array(thr);
26088 
26089 	/* stack[0] = start
26090 	 * stack[1] = deleteCount
26091 	 * stack[2...nargs-1] = items
26092 	 * stack[nargs] = ToObject(this)               -3
26093 	 * stack[nargs+1] = ToUint32(length)           -2
26094 	 * stack[nargs+2] = result array               -1
26095 	 */
26096 
26097 	DUK_ASSERT_TOP(thr, nargs + 3);
26098 
26099 	/* Step 9: copy elements-to-be-deleted into the result array */
26100 
26101 	for (i = 0; i < del_count; i++) {
26102 		if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (act_start + i))) {
26103 			duk_xdef_prop_index_wec(thr, -2, (duk_uarridx_t) i);  /* throw flag irrelevant (false in std alg) */
26104 		} else {
26105 			duk_pop_undefined(thr);
26106 		}
26107 	}
26108 	duk_push_u32(thr, (duk_uint32_t) del_count);
26109 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
26110 
26111 	/* Steps 12 and 13: reorganize elements to make room for itemCount elements */
26112 
26113 	if (item_count < del_count) {
26114 		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 1
26115 		 * -> [ A B F G H ]          (conceptual intermediate step)
26116 		 * -> [ A B . F G H ]        (placeholder marked)
26117 		 *    [ A B C F G H ]        (actual result at this point, C will be replaced)
26118 		 */
26119 
26120 		DUK_ASSERT_TOP(thr, nargs + 3);
26121 
26122 		n = len - del_count;
26123 		for (i = act_start; i < n; i++) {
26124 			if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (i + del_count))) {
26125 				duk_put_prop_index(thr, -4, (duk_uarridx_t) (i + item_count));
26126 			} else {
26127 				duk_pop_undefined(thr);
26128 				duk_del_prop_index(thr, -3, (duk_uarridx_t) (i + item_count));
26129 			}
26130 		}
26131 
26132 		DUK_ASSERT_TOP(thr, nargs + 3);
26133 
26134 		/* loop iterator init and limit changed from standard algorithm */
26135 		n = len - del_count + item_count;
26136 		for (i = len - 1; i >= n; i--) {
26137 			duk_del_prop_index(thr, -3, (duk_uarridx_t) i);
26138 		}
26139 
26140 		DUK_ASSERT_TOP(thr, nargs + 3);
26141 	} else if (item_count > del_count) {
26142 		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 4
26143 		 * -> [ A B F G H ]          (conceptual intermediate step)
26144 		 * -> [ A B . . . . F G H ]  (placeholder marked)
26145 		 *    [ A B C D E F F G H ]  (actual result at this point)
26146 		 */
26147 
26148 		DUK_ASSERT_TOP(thr, nargs + 3);
26149 
26150 		/* loop iterator init and limit changed from standard algorithm */
26151 		for (i = len - del_count - 1; i >= act_start; i--) {
26152 			if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (i + del_count))) {
26153 				duk_put_prop_index(thr, -4, (duk_uarridx_t) (i + item_count));
26154 			} else {
26155 				duk_pop_undefined(thr);
26156 				duk_del_prop_index(thr, -3, (duk_uarridx_t) (i + item_count));
26157 			}
26158 		}
26159 
26160 		DUK_ASSERT_TOP(thr, nargs + 3);
26161 	} else {
26162 		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 3
26163 		 * -> [ A B F G H ]          (conceptual intermediate step)
26164 		 * -> [ A B . . . F G H ]    (placeholder marked)
26165 		 *    [ A B C D E F G H ]    (actual result at this point)
26166 		 */
26167 	}
26168 	DUK_ASSERT_TOP(thr, nargs + 3);
26169 
26170 	/* Step 15: insert itemCount elements into the hole made above */
26171 
26172 	for (i = 0; i < item_count; i++) {
26173 		duk_dup(thr, i + 2);  /* args start at index 2 */
26174 		duk_put_prop_index(thr, -4, (duk_uarridx_t) (act_start + i));
26175 	}
26176 
26177 	/* Step 16: update length; note that the final length may be above 32 bit range
26178 	 * (but we checked above that this isn't the case here)
26179 	 */
26180 
26181 	duk_push_u32(thr, (duk_uint32_t) (len - del_count + item_count));
26182 	duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);
26183 
26184 	/* result array is already at the top of stack */
26185 	DUK_ASSERT_TOP(thr, nargs + 3);
26186 	return 1;
26187 }
26188 
26189 /*
26190  *  reverse()
26191  */
26192 
duk_bi_array_prototype_reverse(duk_hthread * thr)26193 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reverse(duk_hthread *thr) {
26194 	duk_uint32_t len;
26195 	duk_uint32_t middle;
26196 	duk_uint32_t lower, upper;
26197 	duk_bool_t have_lower, have_upper;
26198 
26199 	len = duk__push_this_obj_len_u32(thr);
26200 	middle = len / 2;
26201 
26202 	/* If len <= 1, middle will be 0 and for-loop bails out
26203 	 * immediately (0 < 0 -> false).
26204 	 */
26205 
26206 	for (lower = 0; lower < middle; lower++) {
26207 		DUK_ASSERT(len >= 2);
26208 		DUK_ASSERT_TOP(thr, 2);
26209 
26210 		DUK_ASSERT(len >= lower + 1);
26211 		upper = len - lower - 1;
26212 
26213 		have_lower = duk_get_prop_index(thr, -2, (duk_uarridx_t) lower);
26214 		have_upper = duk_get_prop_index(thr, -3, (duk_uarridx_t) upper);
26215 
26216 		/* [ ToObject(this) ToUint32(length) lowerValue upperValue ] */
26217 
26218 		if (have_upper) {
26219 			duk_put_prop_index(thr, -4, (duk_uarridx_t) lower);
26220 		} else {
26221 			duk_del_prop_index(thr, -4, (duk_uarridx_t) lower);
26222 			duk_pop_undefined(thr);
26223 		}
26224 
26225 		if (have_lower) {
26226 			duk_put_prop_index(thr, -3, (duk_uarridx_t) upper);
26227 		} else {
26228 			duk_del_prop_index(thr, -3, (duk_uarridx_t) upper);
26229 			duk_pop_undefined(thr);
26230 		}
26231 
26232 		DUK_ASSERT_TOP(thr, 2);
26233 	}
26234 
26235 	DUK_ASSERT_TOP(thr, 2);
26236 	duk_pop_unsafe(thr);  /* -> [ ToObject(this) ] */
26237 	return 1;
26238 }
26239 
26240 /*
26241  *  slice()
26242  */
26243 
duk_bi_array_prototype_slice(duk_hthread * thr)26244 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_slice(duk_hthread *thr) {
26245 	duk_uint32_t len_u32;
26246 	duk_int_t len;
26247 	duk_int_t start, end;
26248 	duk_int_t i;
26249 	duk_uarridx_t idx;
26250 	duk_uint32_t res_length = 0;
26251 
26252 	/* XXX: len >= 0x80000000 won't work below because we need to be
26253 	 * able to represent -len.
26254 	 */
26255 	len_u32 = duk__push_this_obj_len_u32_limited(thr);
26256 	len = (duk_int_t) len_u32;
26257 	DUK_ASSERT(len >= 0);
26258 
26259 	duk_push_array(thr);
26260 
26261 	/* stack[0] = start
26262 	 * stack[1] = end
26263 	 * stack[2] = ToObject(this)
26264 	 * stack[3] = ToUint32(length)
26265 	 * stack[4] = result array
26266 	 */
26267 
26268 	start = duk_to_int_clamped(thr, 0, -len, len);
26269 	if (start < 0) {
26270 		start = len + start;
26271 	}
26272 	/* XXX: could duk_is_undefined() provide defaulting undefined to 'len'
26273 	 * (the upper limit)?
26274 	 */
26275 	if (duk_is_undefined(thr, 1)) {
26276 		end = len;
26277 	} else {
26278 		end = duk_to_int_clamped(thr, 1, -len, len);
26279 		if (end < 0) {
26280 			end = len + end;
26281 		}
26282 	}
26283 	DUK_ASSERT(start >= 0 && start <= len);
26284 	DUK_ASSERT(end >= 0 && end <= len);
26285 
26286 	idx = 0;
26287 	for (i = start; i < end; i++) {
26288 		DUK_ASSERT_TOP(thr, 5);
26289 		if (duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
26290 			duk_xdef_prop_index_wec(thr, 4, idx);
26291 			res_length = idx + 1;
26292 		} else {
26293 			duk_pop_undefined(thr);
26294 		}
26295 		idx++;
26296 		DUK_ASSERT_TOP(thr, 5);
26297 	}
26298 
26299 	duk_push_u32(thr, res_length);
26300 	duk_xdef_prop_stridx_short(thr, 4, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
26301 
26302 	DUK_ASSERT_TOP(thr, 5);
26303 	return 1;
26304 }
26305 
26306 /*
26307  *  shift()
26308  */
26309 
duk_bi_array_prototype_shift(duk_hthread * thr)26310 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_shift(duk_hthread *thr) {
26311 	duk_uint32_t len;
26312 	duk_uint32_t i;
26313 
26314 	len = duk__push_this_obj_len_u32(thr);
26315 	if (len == 0) {
26316 		duk_push_int(thr, 0);
26317 		duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
26318 		return 0;
26319 	}
26320 
26321 	duk_get_prop_index(thr, 0, 0);
26322 
26323 	/* stack[0] = object (this)
26324 	 * stack[1] = ToUint32(length)
26325 	 * stack[2] = elem at index 0 (retval)
26326 	 */
26327 
26328 	for (i = 1; i < len; i++) {
26329 		DUK_ASSERT_TOP(thr, 3);
26330 		if (duk_get_prop_index(thr, 0, (duk_uarridx_t) i)) {
26331 			/* fromPresent = true */
26332 			duk_put_prop_index(thr, 0, (duk_uarridx_t) (i - 1));
26333 		} else {
26334 			/* fromPresent = false */
26335 			duk_del_prop_index(thr, 0, (duk_uarridx_t) (i - 1));
26336 			duk_pop_undefined(thr);
26337 		}
26338 	}
26339 	duk_del_prop_index(thr, 0, (duk_uarridx_t) (len - 1));
26340 
26341 	duk_push_u32(thr, (duk_uint32_t) (len - 1));
26342 	duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
26343 
26344 	DUK_ASSERT_TOP(thr, 3);
26345 	return 1;
26346 }
26347 
26348 /*
26349  *  unshift()
26350  */
26351 
duk_bi_array_prototype_unshift(duk_hthread * thr)26352 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_unshift(duk_hthread *thr) {
26353 	duk_idx_t nargs;
26354 	duk_uint32_t len;
26355 	duk_uint32_t i;
26356 
26357 	nargs = duk_get_top(thr);
26358 	len = duk__push_this_obj_len_u32(thr);
26359 
26360 	/* stack[0...nargs-1] = unshift args (vararg)
26361 	 * stack[nargs] = ToObject(this)
26362 	 * stack[nargs+1] = ToUint32(length)
26363 	 */
26364 
26365 	DUK_ASSERT_TOP(thr, nargs + 2);
26366 
26367 	/* Note: unshift() may operate on indices above unsigned 32-bit range
26368 	 * and the final length may be >= 2**32.  However, we restrict the
26369 	 * final result to 32-bit range for practicality.
26370 	 */
26371 
26372 	if (len + (duk_uint32_t) nargs < len) {
26373 		DUK_D(DUK_DPRINT("Array.prototype.unshift() would go beyond 32-bit length, throw"));
26374 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
26375 	}
26376 
26377 	i = len;
26378 	while (i > 0) {
26379 		DUK_ASSERT_TOP(thr, nargs + 2);
26380 		i--;
26381 		/* k+argCount-1; note that may be above 32-bit range */
26382 
26383 		if (duk_get_prop_index(thr, -2, (duk_uarridx_t) i)) {
26384 			/* fromPresent = true */
26385 			/* [ ... ToObject(this) ToUint32(length) val ] */
26386 			duk_put_prop_index(thr, -3, (duk_uarridx_t) (i + (duk_uint32_t) nargs));  /* -> [ ... ToObject(this) ToUint32(length) ] */
26387 		} else {
26388 			/* fromPresent = false */
26389 			/* [ ... ToObject(this) ToUint32(length) val ] */
26390 			duk_pop_undefined(thr);
26391 			duk_del_prop_index(thr, -2, (duk_uarridx_t) (i + (duk_uint32_t) nargs));  /* -> [ ... ToObject(this) ToUint32(length) ] */
26392 		}
26393 		DUK_ASSERT_TOP(thr, nargs + 2);
26394 	}
26395 
26396 	for (i = 0; i < (duk_uint32_t) nargs; i++) {
26397 		DUK_ASSERT_TOP(thr, nargs + 2);
26398 		duk_dup(thr, (duk_idx_t) i);  /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */
26399 		duk_put_prop_index(thr, -3, (duk_uarridx_t) i);
26400 		DUK_ASSERT_TOP(thr, nargs + 2);
26401 	}
26402 
26403 	DUK_ASSERT_TOP(thr, nargs + 2);
26404 	duk_push_u32(thr, len + (duk_uint32_t) nargs);
26405 	duk_dup_top(thr);  /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */
26406 	duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);
26407 	return 1;
26408 }
26409 
26410 /*
26411  *  indexOf(), lastIndexOf()
26412  */
26413 
duk_bi_array_prototype_indexof_shared(duk_hthread * thr)26414 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_hthread *thr) {
26415 	duk_idx_t nargs;
26416 	duk_int_t i, len;
26417 	duk_int_t from_idx;
26418 	duk_small_int_t idx_step = duk_get_current_magic(thr);  /* idx_step is +1 for indexOf, -1 for lastIndexOf */
26419 
26420 	/* lastIndexOf() needs to be a vararg function because we must distinguish
26421 	 * between an undefined fromIndex and a "not given" fromIndex; indexOf() is
26422 	 * made vararg for symmetry although it doesn't strictly need to be.
26423 	 */
26424 
26425 	nargs = duk_get_top(thr);
26426 	duk_set_top(thr, 2);
26427 
26428 	/* XXX: must be able to represent -len */
26429 	len = (duk_int_t) duk__push_this_obj_len_u32_limited(thr);
26430 	if (len == 0) {
26431 		goto not_found;
26432 	}
26433 
26434 	/* Index clamping is a bit tricky, we must ensure that we'll only iterate
26435 	 * through elements that exist and that the specific requirements from E5.1
26436 	 * Sections 15.4.4.14 and 15.4.4.15 are fulfilled; especially:
26437 	 *
26438 	 *   - indexOf: clamp to [-len,len], negative handling -> [0,len],
26439 	 *     if clamped result is len, for-loop bails out immediately
26440 	 *
26441 	 *   - lastIndexOf: clamp to [-len-1, len-1], negative handling -> [-1, len-1],
26442 	 *     if clamped result is -1, for-loop bails out immediately
26443 	 *
26444 	 * If fromIndex is not given, ToInteger(undefined) = 0, which is correct
26445 	 * for indexOf() but incorrect for lastIndexOf().  Hence special handling,
26446 	 * and why lastIndexOf() needs to be a vararg function.
26447 	 */
26448 
26449 	if (nargs >= 2) {
26450 		/* indexOf: clamp fromIndex to [-len, len]
26451 		 * (if fromIndex == len, for-loop terminates directly)
26452 		 *
26453 		 * lastIndexOf: clamp fromIndex to [-len - 1, len - 1]
26454 		 * (if clamped to -len-1 -> fromIndex becomes -1, terminates for-loop directly)
26455 		 */
26456 		from_idx = duk_to_int_clamped(thr,
26457 		                              1,
26458 		                              (idx_step > 0 ? -len : -len - 1),
26459 		                              (idx_step > 0 ? len : len - 1));
26460 		if (from_idx < 0) {
26461 			/* for lastIndexOf, result may be -1 (mark immediate termination) */
26462 			from_idx = len + from_idx;
26463 		}
26464 	} else {
26465 		/* for indexOf, ToInteger(undefined) would be 0, i.e. correct, but
26466 		 * handle both indexOf and lastIndexOf specially here.
26467 		 */
26468 		if (idx_step > 0) {
26469 			from_idx = 0;
26470 		} else {
26471 			from_idx = len - 1;
26472 		}
26473 	}
26474 
26475 	/* stack[0] = searchElement
26476 	 * stack[1] = fromIndex
26477 	 * stack[2] = object
26478 	 * stack[3] = length (not needed, but not popped above)
26479 	 */
26480 
26481 	for (i = from_idx; i >= 0 && i < len; i += idx_step) {
26482 		DUK_ASSERT_TOP(thr, 4);
26483 
26484 		if (duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
26485 			DUK_ASSERT_TOP(thr, 5);
26486 			if (duk_strict_equals(thr, 0, 4)) {
26487 				duk_push_int(thr, i);
26488 				return 1;
26489 			}
26490 		}
26491 
26492 		duk_pop_unsafe(thr);
26493 	}
26494 
26495  not_found:
26496 	duk_push_int(thr, -1);
26497 	return 1;
26498 }
26499 
26500 /*
26501  *  every(), some(), forEach(), map(), filter()
26502  */
26503 
26504 #define DUK__ITER_EVERY    0
26505 #define DUK__ITER_SOME     1
26506 #define DUK__ITER_FOREACH  2
26507 #define DUK__ITER_MAP      3
26508 #define DUK__ITER_FILTER   4
26509 
26510 /* XXX: This helper is a bit awkward because the handling for the different iteration
26511  * callers is quite different.  This now compiles to a bit less than 500 bytes, so with
26512  * 5 callers the net result is about 100 bytes / caller.
26513  */
26514 
duk_bi_array_prototype_iter_shared(duk_hthread * thr)26515 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_hthread *thr) {
26516 	duk_uint32_t len;
26517 	duk_uint32_t i;
26518 	duk_uarridx_t k;
26519 	duk_bool_t bval;
26520 	duk_small_int_t iter_type = duk_get_current_magic(thr);
26521 	duk_uint32_t res_length = 0;
26522 
26523 	/* each call this helper serves has nargs==2 */
26524 	DUK_ASSERT_TOP(thr, 2);
26525 
26526 	len = duk__push_this_obj_len_u32(thr);
26527 	duk_require_callable(thr, 0);
26528 	/* if thisArg not supplied, behave as if undefined was supplied */
26529 
26530 	if (iter_type == DUK__ITER_MAP || iter_type == DUK__ITER_FILTER) {
26531 		duk_push_array(thr);
26532 	} else {
26533 		duk_push_undefined(thr);
26534 	}
26535 
26536 	/* stack[0] = callback
26537 	 * stack[1] = thisArg
26538 	 * stack[2] = object
26539 	 * stack[3] = ToUint32(length)  (unused, but avoid unnecessary pop)
26540 	 * stack[4] = result array (or undefined)
26541 	 */
26542 
26543 	k = 0;  /* result index for filter() */
26544 	for (i = 0; i < len; i++) {
26545 		DUK_ASSERT_TOP(thr, 5);
26546 
26547 		if (!duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
26548 			/* For 'map' trailing missing elements don't invoke the
26549 			 * callback but count towards the result length.
26550 			 */
26551 			if (iter_type == DUK__ITER_MAP) {
26552 				res_length = i + 1;
26553 			}
26554 			duk_pop_undefined(thr);
26555 			continue;
26556 		}
26557 
26558 		/* The original value needs to be preserved for filter(), hence
26559 		 * this funny order.  We can't re-get the value because of side
26560 		 * effects.
26561 		 */
26562 
26563 		duk_dup_0(thr);
26564 		duk_dup_1(thr);
26565 		duk_dup_m3(thr);
26566 		duk_push_u32(thr, i);
26567 		duk_dup_2(thr);  /* [ ... val callback thisArg val i obj ] */
26568 		duk_call_method(thr, 3); /* -> [ ... val retval ] */
26569 
26570 		switch (iter_type) {
26571 		case DUK__ITER_EVERY:
26572 			bval = duk_to_boolean(thr, -1);
26573 			if (!bval) {
26574 				/* stack top contains 'false' */
26575 				return 1;
26576 			}
26577 			break;
26578 		case DUK__ITER_SOME:
26579 			bval = duk_to_boolean(thr, -1);
26580 			if (bval) {
26581 				/* stack top contains 'true' */
26582 				return 1;
26583 			}
26584 			break;
26585 		case DUK__ITER_FOREACH:
26586 			/* nop */
26587 			break;
26588 		case DUK__ITER_MAP:
26589 			duk_dup_top(thr);
26590 			duk_xdef_prop_index_wec(thr, 4, (duk_uarridx_t) i);  /* retval to result[i] */
26591 			res_length = i + 1;
26592 			break;
26593 		case DUK__ITER_FILTER:
26594 			bval = duk_to_boolean(thr, -1);
26595 			if (bval) {
26596 				duk_dup_m2(thr);  /* orig value */
26597 				duk_xdef_prop_index_wec(thr, 4, (duk_uarridx_t) k);
26598 				k++;
26599 				res_length = k;
26600 			}
26601 			break;
26602 		default:
26603 			DUK_UNREACHABLE();
26604 			break;
26605 		}
26606 		duk_pop_2_unsafe(thr);
26607 
26608 		DUK_ASSERT_TOP(thr, 5);
26609 	}
26610 
26611 	switch (iter_type) {
26612 	case DUK__ITER_EVERY:
26613 		duk_push_true(thr);
26614 		break;
26615 	case DUK__ITER_SOME:
26616 		duk_push_false(thr);
26617 		break;
26618 	case DUK__ITER_FOREACH:
26619 		duk_push_undefined(thr);
26620 		break;
26621 	case DUK__ITER_MAP:
26622 	case DUK__ITER_FILTER:
26623 		DUK_ASSERT_TOP(thr, 5);
26624 		DUK_ASSERT(duk_is_array(thr, -1));  /* topmost element is the result array already */
26625 		duk_push_u32(thr, res_length);
26626 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
26627 		break;
26628 	default:
26629 		DUK_UNREACHABLE();
26630 		break;
26631 	}
26632 
26633 	return 1;
26634 }
26635 
26636 /*
26637  *  reduce(), reduceRight()
26638  */
26639 
duk_bi_array_prototype_reduce_shared(duk_hthread * thr)26640 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_hthread *thr) {
26641 	duk_idx_t nargs;
26642 	duk_bool_t have_acc;
26643 	duk_uint32_t i, len;
26644 	duk_small_int_t idx_step = duk_get_current_magic(thr);  /* idx_step is +1 for reduce, -1 for reduceRight */
26645 
26646 	/* We're a varargs function because we need to detect whether
26647 	 * initialValue was given or not.
26648 	 */
26649 	nargs = duk_get_top(thr);
26650 	DUK_DDD(DUK_DDDPRINT("nargs=%ld", (long) nargs));
26651 
26652 	duk_set_top(thr, 2);
26653 	len = duk__push_this_obj_len_u32(thr);
26654 	duk_require_callable(thr, 0);
26655 
26656 	/* stack[0] = callback fn
26657 	 * stack[1] = initialValue
26658 	 * stack[2] = object (coerced this)
26659 	 * stack[3] = length (not needed, but not popped above)
26660 	 * stack[4] = accumulator
26661 	 */
26662 
26663 	have_acc = 0;
26664 	if (nargs >= 2) {
26665 		duk_dup_1(thr);
26666 		have_acc = 1;
26667 	}
26668 	DUK_DDD(DUK_DDDPRINT("have_acc=%ld, acc=%!T",
26669 	                     (long) have_acc, (duk_tval *) duk_get_tval(thr, 3)));
26670 
26671 	/* For len == 0, i is initialized to len - 1 which underflows.
26672 	 * The condition (i < len) will then exit the for-loop on the
26673 	 * first round which is correct.  Similarly, loop termination
26674 	 * happens by i underflowing.
26675 	 */
26676 
26677 	for (i = (idx_step >= 0 ? 0 : len - 1);
26678 	     i < len;  /* i >= 0 would always be true */
26679 	     i += (duk_uint32_t) idx_step) {
26680 		DUK_DDD(DUK_DDDPRINT("i=%ld, len=%ld, have_acc=%ld, top=%ld, acc=%!T",
26681 		                     (long) i, (long) len, (long) have_acc,
26682 		                     (long) duk_get_top(thr),
26683 		                     (duk_tval *) duk_get_tval(thr, 4)));
26684 
26685 		DUK_ASSERT((have_acc && duk_get_top(thr) == 5) ||
26686 		           (!have_acc && duk_get_top(thr) == 4));
26687 
26688 		if (!duk_has_prop_index(thr, 2, (duk_uarridx_t) i)) {
26689 			continue;
26690 		}
26691 
26692 		if (!have_acc) {
26693 			DUK_ASSERT_TOP(thr, 4);
26694 			duk_get_prop_index(thr, 2, (duk_uarridx_t) i);
26695 			have_acc = 1;
26696 			DUK_ASSERT_TOP(thr, 5);
26697 		} else {
26698 			DUK_ASSERT_TOP(thr, 5);
26699 			duk_dup_0(thr);
26700 			duk_dup(thr, 4);
26701 			duk_get_prop_index(thr, 2, (duk_uarridx_t) i);
26702 			duk_push_u32(thr, i);
26703 			duk_dup_2(thr);
26704 			DUK_DDD(DUK_DDDPRINT("calling reduce function: func=%!T, prev=%!T, curr=%!T, idx=%!T, obj=%!T",
26705 			                     (duk_tval *) duk_get_tval(thr, -5), (duk_tval *) duk_get_tval(thr, -4),
26706 			                     (duk_tval *) duk_get_tval(thr, -3), (duk_tval *) duk_get_tval(thr, -2),
26707 			                     (duk_tval *) duk_get_tval(thr, -1)));
26708 			duk_call(thr, 4);
26709 			DUK_DDD(DUK_DDDPRINT("-> result: %!T", (duk_tval *) duk_get_tval(thr, -1)));
26710 			duk_replace(thr, 4);
26711 			DUK_ASSERT_TOP(thr, 5);
26712 		}
26713 	}
26714 
26715 	if (!have_acc) {
26716 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
26717 	}
26718 
26719 	DUK_ASSERT_TOP(thr, 5);
26720 	return 1;
26721 }
26722 
26723 #endif  /* DUK_USE_ARRAY_BUILTIN */
26724 
26725 /* automatic undefs */
26726 #undef DUK__ARRAY_MID_JOIN_LIMIT
26727 #undef DUK__ITER_EVERY
26728 #undef DUK__ITER_FILTER
26729 #undef DUK__ITER_FOREACH
26730 #undef DUK__ITER_MAP
26731 #undef DUK__ITER_SOME
26732 /*
26733  *  Boolean built-ins
26734  */
26735 
26736 /* #include duk_internal.h -> already included */
26737 
26738 #if defined(DUK_USE_BOOLEAN_BUILTIN)
26739 
26740 /* Shared helper to provide toString() and valueOf().  Checks 'this', gets
26741  * the primitive value to stack top, and optionally coerces with ToString().
26742  */
duk_bi_boolean_prototype_tostring_shared(duk_hthread * thr)26743 DUK_INTERNAL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_hthread *thr) {
26744 	duk_tval *tv;
26745 	duk_hobject *h;
26746 	duk_small_int_t coerce_tostring = duk_get_current_magic(thr);
26747 
26748 	/* XXX: there is room to use a shared helper here, many built-ins
26749 	 * check the 'this' type, and if it's an object, check its class,
26750 	 * then get its internal value, etc.
26751 	 */
26752 
26753 	duk_push_this(thr);
26754 	tv = duk_get_tval(thr, -1);
26755 	DUK_ASSERT(tv != NULL);
26756 
26757 	if (DUK_TVAL_IS_BOOLEAN(tv)) {
26758 		goto type_ok;
26759 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
26760 		h = DUK_TVAL_GET_OBJECT(tv);
26761 		DUK_ASSERT(h != NULL);
26762 
26763 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_BOOLEAN) {
26764 			duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
26765 			DUK_ASSERT(duk_is_boolean(thr, -1));
26766 			goto type_ok;
26767 		}
26768 	}
26769 
26770 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
26771 	/* never here */
26772 
26773  type_ok:
26774 	if (coerce_tostring) {
26775 		duk_to_string(thr, -1);
26776 	}
26777 	return 1;
26778 }
26779 
duk_bi_boolean_constructor(duk_hthread * thr)26780 DUK_INTERNAL duk_ret_t duk_bi_boolean_constructor(duk_hthread *thr) {
26781 	duk_hobject *h_this;
26782 
26783 	duk_to_boolean(thr, 0);
26784 
26785 	if (duk_is_constructor_call(thr)) {
26786 		/* XXX: helper; rely on Boolean.prototype as being non-writable, non-configurable */
26787 		duk_push_this(thr);
26788 		h_this = duk_known_hobject(thr, -1);
26789 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE]);
26790 
26791 		DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_BOOLEAN);
26792 
26793 		duk_dup_0(thr);  /* -> [ val obj val ] */
26794 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);  /* XXX: proper flags? */
26795 	}  /* unbalanced stack */
26796 
26797 	return 1;
26798 }
26799 
26800 #endif  /* DUK_USE_BOOLEAN_BUILTIN */
26801 /*
26802  *  ES2015 TypedArray and Node.js Buffer built-ins
26803  */
26804 
26805 /* #include duk_internal.h -> already included */
26806 
26807 /*
26808  *  Helpers for buffer handling, enabled with DUK_USE_BUFFEROBJECT_SUPPORT.
26809  */
26810 
26811 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
26812 /* Map class number (minus DUK_HOBJECT_CLASS_BUFOBJ_MIN) to a bidx for the
26813  * default internal prototype.
26814  */
26815 static const duk_uint8_t duk__buffer_proto_from_classnum[] = {
26816 	DUK_BIDX_ARRAYBUFFER_PROTOTYPE,
26817 	DUK_BIDX_DATAVIEW_PROTOTYPE,
26818 	DUK_BIDX_INT8ARRAY_PROTOTYPE,
26819 	DUK_BIDX_UINT8ARRAY_PROTOTYPE,
26820 	DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
26821 	DUK_BIDX_INT16ARRAY_PROTOTYPE,
26822 	DUK_BIDX_UINT16ARRAY_PROTOTYPE,
26823 	DUK_BIDX_INT32ARRAY_PROTOTYPE,
26824 	DUK_BIDX_UINT32ARRAY_PROTOTYPE,
26825 	DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
26826 	DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
26827 };
26828 
26829 /* Map DUK_HBUFOBJ_ELEM_xxx to duk_hobject class number.
26830  * Sync with duk_hbufobj.h and duk_hobject.h.
26831  */
26832 static const duk_uint8_t duk__buffer_class_from_elemtype[9] = {
26833 	DUK_HOBJECT_CLASS_UINT8ARRAY,
26834 	DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY,
26835 	DUK_HOBJECT_CLASS_INT8ARRAY,
26836 	DUK_HOBJECT_CLASS_UINT16ARRAY,
26837 	DUK_HOBJECT_CLASS_INT16ARRAY,
26838 	DUK_HOBJECT_CLASS_UINT32ARRAY,
26839 	DUK_HOBJECT_CLASS_INT32ARRAY,
26840 	DUK_HOBJECT_CLASS_FLOAT32ARRAY,
26841 	DUK_HOBJECT_CLASS_FLOAT64ARRAY
26842 };
26843 
26844 /* Map DUK_HBUFOBJ_ELEM_xxx to prototype object built-in index.
26845  * Sync with duk_hbufobj.h.
26846  */
26847 static const duk_uint8_t duk__buffer_proto_from_elemtype[9] = {
26848 	DUK_BIDX_UINT8ARRAY_PROTOTYPE,
26849 	DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
26850 	DUK_BIDX_INT8ARRAY_PROTOTYPE,
26851 	DUK_BIDX_UINT16ARRAY_PROTOTYPE,
26852 	DUK_BIDX_INT16ARRAY_PROTOTYPE,
26853 	DUK_BIDX_UINT32ARRAY_PROTOTYPE,
26854 	DUK_BIDX_INT32ARRAY_PROTOTYPE,
26855 	DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
26856 	DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
26857 };
26858 
26859 /* Map DUK__FLD_xxx to byte size. */
26860 static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6] = {
26861 	1,  /* DUK__FLD_8BIT */
26862 	2,  /* DUK__FLD_16BIT */
26863 	4,  /* DUK__FLD_32BIT */
26864 	4,  /* DUK__FLD_FLOAT */
26865 	8,  /* DUK__FLD_DOUBLE */
26866 	0   /* DUK__FLD_VARINT; not relevant here */
26867 };
26868 
26869 /* Bitfield for each DUK_HBUFOBJ_ELEM_xxx indicating which element types
26870  * are compatible with a blind byte copy for the TypedArray set() method (also
26871  * used for TypedArray constructor).  Array index is target buffer elem type,
26872  * bitfield indicates compatible source types.  The types must have same byte
26873  * size and they must be coercion compatible.
26874  */
26875 #if !defined(DUK_USE_PREFER_SIZE)
26876 static duk_uint16_t duk__buffer_elemtype_copy_compatible[9] = {
26877 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT8 */
26878 	(1U << DUK_HBUFOBJ_ELEM_UINT8) |
26879 		(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) |
26880 		(1U << DUK_HBUFOBJ_ELEM_INT8),
26881 
26882 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT8CLAMPED
26883 	 * Note: INT8 is -not- copy compatible, e.g. -1 would coerce to 0x00.
26884 	 */
26885 	(1U << DUK_HBUFOBJ_ELEM_UINT8) |
26886 		(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED),
26887 
26888 	/* xxx -> DUK_HBUFOBJ_ELEM_INT8 */
26889 	(1U << DUK_HBUFOBJ_ELEM_UINT8) |
26890 		(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) |
26891 		(1U << DUK_HBUFOBJ_ELEM_INT8),
26892 
26893 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT16 */
26894 	(1U << DUK_HBUFOBJ_ELEM_UINT16) |
26895 		(1U << DUK_HBUFOBJ_ELEM_INT16),
26896 
26897 	/* xxx -> DUK_HBUFOBJ_ELEM_INT16 */
26898 	(1U << DUK_HBUFOBJ_ELEM_UINT16) |
26899 		(1U << DUK_HBUFOBJ_ELEM_INT16),
26900 
26901 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT32 */
26902 	(1U << DUK_HBUFOBJ_ELEM_UINT32) |
26903 		(1U << DUK_HBUFOBJ_ELEM_INT32),
26904 
26905 	/* xxx -> DUK_HBUFOBJ_ELEM_INT32 */
26906 	(1U << DUK_HBUFOBJ_ELEM_UINT32) |
26907 		(1U << DUK_HBUFOBJ_ELEM_INT32),
26908 
26909 	/* xxx -> DUK_HBUFOBJ_ELEM_FLOAT32 */
26910 	(1U << DUK_HBUFOBJ_ELEM_FLOAT32),
26911 
26912 	/* xxx -> DUK_HBUFOBJ_ELEM_FLOAT64 */
26913 	(1U << DUK_HBUFOBJ_ELEM_FLOAT64)
26914 };
26915 #endif  /* !DUK_USE_PREFER_SIZE */
26916 
duk__hbufobj_promote_this(duk_hthread * thr)26917 DUK_LOCAL duk_hbufobj *duk__hbufobj_promote_this(duk_hthread *thr) {
26918 	duk_tval *tv_dst;
26919 	duk_hbufobj *res;
26920 
26921 	duk_push_this(thr);
26922 	DUK_ASSERT(duk_is_buffer(thr, -1));
26923 	res = (duk_hbufobj *) duk_to_hobject(thr, -1);
26924 	DUK_HBUFOBJ_ASSERT_VALID(res);
26925 	DUK_DD(DUK_DDPRINT("promoted 'this' automatically to an ArrayBuffer: %!iT", duk_get_tval(thr, -1)));
26926 
26927 	tv_dst = duk_get_borrowed_this_tval(thr);
26928 	DUK_TVAL_SET_OBJECT_UPDREF(thr, tv_dst, (duk_hobject *) res);
26929 	duk_pop(thr);
26930 
26931 	return res;
26932 }
26933 
26934 #define DUK__BUFOBJ_FLAG_THROW    (1 << 0)
26935 #define DUK__BUFOBJ_FLAG_PROMOTE  (1 << 1)
26936 
26937 /* Shared helper.  When DUK__BUFOBJ_FLAG_PROMOTE is given, the return value is
26938  * always a duk_hbufobj *.  Without the flag the return value can also be a
26939  * plain buffer, and the caller must check for it using DUK_HEAPHDR_IS_BUFFER().
26940  */
duk__getrequire_bufobj_this(duk_hthread * thr,duk_small_uint_t flags)26941 DUK_LOCAL duk_heaphdr *duk__getrequire_bufobj_this(duk_hthread *thr, duk_small_uint_t flags) {
26942 	duk_tval *tv;
26943 	duk_hbufobj *h_this;
26944 
26945 	DUK_ASSERT(thr != NULL);
26946 
26947 	tv = duk_get_borrowed_this_tval(thr);
26948 	DUK_ASSERT(tv != NULL);
26949 
26950 	if (DUK_TVAL_IS_OBJECT(tv)) {
26951 		h_this = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
26952 		DUK_ASSERT(h_this != NULL);
26953 		if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_this)) {
26954 			DUK_HBUFOBJ_ASSERT_VALID(h_this);
26955 			return (duk_heaphdr *) h_this;
26956 		}
26957 	} else if (DUK_TVAL_IS_BUFFER(tv)) {
26958 		if (flags & DUK__BUFOBJ_FLAG_PROMOTE) {
26959 			/* Promote a plain buffer to a Uint8Array.  This is very
26960 			 * inefficient but allows plain buffer to be used wherever an
26961 			 * Uint8Array is used with very small cost; hot path functions
26962 			 * like index read/write calls should provide direct buffer
26963 			 * support to avoid promotion.
26964 			 */
26965 			/* XXX: make this conditional to a flag if call sites need it? */
26966 			h_this = duk__hbufobj_promote_this(thr);
26967 			DUK_ASSERT(h_this != NULL);
26968 			DUK_HBUFOBJ_ASSERT_VALID(h_this);
26969 			return (duk_heaphdr *) h_this;
26970 		} else {
26971 			/* XXX: ugly, share return pointer for duk_hbuffer. */
26972 			return (duk_heaphdr *) DUK_TVAL_GET_BUFFER(tv);
26973 		}
26974 	}
26975 
26976 	if (flags & DUK__BUFOBJ_FLAG_THROW) {
26977 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);
26978 		DUK_WO_NORETURN(return NULL;);
26979 	}
26980 	return NULL;
26981 }
26982 
26983 /* Check that 'this' is a duk_hbufobj and return a pointer to it. */
duk__get_bufobj_this(duk_hthread * thr)26984 DUK_LOCAL duk_hbufobj *duk__get_bufobj_this(duk_hthread *thr) {
26985 	return (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_PROMOTE);
26986 }
26987 
26988 /* Check that 'this' is a duk_hbufobj and return a pointer to it
26989  * (NULL if not).
26990  */
duk__require_bufobj_this(duk_hthread * thr)26991 DUK_LOCAL duk_hbufobj *duk__require_bufobj_this(duk_hthread *thr) {
26992 	return (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW | DUK__BUFOBJ_FLAG_PROMOTE);
26993 }
26994 
26995 /* Check that value is a duk_hbufobj and return a pointer to it. */
duk__require_bufobj_value(duk_hthread * thr,duk_idx_t idx)26996 DUK_LOCAL duk_hbufobj *duk__require_bufobj_value(duk_hthread *thr, duk_idx_t idx) {
26997 	duk_tval *tv;
26998 	duk_hbufobj *h_obj;
26999 
27000 	/* Don't accept relative indices now. */
27001 	DUK_ASSERT(idx >= 0);
27002 
27003 	tv = duk_require_tval(thr, idx);
27004 	DUK_ASSERT(tv != NULL);
27005 	if (DUK_TVAL_IS_OBJECT(tv)) {
27006 		h_obj = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
27007 		DUK_ASSERT(h_obj != NULL);
27008 		if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_obj)) {
27009 			DUK_HBUFOBJ_ASSERT_VALID(h_obj);
27010 			return h_obj;
27011 		}
27012 	} else if (DUK_TVAL_IS_BUFFER(tv)) {
27013 		h_obj = (duk_hbufobj *) duk_to_hobject(thr, idx);
27014 		DUK_ASSERT(h_obj != NULL);
27015 		DUK_HBUFOBJ_ASSERT_VALID(h_obj);
27016 		return h_obj;
27017 	}
27018 
27019 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);
27020 	DUK_WO_NORETURN(return NULL;);
27021 }
27022 
duk__set_bufobj_buffer(duk_hthread * thr,duk_hbufobj * h_bufobj,duk_hbuffer * h_val)27023 DUK_LOCAL void duk__set_bufobj_buffer(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_hbuffer *h_val) {
27024 	DUK_ASSERT(thr != NULL);
27025 	DUK_ASSERT(h_bufobj != NULL);
27026 	DUK_ASSERT(h_bufobj->buf == NULL);  /* no need to decref */
27027 	DUK_ASSERT(h_val != NULL);
27028 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
27029 	DUK_UNREF(thr);
27030 
27031 	h_bufobj->buf = h_val;
27032 	DUK_HBUFFER_INCREF(thr, h_val);
27033 	h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val);
27034 	DUK_ASSERT(h_bufobj->shift == 0);
27035 	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFOBJ_ELEM_UINT8);
27036 	DUK_ASSERT(h_bufobj->is_typedarray == 0);
27037 
27038 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
27039 }
27040 
27041 /* 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)27042 DUK_LOCAL void duk__resolve_offset_opt_length(duk_hthread *thr,
27043                                               duk_hbufobj *h_bufarg,
27044                                               duk_idx_t idx_offset,
27045                                               duk_idx_t idx_length,
27046                                               duk_uint_t *out_offset,
27047                                               duk_uint_t *out_length,
27048                                               duk_bool_t throw_flag) {
27049 	duk_int_t offset_signed;
27050 	duk_int_t length_signed;
27051 	duk_uint_t offset;
27052 	duk_uint_t length;
27053 
27054 	offset_signed = duk_to_int(thr, idx_offset);
27055 	if (offset_signed < 0) {
27056 		goto fail_range;
27057 	}
27058 	offset = (duk_uint_t) offset_signed;
27059 	if (offset > h_bufarg->length) {
27060 		goto fail_range;
27061 	}
27062 	DUK_ASSERT_DISABLE(offset >= 0);  /* unsigned */
27063 	DUK_ASSERT(offset <= h_bufarg->length);
27064 
27065 	if (duk_is_undefined(thr, idx_length)) {
27066 		DUK_ASSERT(h_bufarg->length >= offset);
27067 		length = h_bufarg->length - offset;  /* >= 0 */
27068 	} else {
27069 		length_signed = duk_to_int(thr, idx_length);
27070 		if (length_signed < 0) {
27071 			goto fail_range;
27072 		}
27073 		length = (duk_uint_t) length_signed;
27074 		DUK_ASSERT(h_bufarg->length >= offset);
27075 		if (length > h_bufarg->length - offset) {
27076 			/* Unlike for negative arguments, some call sites
27077 			 * want length to be clamped if it's positive.
27078 			 */
27079 			if (throw_flag) {
27080 				goto fail_range;
27081 			} else {
27082 				length = h_bufarg->length - offset;
27083 			}
27084 		}
27085 	}
27086 	DUK_ASSERT_DISABLE(length >= 0);  /* unsigned */
27087 	DUK_ASSERT(offset + length <= h_bufarg->length);
27088 
27089 	*out_offset = offset;
27090 	*out_length = length;
27091 	return;
27092 
27093  fail_range:
27094 	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS);
27095 	DUK_WO_NORETURN(return;);
27096 }
27097 
27098 /* Shared lenient buffer length clamping helper.  No negative indices, no
27099  * element/byte shifting.
27100  */
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)27101 DUK_LOCAL void duk__clamp_startend_nonegidx_noshift(duk_hthread *thr,
27102                                                     duk_int_t buffer_length,
27103                                                     duk_idx_t idx_start,
27104                                                     duk_idx_t idx_end,
27105                                                     duk_int_t *out_start_offset,
27106                                                     duk_int_t *out_end_offset) {
27107 	duk_int_t start_offset;
27108 	duk_int_t end_offset;
27109 
27110 	DUK_ASSERT(out_start_offset != NULL);
27111 	DUK_ASSERT(out_end_offset != NULL);
27112 
27113 	/* undefined coerces to zero which is correct */
27114 	start_offset = duk_to_int_clamped(thr, idx_start, 0, buffer_length);
27115 	if (duk_is_undefined(thr, idx_end)) {
27116 		end_offset = buffer_length;
27117 	} else {
27118 		end_offset = duk_to_int_clamped(thr, idx_end, start_offset, buffer_length);
27119 	}
27120 
27121 	DUK_ASSERT(start_offset >= 0);
27122 	DUK_ASSERT(start_offset <= buffer_length);
27123 	DUK_ASSERT(end_offset >= 0);
27124 	DUK_ASSERT(end_offset <= buffer_length);
27125 	DUK_ASSERT(start_offset <= end_offset);
27126 
27127 	*out_start_offset = start_offset;
27128 	*out_end_offset = end_offset;
27129 }
27130 
27131 /* Shared lenient buffer length clamping helper.  Indices are treated as
27132  * element indices (though output values are byte offsets) which only
27133  * really matters for TypedArray views as other buffer object have a zero
27134  * shift.  Negative indices are counted from end of input slice; crossed
27135  * indices are clamped to zero length; and final indices are clamped
27136  * against input slice.  Used for e.g. ArrayBuffer slice().
27137  */
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)27138 DUK_LOCAL void duk__clamp_startend_negidx_shifted(duk_hthread *thr,
27139                                                   duk_int_t buffer_length,
27140                                                   duk_uint8_t buffer_shift,
27141                                                   duk_idx_t idx_start,
27142                                                   duk_idx_t idx_end,
27143                                                   duk_int_t *out_start_offset,
27144                                                   duk_int_t *out_end_offset) {
27145 	duk_int_t start_offset;
27146 	duk_int_t end_offset;
27147 
27148 	DUK_ASSERT(out_start_offset != NULL);
27149 	DUK_ASSERT(out_end_offset != NULL);
27150 
27151 	buffer_length >>= buffer_shift;  /* as (full) elements */
27152 
27153 	/* Resolve start/end offset as element indices first; arguments
27154 	 * at idx_start/idx_end are element offsets.  Working with element
27155 	 * indices first also avoids potential for wrapping.
27156 	 */
27157 
27158 	start_offset = duk_to_int(thr, idx_start);
27159 	if (start_offset < 0) {
27160 		start_offset = buffer_length + start_offset;
27161 	}
27162 	if (duk_is_undefined(thr, idx_end)) {
27163 		end_offset = buffer_length;
27164 	} else {
27165 		end_offset = duk_to_int(thr, idx_end);
27166 		if (end_offset < 0) {
27167 			end_offset = buffer_length + end_offset;
27168 		}
27169 	}
27170 	/* Note: start_offset/end_offset can still be < 0 here. */
27171 
27172 	if (start_offset < 0) {
27173 		start_offset = 0;
27174 	} else if (start_offset > buffer_length) {
27175 		start_offset = buffer_length;
27176 	}
27177 	if (end_offset < start_offset) {
27178 		end_offset = start_offset;
27179 	} else if (end_offset > buffer_length) {
27180 		end_offset = buffer_length;
27181 	}
27182 	DUK_ASSERT(start_offset >= 0);
27183 	DUK_ASSERT(start_offset <= buffer_length);
27184 	DUK_ASSERT(end_offset >= 0);
27185 	DUK_ASSERT(end_offset <= buffer_length);
27186 	DUK_ASSERT(start_offset <= end_offset);
27187 
27188 	/* Convert indices to byte offsets. */
27189 	start_offset <<= buffer_shift;
27190 	end_offset <<= buffer_shift;
27191 
27192 	*out_start_offset = start_offset;
27193 	*out_end_offset = end_offset;
27194 }
27195 
duk_hbufobj_promote_plain(duk_hthread * thr,duk_idx_t idx)27196 DUK_INTERNAL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx) {
27197 	if (duk_is_buffer(thr, idx)) {
27198 		duk_to_object(thr, idx);
27199 	}
27200 }
27201 
duk_hbufobj_push_uint8array_from_plain(duk_hthread * thr,duk_hbuffer * h_buf)27202 DUK_INTERNAL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf) {
27203 	/* Push Uint8Array which will share the same underlying buffer as
27204 	 * the plain buffer argument.  Also create an ArrayBuffer with the
27205 	 * same backing for the result .buffer property.
27206 	 */
27207 
27208 	duk_push_hbuffer(thr, h_buf);
27209 	duk_push_buffer_object(thr, -1, 0, (duk_size_t) DUK_HBUFFER_GET_SIZE(h_buf), DUK_BUFOBJ_UINT8ARRAY);
27210 	duk_remove_m2(thr);
27211 
27212 #if 0
27213 	/* More verbose equivalent; maybe useful if e.g. .buffer is omitted. */
27214 	h_bufobj = duk_push_bufobj_raw(thr,
27215 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27216 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27217 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_UINT8ARRAY),
27218 	                               DUK_BIDX_UINT8ARRAY_PROTOTYPE);
27219 	DUK_ASSERT(h_bufobj != NULL);
27220 	duk__set_bufobj_buffer(thr, h_bufobj, h_buf);
27221 	h_bufobj->is_typedarray = 1;
27222 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
27223 
27224 	h_arrbuf = duk_push_bufobj_raw(thr,
27225 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27226 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27227 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
27228 	                               DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
27229 	DUK_ASSERT(h_arrbuf != NULL);
27230 	duk__set_bufobj_buffer(thr, h_arrbuf, h_buf);
27231 	DUK_ASSERT(h_arrbuf->is_typedarray == 0);
27232 	DUK_HBUFOBJ_ASSERT_VALID(h_arrbuf);
27233 
27234 	DUK_ASSERT(h_bufobj->buf_prop == NULL);
27235 	h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
27236 	DUK_ASSERT(h_arrbuf != NULL);
27237 	DUK_HBUFOBJ_INCREF(thr, h_arrbuf);
27238 	duk_pop(thr);
27239 #endif
27240 }
27241 
27242 /* 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)27243 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) {
27244 	duk_double_union du;
27245 
27246 	DUK_ASSERT(elem_size > 0);
27247 	duk_memcpy((void *) du.uc, (const void *) p, (size_t) elem_size);
27248 
27249 	switch (h_bufobj->elem_type) {
27250 	case DUK_HBUFOBJ_ELEM_UINT8:
27251 	case DUK_HBUFOBJ_ELEM_UINT8CLAMPED:
27252 		duk_push_uint(thr, (duk_uint_t) du.uc[0]);
27253 		break;
27254 	case DUK_HBUFOBJ_ELEM_INT8:
27255 		duk_push_int(thr, (duk_int_t) (duk_int8_t) du.uc[0]);
27256 		break;
27257 	case DUK_HBUFOBJ_ELEM_UINT16:
27258 		duk_push_uint(thr, (duk_uint_t) du.us[0]);
27259 		break;
27260 	case DUK_HBUFOBJ_ELEM_INT16:
27261 		duk_push_int(thr, (duk_int_t) (duk_int16_t) du.us[0]);
27262 		break;
27263 	case DUK_HBUFOBJ_ELEM_UINT32:
27264 		duk_push_uint(thr, (duk_uint_t) du.ui[0]);
27265 		break;
27266 	case DUK_HBUFOBJ_ELEM_INT32:
27267 		duk_push_int(thr, (duk_int_t) (duk_int32_t) du.ui[0]);
27268 		break;
27269 	case DUK_HBUFOBJ_ELEM_FLOAT32:
27270 		duk_push_number(thr, (duk_double_t) du.f[0]);
27271 		break;
27272 	case DUK_HBUFOBJ_ELEM_FLOAT64:
27273 		duk_push_number(thr, (duk_double_t) du.d);
27274 		break;
27275 	default:
27276 		DUK_UNREACHABLE();
27277 	}
27278 }
27279 
27280 /* 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)27281 DUK_INTERNAL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
27282 	duk_double_union du;
27283 
27284 	/* NOTE! Caller must ensure that any side effects from the
27285 	 * coercions below are safe.  If that cannot be guaranteed
27286 	 * (which is normally the case), caller must coerce the
27287 	 * argument using duk_to_number() before any pointer
27288 	 * validations; the result of duk_to_number() always coerces
27289 	 * without side effects here.
27290 	 */
27291 
27292 	switch (h_bufobj->elem_type) {
27293 	case DUK_HBUFOBJ_ELEM_UINT8:
27294 		du.uc[0] = (duk_uint8_t) duk_to_uint32(thr, -1);
27295 		break;
27296 	case DUK_HBUFOBJ_ELEM_UINT8CLAMPED:
27297 		du.uc[0] = (duk_uint8_t) duk_to_uint8clamped(thr, -1);
27298 		break;
27299 	case DUK_HBUFOBJ_ELEM_INT8:
27300 		du.uc[0] = (duk_uint8_t) duk_to_int32(thr, -1);
27301 		break;
27302 	case DUK_HBUFOBJ_ELEM_UINT16:
27303 		du.us[0] = (duk_uint16_t) duk_to_uint32(thr, -1);
27304 		break;
27305 	case DUK_HBUFOBJ_ELEM_INT16:
27306 		du.us[0] = (duk_uint16_t) duk_to_int32(thr, -1);
27307 		break;
27308 	case DUK_HBUFOBJ_ELEM_UINT32:
27309 		du.ui[0] = (duk_uint32_t) duk_to_uint32(thr, -1);
27310 		break;
27311 	case DUK_HBUFOBJ_ELEM_INT32:
27312 		du.ui[0] = (duk_uint32_t) duk_to_int32(thr, -1);
27313 		break;
27314 	case DUK_HBUFOBJ_ELEM_FLOAT32:
27315 		/* A double-to-float cast is undefined behavior in C99 if
27316 		 * the cast is out-of-range, so use a helper.  Example:
27317 		 * runtime error: value -1e+100 is outside the range of representable values of type 'float'
27318 		 */
27319 		du.f[0] = duk_double_to_float_t(duk_to_number_m1(thr));
27320 		break;
27321 	case DUK_HBUFOBJ_ELEM_FLOAT64:
27322 		du.d = (duk_double_t) duk_to_number_m1(thr);
27323 		break;
27324 	default:
27325 		DUK_UNREACHABLE();
27326 	}
27327 
27328 	DUK_ASSERT(elem_size > 0);
27329 	duk_memcpy((void *) p, (const void *) du.uc, (size_t) elem_size);
27330 }
27331 
27332 /* Helper to create a fixed buffer from argument value at index 0.
27333  * Node.js and allocPlain() compatible.
27334  */
duk__hbufobj_fixed_from_argvalue(duk_hthread * thr)27335 DUK_LOCAL duk_hbuffer *duk__hbufobj_fixed_from_argvalue(duk_hthread *thr) {
27336 	duk_int_t len;
27337 	duk_int_t i;
27338 	duk_size_t buf_size;
27339 	duk_uint8_t *buf;
27340 
27341 	switch (duk_get_type(thr, 0)) {
27342 	case DUK_TYPE_NUMBER: {
27343 		len = duk_to_int_clamped(thr, 0, 0, DUK_INT_MAX);
27344 		(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) len);
27345 		break;
27346 	}
27347 	case DUK_TYPE_BUFFER: { /* Treat like Uint8Array. */
27348 		goto slow_copy;
27349 	}
27350 	case DUK_TYPE_OBJECT: {
27351 		duk_hobject *h;
27352 		duk_hbufobj *h_bufobj;
27353 
27354 		/* For Node.js Buffers "Passing an ArrayBuffer returns a Buffer
27355 		 * that shares allocated memory with the given ArrayBuffer."
27356 		 * https://nodejs.org/api/buffer.html#buffer_buffer_from_buffer_alloc_and_buffer_allocunsafe
27357 		 */
27358 
27359 		h = duk_known_hobject(thr, 0);
27360 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAYBUFFER) {
27361 			DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ(h));
27362 			h_bufobj = (duk_hbufobj *) h;
27363 			if (DUK_UNLIKELY(h_bufobj->buf == NULL)) {
27364 				DUK_ERROR_TYPE_INVALID_ARGS(thr);
27365 				DUK_WO_NORETURN(return NULL;);
27366 			}
27367 			if (DUK_UNLIKELY(h_bufobj->offset != 0 || h_bufobj->length != DUK_HBUFFER_GET_SIZE(h_bufobj->buf))) {
27368 				/* No support for ArrayBuffers with slice
27369 				 * offset/length.
27370 				 */
27371 				DUK_ERROR_TYPE_INVALID_ARGS(thr);
27372 				DUK_WO_NORETURN(return NULL;);
27373 			}
27374 			duk_push_hbuffer(thr, h_bufobj->buf);
27375 			return h_bufobj->buf;
27376 		}
27377 		goto slow_copy;
27378 	}
27379 	case DUK_TYPE_STRING: {
27380 		/* ignore encoding for now */
27381 		duk_require_hstring_notsymbol(thr, 0);
27382 		duk_dup_0(thr);
27383 		(void) duk_to_buffer(thr, -1, &buf_size);
27384 		break;
27385 	}
27386 	default:
27387 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
27388 		DUK_WO_NORETURN(return NULL;);
27389 	}
27390 
27391  done:
27392 	DUK_ASSERT(duk_is_buffer(thr, -1));
27393 	return duk_known_hbuffer(thr, -1);
27394 
27395  slow_copy:
27396 	/* XXX: fast path for typed arrays and other buffer objects? */
27397 
27398 	(void) duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
27399 	len = duk_to_int_clamped(thr, -1, 0, DUK_INT_MAX);
27400 	duk_pop(thr);
27401 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len);  /* no zeroing, all indices get initialized */
27402 	for (i = 0; i < len; i++) {
27403 		/* XXX: fast path for array or buffer arguments? */
27404 		duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
27405 		buf[i] = (duk_uint8_t) (duk_to_uint32(thr, -1) & 0xffU);
27406 		duk_pop(thr);
27407 	}
27408 	goto done;
27409 }
27410 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27411 
27412 /*
27413  *  Node.js Buffer constructor
27414  *
27415  *  Node.js Buffers are just Uint8Arrays with internal prototype set to
27416  *  Buffer.prototype so they're handled otherwise the same as Uint8Array.
27417  *  However, the constructor arguments are very different so a separate
27418  *  constructor entry point is used.
27419  */
27420 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_constructor(duk_hthread * thr)27421 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_hthread *thr) {
27422 	duk_hbuffer *h_buf;
27423 
27424 	h_buf = duk__hbufobj_fixed_from_argvalue(thr);
27425 	DUK_ASSERT(h_buf != NULL);
27426 
27427 	duk_push_buffer_object(thr,
27428 	                       -1,
27429 	                       0,
27430 	                       DUK_HBUFFER_FIXED_GET_SIZE((duk_hbuffer_fixed *) (void *) h_buf),
27431 	                       DUK_BUFOBJ_UINT8ARRAY);
27432 	duk_push_hobject_bidx(thr, DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
27433 	duk_set_prototype(thr, -2);
27434 
27435 	/* XXX: a more direct implementation */
27436 
27437 	return 1;
27438 }
27439 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27440 
27441 /*
27442  *  ArrayBuffer, DataView, and TypedArray constructors
27443  */
27444 
27445 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_arraybuffer_constructor(duk_hthread * thr)27446 DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_hthread *thr) {
27447 	duk_hbufobj *h_bufobj;
27448 	duk_hbuffer *h_val;
27449 	duk_int_t len;
27450 
27451 	DUK_CTX_ASSERT_VALID(thr);
27452 
27453 	duk_require_constructor_call(thr);
27454 
27455 	len = duk_to_int(thr, 0);
27456 	if (len < 0) {
27457 		goto fail_length;
27458 	}
27459 	(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) len);
27460 	h_val = (duk_hbuffer *) duk_known_hbuffer(thr, -1);
27461 
27462 	h_bufobj = duk_push_bufobj_raw(thr,
27463 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27464 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27465 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
27466 	                               DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
27467 	DUK_ASSERT(h_bufobj != NULL);
27468 
27469 	duk__set_bufobj_buffer(thr, h_bufobj, h_val);
27470 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
27471 
27472 	return 1;
27473 
27474  fail_length:
27475 	DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
27476 }
27477 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27478 
27479 
27480 /* Format of magic, bits:
27481  *   0...1: elem size shift (0-3)
27482  *   2...5: elem type (DUK_HBUFOBJ_ELEM_xxx)
27483  *
27484  * XXX: add prototype bidx explicitly to magic instead of using a mapping?
27485  */
27486 
27487 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_typedarray_constructor(duk_hthread * thr)27488 DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
27489 	duk_tval *tv;
27490 	duk_hobject *h_obj;
27491 	duk_hbufobj *h_bufobj = NULL;
27492 	duk_hbufobj *h_bufarg = NULL;
27493 	duk_hbuffer *h_val;
27494 	duk_small_uint_t magic;
27495 	duk_small_uint_t shift;
27496 	duk_small_uint_t elem_type;
27497 	duk_small_uint_t elem_size;
27498 	duk_small_uint_t class_num;
27499 	duk_small_uint_t proto_bidx;
27500 	duk_uint_t align_mask;
27501 	duk_uint_t elem_length;
27502 	duk_int_t elem_length_signed;
27503 	duk_uint_t byte_length;
27504 	duk_small_uint_t copy_mode;
27505 
27506 	/* XXX: The same copy helpers could be shared with at least some
27507 	 * buffer functions.
27508 	 */
27509 
27510 	duk_require_constructor_call(thr);
27511 
27512 	/* We could fit built-in index into magic but that'd make the magic
27513 	 * number dependent on built-in numbering (genbuiltins.py doesn't
27514 	 * handle that yet).  So map both class and prototype from the
27515 	 * element type.
27516 	 */
27517 	magic = (duk_small_uint_t) duk_get_current_magic(thr);
27518 	shift = magic & 0x03U;               /* bits 0...1: shift */
27519 	elem_type = (magic >> 2) & 0x0fU;    /* bits 2...5: type */
27520 	elem_size = 1U << shift;
27521 	align_mask = elem_size - 1;
27522 	DUK_ASSERT(elem_type < sizeof(duk__buffer_proto_from_elemtype) / sizeof(duk_uint8_t));
27523 	proto_bidx = duk__buffer_proto_from_elemtype[elem_type];
27524 	DUK_ASSERT(proto_bidx < DUK_NUM_BUILTINS);
27525 	DUK_ASSERT(elem_type < sizeof(duk__buffer_class_from_elemtype) / sizeof(duk_uint8_t));
27526 	class_num = duk__buffer_class_from_elemtype[elem_type];
27527 
27528 	DUK_DD(DUK_DDPRINT("typedarray constructor, magic=%d, shift=%d, elem_type=%d, "
27529 	                   "elem_size=%d, proto_bidx=%d, class_num=%d",
27530 	                   (int) magic, (int) shift, (int) elem_type, (int) elem_size,
27531 	                   (int) proto_bidx, (int) class_num));
27532 
27533 	/* Argument variants.  When the argument is an ArrayBuffer a view to
27534 	 * the same buffer is created; otherwise a new ArrayBuffer is always
27535 	 * created.
27536 	 */
27537 
27538 	/* XXX: initial iteration to treat a plain buffer like an ArrayBuffer:
27539 	 * coerce to an ArrayBuffer object and use that as .buffer.  The underlying
27540 	 * buffer will be the same but result .buffer !== inputPlainBuffer.
27541 	 */
27542 	duk_hbufobj_promote_plain(thr, 0);
27543 
27544 	tv = duk_get_tval(thr, 0);
27545 	DUK_ASSERT(tv != NULL);  /* arg count */
27546 	if (DUK_TVAL_IS_OBJECT(tv)) {
27547 		h_obj = DUK_TVAL_GET_OBJECT(tv);
27548 		DUK_ASSERT(h_obj != NULL);
27549 
27550 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_ARRAYBUFFER) {
27551 			/* ArrayBuffer: unlike any other argument variant, create
27552 			 * a view into the existing buffer.
27553 			 */
27554 
27555 			duk_int_t byte_offset_signed;
27556 			duk_uint_t byte_offset;
27557 
27558 			h_bufarg = (duk_hbufobj *) h_obj;
27559 
27560 			byte_offset_signed = duk_to_int(thr, 1);
27561 			if (byte_offset_signed < 0) {
27562 				goto fail_arguments;
27563 			}
27564 			byte_offset = (duk_uint_t) byte_offset_signed;
27565 			if (byte_offset > h_bufarg->length ||
27566 			    (byte_offset & align_mask) != 0) {
27567 				/* Must be >= 0 and multiple of element size. */
27568 				goto fail_arguments;
27569 			}
27570 			if (duk_is_undefined(thr, 2)) {
27571 				DUK_ASSERT(h_bufarg->length >= byte_offset);
27572 				byte_length = h_bufarg->length - byte_offset;
27573 				if ((byte_length & align_mask) != 0) {
27574 					/* Must be element size multiple from
27575 					 * start offset to end of buffer.
27576 					 */
27577 					goto fail_arguments;
27578 				}
27579 				elem_length = (byte_length >> shift);
27580 			} else {
27581 				elem_length_signed = duk_to_int(thr, 2);
27582 				if (elem_length_signed < 0) {
27583 					goto fail_arguments;
27584 				}
27585 				elem_length = (duk_uint_t) elem_length_signed;
27586 				byte_length = elem_length << shift;
27587 				if ((byte_length >> shift) != elem_length) {
27588 					/* Byte length would overflow. */
27589 					/* XXX: easier check with less code? */
27590 					goto fail_arguments;
27591 				}
27592 				DUK_ASSERT(h_bufarg->length >= byte_offset);
27593 				if (byte_length > h_bufarg->length - byte_offset) {
27594 					/* Not enough data. */
27595 					goto fail_arguments;
27596 				}
27597 			}
27598 			DUK_UNREF(elem_length);
27599 			DUK_ASSERT_DISABLE(byte_offset >= 0);
27600 			DUK_ASSERT(byte_offset <= h_bufarg->length);
27601 			DUK_ASSERT_DISABLE(byte_length >= 0);
27602 			DUK_ASSERT(byte_offset + byte_length <= h_bufarg->length);
27603 			DUK_ASSERT((elem_length << shift) == byte_length);
27604 
27605 			h_bufobj = duk_push_bufobj_raw(thr,
27606 			                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27607 			                               DUK_HOBJECT_FLAG_BUFOBJ |
27608 			                               DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
27609 			                               (duk_small_int_t) proto_bidx);
27610 			h_val = h_bufarg->buf;
27611 			if (h_val == NULL) {
27612 				DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27613 			}
27614 			h_bufobj->buf = h_val;
27615 			DUK_HBUFFER_INCREF(thr, h_val);
27616 			h_bufobj->offset = h_bufarg->offset + byte_offset;
27617 			h_bufobj->length = byte_length;
27618 			h_bufobj->shift = (duk_uint8_t) shift;
27619 			h_bufobj->elem_type = (duk_uint8_t) elem_type;
27620 			h_bufobj->is_typedarray = 1;
27621 			DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
27622 
27623 			/* Set .buffer to the argument ArrayBuffer. */
27624 			DUK_ASSERT(h_bufobj->buf_prop == NULL);
27625 			h_bufobj->buf_prop = (duk_hobject *) h_bufarg;
27626 			DUK_ASSERT(h_bufarg != NULL);
27627 			DUK_HBUFOBJ_INCREF(thr, h_bufarg);
27628 			return 1;
27629 		} else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
27630 			/* TypedArray (or other non-ArrayBuffer duk_hbufobj).
27631 			 * Conceptually same behavior as for an Array-like argument,
27632 			 * with a few fast paths.
27633 			 */
27634 
27635 			h_bufarg = (duk_hbufobj *) h_obj;
27636 			DUK_HBUFOBJ_ASSERT_VALID(h_bufarg);
27637 			elem_length_signed = (duk_int_t) (h_bufarg->length >> h_bufarg->shift);
27638 			if (h_bufarg->buf == NULL) {
27639 				DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27640 			}
27641 
27642 			/* Select copy mode.  Must take into account element
27643 			 * compatibility and validity of the underlying source
27644 			 * buffer.
27645 			 */
27646 
27647 			DUK_DDD(DUK_DDDPRINT("selecting copy mode for bufobj arg, "
27648 			                     "src byte_length=%ld, src shift=%d, "
27649 			                     "src/dst elem_length=%ld; "
27650 			                     "dst shift=%d -> dst byte_length=%ld",
27651 			                     (long) h_bufarg->length, (int) h_bufarg->shift,
27652 			                     (long) elem_length_signed, (int) shift,
27653 			                     (long) (elem_length_signed << shift)));
27654 
27655 			copy_mode = 2;  /* default is explicit index read/write copy */
27656 #if !defined(DUK_USE_PREFER_SIZE)
27657 			/* With a size optimized build copy_mode 2 is enough.
27658 			 * Modes 0 and 1 are faster but conceptually the same.
27659 			 */
27660 			DUK_ASSERT(elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
27661 			if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
27662 				if ((duk__buffer_elemtype_copy_compatible[elem_type] & (1 << h_bufarg->elem_type)) != 0) {
27663 					DUK_DDD(DUK_DDDPRINT("source/target are copy compatible, memcpy"));
27664 					DUK_ASSERT(shift == h_bufarg->shift);  /* byte sizes will match */
27665 					copy_mode = 0;
27666 				} else {
27667 					DUK_DDD(DUK_DDDPRINT("source/target not copy compatible but valid, fast copy"));
27668 					copy_mode = 1;
27669 				}
27670 			}
27671 #endif  /* !DUK_USE_PREFER_SIZE */
27672 		} else {
27673 			/* Array or Array-like */
27674 			elem_length_signed = (duk_int_t) duk_get_length(thr, 0);
27675 			copy_mode = 2;
27676 		}
27677 	} else {
27678 		/* Non-object argument is simply int coerced, matches
27679 		 * V8 behavior (except for "null", which we coerce to
27680 		 * 0 but V8 TypeErrors).
27681 		 */
27682 		elem_length_signed = duk_to_int(thr, 0);
27683 		copy_mode = 3;
27684 	}
27685 	if (elem_length_signed < 0) {
27686 		goto fail_arguments;
27687 	}
27688 	elem_length = (duk_uint_t) elem_length_signed;
27689 	byte_length = (duk_uint_t) (elem_length << shift);
27690 	if ((byte_length >> shift) != elem_length) {
27691 		/* Byte length would overflow. */
27692 		/* XXX: easier check with less code? */
27693 		goto fail_arguments;
27694 	}
27695 
27696 	DUK_DDD(DUK_DDDPRINT("elem_length=%ld, byte_length=%ld",
27697 	                     (long) elem_length, (long) byte_length));
27698 
27699 	/* ArrayBuffer argument is handled specially above; the rest of the
27700 	 * argument variants are handled by shared code below.
27701 	 *
27702 	 * ArrayBuffer in h_bufobj->buf_prop is intentionally left unset.
27703 	 * It will be automatically created by the .buffer accessor on
27704 	 * first access.
27705 	 */
27706 
27707 	/* Push the resulting view object on top of a plain fixed buffer. */
27708 	(void) duk_push_fixed_buffer(thr, byte_length);
27709 	h_val = duk_known_hbuffer(thr, -1);
27710 	DUK_ASSERT(h_val != NULL);
27711 
27712 	h_bufobj = duk_push_bufobj_raw(thr,
27713 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27714 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27715 	                               DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
27716 	                               (duk_small_int_t) proto_bidx);
27717 
27718 	h_bufobj->buf = h_val;
27719 	DUK_HBUFFER_INCREF(thr, h_val);
27720 	DUK_ASSERT(h_bufobj->offset == 0);
27721 	h_bufobj->length = byte_length;
27722 	h_bufobj->shift = (duk_uint8_t) shift;
27723 	h_bufobj->elem_type = (duk_uint8_t) elem_type;
27724 	h_bufobj->is_typedarray = 1;
27725 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
27726 
27727 	/* Copy values, the copy method depends on the arguments.
27728 	 *
27729 	 * Copy mode decision may depend on the validity of the underlying
27730 	 * buffer of the source argument; there must be no harmful side effects
27731 	 * from there to here for copy_mode to still be valid.
27732 	 */
27733 	DUK_DDD(DUK_DDDPRINT("copy mode: %d", (int) copy_mode));
27734 	switch (copy_mode) {
27735 		/* Copy modes 0 and 1 can be omitted in size optimized build,
27736 		 * copy mode 2 handles them (but more slowly).
27737 		 */
27738 #if !defined(DUK_USE_PREFER_SIZE)
27739 	case 0: {
27740 		/* Use byte copy. */
27741 
27742 		duk_uint8_t *p_src;
27743 		duk_uint8_t *p_dst;
27744 
27745 		DUK_ASSERT(h_bufobj != NULL);
27746 		DUK_ASSERT(h_bufobj->buf != NULL);
27747 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufobj));
27748 		DUK_ASSERT(h_bufarg != NULL);
27749 		DUK_ASSERT(h_bufarg->buf != NULL);
27750 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufarg));
27751 
27752 		p_dst = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj);
27753 		p_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
27754 
27755 		DUK_DDD(DUK_DDDPRINT("using memcpy: p_src=%p, p_dst=%p, byte_length=%ld",
27756 		                     (void *) p_src, (void *) p_dst, (long) byte_length));
27757 
27758 		duk_memcpy_unsafe((void *) p_dst, (const void *) p_src, (size_t) byte_length);
27759 		break;
27760 	}
27761 	case 1: {
27762 		/* Copy values through direct validated reads and writes. */
27763 
27764 		duk_small_uint_t src_elem_size;
27765 		duk_small_uint_t dst_elem_size;
27766 		duk_uint8_t *p_src;
27767 		duk_uint8_t *p_src_end;
27768 		duk_uint8_t *p_dst;
27769 
27770 		DUK_ASSERT(h_bufobj != NULL);
27771 		DUK_ASSERT(h_bufobj->buf != NULL);
27772 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufobj));
27773 		DUK_ASSERT(h_bufarg != NULL);
27774 		DUK_ASSERT(h_bufarg->buf != NULL);
27775 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufarg));
27776 
27777 		src_elem_size = (duk_small_uint_t) (1U << h_bufarg->shift);
27778 		dst_elem_size = elem_size;
27779 
27780 		p_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
27781 		p_dst = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj);
27782 		p_src_end = p_src + h_bufarg->length;
27783 
27784 		DUK_DDD(DUK_DDDPRINT("using fast copy: p_src=%p, p_src_end=%p, p_dst=%p, "
27785 		                     "src_elem_size=%d, dst_elem_size=%d",
27786 		                     (void *) p_src, (void *) p_src_end, (void *) p_dst,
27787 		                     (int) src_elem_size, (int) dst_elem_size));
27788 
27789 		while (p_src != p_src_end) {
27790 			DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
27791 			                     "p_src=%p, p_src_end=%p, p_dst=%p",
27792 			                     (void *) p_src, (void *) p_src_end, (void *) p_dst));
27793 			/* A validated read() is always a number, so it's write coercion
27794 			 * is always side effect free an won't invalidate pointers etc.
27795 			 */
27796 			duk_hbufobj_push_validated_read(thr, h_bufarg, p_src, src_elem_size);
27797 			duk_hbufobj_validated_write(thr, h_bufobj, p_dst, dst_elem_size);
27798 			duk_pop(thr);
27799 			p_src += src_elem_size;
27800 			p_dst += dst_elem_size;
27801 		}
27802 		break;
27803 	}
27804 #endif  /* !DUK_USE_PREFER_SIZE */
27805 	case 2: {
27806 		/* Copy values by index reads and writes.  Let virtual
27807 		 * property handling take care of coercion.
27808 		 */
27809 		duk_uint_t i;
27810 
27811 		DUK_DDD(DUK_DDDPRINT("using slow copy"));
27812 
27813 		for (i = 0; i < elem_length; i++) {
27814 			duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
27815 			duk_put_prop_index(thr, -2, (duk_uarridx_t) i);
27816 		}
27817 		break;
27818 	}
27819 	default:
27820 	case 3: {
27821 		/* No copy, leave zero bytes in the buffer.  There's no
27822 		 * ambiguity with Float32/Float64 because zero bytes also
27823 		 * represent 0.0.
27824 		 */
27825 
27826 		DUK_DDD(DUK_DDDPRINT("using no copy"));
27827 		break;
27828 	}
27829 	}
27830 
27831 	return 1;
27832 
27833  fail_arguments:
27834 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
27835 }
27836 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27837 /* When bufferobject support is disabled, new Uint8Array() could still be
27838  * supported to create a plain fixed buffer.  Disabled for now.
27839  */
27840 #if 0
27841 DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
27842 	duk_int_t elem_length_signed;
27843 	duk_uint_t byte_length;
27844 
27845 	/* XXX: The same copy helpers could be shared with at least some
27846 	 * buffer functions.
27847 	 */
27848 
27849 	duk_require_constructor_call(thr);
27850 
27851 	elem_length_signed = duk_require_int(thr, 0);
27852 	if (elem_length_signed < 0) {
27853 		goto fail_arguments;
27854 	}
27855 	byte_length = (duk_uint_t) elem_length_signed;
27856 
27857 	(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) byte_length);
27858 	return 1;
27859 
27860  fail_arguments:
27861 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
27862 }
27863 #endif  /* 0 */
27864 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27865 
27866 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_dataview_constructor(duk_hthread * thr)27867 DUK_INTERNAL duk_ret_t duk_bi_dataview_constructor(duk_hthread *thr) {
27868 	duk_hbufobj *h_bufarg;
27869 	duk_hbufobj *h_bufobj;
27870 	duk_hbuffer *h_val;
27871 	duk_uint_t offset;
27872 	duk_uint_t length;
27873 
27874 	duk_require_constructor_call(thr);
27875 
27876 	h_bufarg = duk__require_bufobj_value(thr, 0);
27877 	DUK_ASSERT(h_bufarg != NULL);
27878 	if (DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_bufarg) != DUK_HOBJECT_CLASS_ARRAYBUFFER) {
27879 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27880 	}
27881 
27882 	duk__resolve_offset_opt_length(thr, h_bufarg, 1, 2, &offset, &length, 1 /*throw_flag*/);
27883 	DUK_ASSERT(offset <= h_bufarg->length);
27884 	DUK_ASSERT(offset + length <= h_bufarg->length);
27885 
27886 	h_bufobj = duk_push_bufobj_raw(thr,
27887 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27888 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27889 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATAVIEW),
27890 	                               DUK_BIDX_DATAVIEW_PROTOTYPE);
27891 
27892 	h_val = h_bufarg->buf;
27893 	if (h_val == NULL) {
27894 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27895 	}
27896 	h_bufobj->buf = h_val;
27897 	DUK_HBUFFER_INCREF(thr, h_val);
27898 	h_bufobj->offset = h_bufarg->offset + offset;
27899 	h_bufobj->length = length;
27900 	DUK_ASSERT(h_bufobj->shift == 0);
27901 	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFOBJ_ELEM_UINT8);
27902 	DUK_ASSERT(h_bufobj->is_typedarray == 0);
27903 
27904 	DUK_ASSERT(h_bufobj->buf_prop == NULL);
27905 	h_bufobj->buf_prop = (duk_hobject *) h_bufarg;
27906 	DUK_ASSERT(h_bufarg != NULL);
27907 	DUK_HBUFOBJ_INCREF(thr, h_bufarg);
27908 
27909 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
27910 	return 1;
27911 }
27912 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27913 
27914 /*
27915  *  ArrayBuffer.isView()
27916  */
27917 
27918 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_arraybuffer_isview(duk_hthread * thr)27919 DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_isview(duk_hthread *thr) {
27920 	duk_hobject *h_obj;
27921 	duk_bool_t ret = 0;
27922 
27923 	if (duk_is_buffer(thr, 0)) {
27924 		ret = 1;
27925 	} else {
27926 		h_obj = duk_get_hobject(thr, 0);
27927 		if (h_obj != NULL && DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
27928 			/* DataView needs special casing: ArrayBuffer.isView() is
27929 			 * true, but ->is_typedarray is 0.
27930 			 */
27931 			ret = ((duk_hbufobj *) h_obj)->is_typedarray ||
27932 			      (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_DATAVIEW);
27933 		}
27934 	}
27935 	duk_push_boolean(thr, ret);
27936 	return 1;
27937 }
27938 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27939 
27940 /*
27941  *  Uint8Array.allocPlain()
27942  */
27943 
27944 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_uint8array_allocplain(duk_hthread * thr)27945 DUK_INTERNAL duk_ret_t duk_bi_uint8array_allocplain(duk_hthread *thr) {
27946 	duk__hbufobj_fixed_from_argvalue(thr);
27947 	return 1;
27948 }
27949 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27950 
27951 /*
27952  *  Uint8Array.plainOf()
27953  */
27954 
27955 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_uint8array_plainof(duk_hthread * thr)27956 DUK_INTERNAL duk_ret_t duk_bi_uint8array_plainof(duk_hthread *thr) {
27957 	duk_hbufobj *h_bufobj;
27958 
27959 #if !defined(DUK_USE_PREFER_SIZE)
27960 	/* Avoid churn if argument is already a plain buffer. */
27961 	if (duk_is_buffer(thr, 0)) {
27962 		return 1;
27963 	}
27964 #endif
27965 
27966 	/* Promotes plain buffers to ArrayBuffers, so for a plain buffer
27967 	 * argument we'll create a pointless temporary (but still work
27968 	 * correctly).
27969 	 */
27970 	h_bufobj = duk__require_bufobj_value(thr, 0);
27971 	if (h_bufobj->buf == NULL) {
27972 		duk_push_undefined(thr);
27973 	} else {
27974 		duk_push_hbuffer(thr, h_bufobj->buf);
27975 	}
27976 	return 1;
27977 }
27978 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27979 
27980 /*
27981  *  Node.js Buffer: toString([encoding], [start], [end])
27982  */
27983 
27984 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_tostring(duk_hthread * thr)27985 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_hthread *thr) {
27986 	duk_hbufobj *h_this;
27987 	duk_int_t start_offset, end_offset;
27988 	duk_uint8_t *buf_slice;
27989 	duk_size_t slice_length;
27990 
27991 	h_this = duk__get_bufobj_this(thr);
27992 	if (h_this == NULL) {
27993 		/* XXX: happens e.g. when evaluating: String(Buffer.prototype). */
27994 		duk_push_literal(thr, "[object Object]");
27995 		return 1;
27996 	}
27997 	DUK_HBUFOBJ_ASSERT_VALID(h_this);
27998 
27999 	/* Ignore encoding for now. */
28000 
28001 	duk__clamp_startend_nonegidx_noshift(thr,
28002 	                                     (duk_int_t) h_this->length,
28003 	                                     1 /*idx_start*/,
28004 	                                     2 /*idx_end*/,
28005 	                                     &start_offset,
28006 	                                     &end_offset);
28007 
28008 	slice_length = (duk_size_t) (end_offset - start_offset);
28009 	buf_slice = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, slice_length);  /* all bytes initialized below */
28010 	DUK_ASSERT(buf_slice != NULL);
28011 
28012 	/* Neutered or uncovered, TypeError. */
28013 	if (h_this->buf == NULL ||
28014 	    !DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length)) {
28015 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28016 	}
28017 
28018 	/* XXX: ideally we wouldn't make a copy but a view into the buffer for the
28019 	 * decoding process.  Or the decoding helper could be changed to accept
28020 	 * the slice info (a buffer pointer is NOT a good approach because guaranteeing
28021 	 * its stability is difficult).
28022 	 */
28023 
28024 	DUK_ASSERT(DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length));
28025 	duk_memcpy_unsafe((void *) buf_slice,
28026 	                  (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
28027 	                  (size_t) slice_length);
28028 
28029 	/* Use the equivalent of: new TextEncoder().encode(this) to convert the
28030 	 * string.  Result will be valid UTF-8; non-CESU-8 inputs are currently
28031 	 * interpreted loosely.  Value stack convention is a bit odd for now.
28032 	 */
28033 	duk_replace(thr, 0);
28034 	duk_set_top(thr, 1);
28035 	return duk_textdecoder_decode_utf8_nodejs(thr);
28036 }
28037 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28038 
28039 /*
28040  *  Node.js Buffer.prototype: toJSON()
28041  */
28042 
28043 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_tojson(duk_hthread * thr)28044 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_hthread *thr) {
28045 	duk_hbufobj *h_this;
28046 	duk_uint8_t *buf;
28047 	duk_uint_t i, n;
28048 	duk_tval *tv;
28049 
28050 	h_this = duk__require_bufobj_this(thr);
28051 	DUK_ASSERT(h_this != NULL);
28052 
28053 	if (h_this->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_this)) {
28054 		/* Serialize uncovered backing buffer as a null; doesn't
28055 		 * really matter as long we're memory safe.
28056 		 */
28057 		duk_push_null(thr);
28058 		return 1;
28059 	}
28060 
28061 	duk_push_object(thr);
28062 	duk_push_hstring_stridx(thr, DUK_STRIDX_UC_BUFFER);
28063 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_TYPE);
28064 
28065 	/* XXX: uninitialized would be OK */
28066 	DUK_ASSERT_DISABLE((duk_size_t) h_this->length <= (duk_size_t) DUK_UINT32_MAX);
28067 	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) h_this->length);  /* XXX: needs revision with >4G buffers */
28068 	DUK_ASSERT(!duk_is_bare_object(thr, -1));
28069 
28070 	DUK_ASSERT(h_this->buf != NULL);
28071 	buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
28072 	for (i = 0, n = h_this->length; i < n; i++) {
28073 		DUK_TVAL_SET_U32(tv + i, (duk_uint32_t) buf[i]);  /* no need for decref or incref */
28074 	}
28075 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_DATA);
28076 
28077 	return 1;
28078 }
28079 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28080 
28081 /*
28082  *  Node.js Buffer.prototype.equals()
28083  *  Node.js Buffer.prototype.compare()
28084  *  Node.js Buffer.compare()
28085  */
28086 
28087 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_buffer_compare_shared(duk_hthread * thr)28088 DUK_INTERNAL duk_ret_t duk_bi_buffer_compare_shared(duk_hthread *thr) {
28089 	duk_small_uint_t magic;
28090 	duk_hbufobj *h_bufarg1;
28091 	duk_hbufobj *h_bufarg2;
28092 	duk_small_int_t comp_res;
28093 
28094 	/* XXX: keep support for plain buffers and non-Node.js buffers? */
28095 
28096 	magic = (duk_small_uint_t) duk_get_current_magic(thr);
28097 	if (magic & 0x02U) {
28098 		/* Static call style. */
28099 		h_bufarg1 = duk__require_bufobj_value(thr, 0);
28100 		h_bufarg2 = duk__require_bufobj_value(thr, 1);
28101 	} else {
28102 		h_bufarg1 = duk__require_bufobj_this(thr);
28103 		h_bufarg2 = duk__require_bufobj_value(thr, 0);
28104 	}
28105 	DUK_ASSERT(h_bufarg1 != NULL);
28106 	DUK_ASSERT(h_bufarg2 != NULL);
28107 
28108 	/* We want to compare the slice/view areas of the arguments.
28109 	 * If either slice/view is invalid (underlying buffer is shorter)
28110 	 * ensure equals() is false, but otherwise the only thing that
28111 	 * matters is to be memory safe.
28112 	 */
28113 
28114 	if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg1) &&
28115 	    DUK_HBUFOBJ_VALID_SLICE(h_bufarg2)) {
28116 		comp_res = duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg1->buf) + h_bufarg1->offset,
28117 		                               (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg2->buf) + h_bufarg2->offset,
28118 		                               (duk_size_t) h_bufarg1->length,
28119 		                               (duk_size_t) h_bufarg2->length);
28120 	} else {
28121 		comp_res = -1;  /* either nonzero value is ok */
28122 	}
28123 
28124 	if (magic & 0x01U) {
28125 		/* compare: similar to string comparison but for buffer data. */
28126 		duk_push_int(thr, comp_res);
28127 	} else {
28128 		/* equals */
28129 		duk_push_boolean(thr, (comp_res == 0));
28130 	}
28131 
28132 	return 1;
28133 }
28134 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28135 
28136 /*
28137  *  Node.js Buffer.prototype.fill()
28138  */
28139 
28140 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_fill(duk_hthread * thr)28141 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_hthread *thr) {
28142 	duk_hbufobj *h_this;
28143 	const duk_uint8_t *fill_str_ptr;
28144 	duk_size_t fill_str_len;
28145 	duk_uint8_t fill_value;
28146 	duk_int_t fill_offset;
28147 	duk_int_t fill_end;
28148 	duk_size_t fill_length;
28149 	duk_uint8_t *p;
28150 
28151 	h_this = duk__require_bufobj_this(thr);
28152 	DUK_ASSERT(h_this != NULL);
28153 	if (h_this->buf == NULL) {
28154 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28155 	}
28156 
28157 	/* [ value offset end ] */
28158 
28159 	if (duk_is_string_notsymbol(thr, 0)) {
28160 		fill_str_ptr = (const duk_uint8_t *) duk_get_lstring(thr, 0, &fill_str_len);
28161 		DUK_ASSERT(fill_str_ptr != NULL);
28162 	} else {
28163 		/* Symbols get ToNumber() coerced and cause TypeError. */
28164 		fill_value = (duk_uint8_t) duk_to_uint32(thr, 0);
28165 		fill_str_ptr = (const duk_uint8_t *) &fill_value;
28166 		fill_str_len = 1;
28167 	}
28168 
28169 	/* Fill offset handling is more lenient than in Node.js. */
28170 
28171 	duk__clamp_startend_nonegidx_noshift(thr,
28172 	                                     (duk_int_t) h_this->length,
28173 	                                     1 /*idx_start*/,
28174 	                                     2 /*idx_end*/,
28175 	                                     &fill_offset,
28176 	                                     &fill_end);
28177 
28178 	DUK_DDD(DUK_DDDPRINT("fill: fill_value=%02x, fill_offset=%ld, fill_end=%ld, view length=%ld",
28179 	                     (unsigned int) fill_value, (long) fill_offset, (long) fill_end, (long) h_this->length));
28180 
28181 	DUK_ASSERT(fill_end - fill_offset >= 0);
28182 	DUK_ASSERT(h_this->buf != NULL);
28183 
28184 	p = (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + fill_offset);
28185 	fill_length = (duk_size_t) (fill_end - fill_offset);
28186 	if (fill_str_len == 1) {
28187 		/* Handle single character fills as memset() even when
28188 		 * the fill data comes from a one-char argument.
28189 		 */
28190 		duk_memset_unsafe((void *) p, (int) fill_str_ptr[0], (size_t) fill_length);
28191 	} else if (fill_str_len > 1) {
28192 		duk_size_t i, n, t;
28193 
28194 		for (i = 0, n = (duk_size_t) (fill_end - fill_offset), t = 0; i < n; i++) {
28195 			p[i] = fill_str_ptr[t++];
28196 			if (t >= fill_str_len) {
28197 				t = 0;
28198 			}
28199 		}
28200 	} else {
28201 		DUK_DDD(DUK_DDDPRINT("zero size fill pattern, ignore silently"));
28202 	}
28203 
28204 	/* Return the Buffer to allow chaining: b.fill(0x11).fill(0x22, 3, 5).toString() */
28205 	duk_push_this(thr);
28206 	return 1;
28207 }
28208 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28209 
28210 /*
28211  *  Node.js Buffer.prototype.write(string, [offset], [length], [encoding])
28212  */
28213 
28214 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_write(duk_hthread * thr)28215 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_write(duk_hthread *thr) {
28216 	duk_hbufobj *h_this;
28217 	duk_uint_t offset;
28218 	duk_uint_t length;
28219 	const duk_uint8_t *str_data;
28220 	duk_size_t str_len;
28221 
28222 	/* XXX: very inefficient support for plain buffers */
28223 	h_this = duk__require_bufobj_this(thr);
28224 	DUK_ASSERT(h_this != NULL);
28225 
28226 	/* Argument must be a string, e.g. a buffer is not allowed. */
28227 	str_data = (const duk_uint8_t *) duk_require_lstring_notsymbol(thr, 0, &str_len);
28228 
28229 	duk__resolve_offset_opt_length(thr, h_this, 1, 2, &offset, &length, 0 /*throw_flag*/);
28230 	DUK_ASSERT(offset <= h_this->length);
28231 	DUK_ASSERT(offset + length <= h_this->length);
28232 
28233 	/* XXX: encoding is ignored now. */
28234 
28235 	if (length > str_len) {
28236 		length = (duk_uint_t) str_len;
28237 	}
28238 
28239 	if (DUK_HBUFOBJ_VALID_SLICE(h_this)) {
28240 		/* Cannot overlap. */
28241 		duk_memcpy_unsafe((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset),
28242 		                  (const void *) str_data,
28243 		                  (size_t) length);
28244 	} else {
28245 		DUK_DDD(DUK_DDDPRINT("write() target buffer is not covered, silent ignore"));
28246 	}
28247 
28248 	duk_push_uint(thr, length);
28249 	return 1;
28250 }
28251 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28252 
28253 /*
28254  *  Node.js Buffer.prototype.copy()
28255  */
28256 
28257 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_copy(duk_hthread * thr)28258 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_hthread *thr) {
28259 	duk_hbufobj *h_this;
28260 	duk_hbufobj *h_bufarg;
28261 	duk_int_t source_length;
28262 	duk_int_t target_length;
28263 	duk_int_t target_start, source_start, source_end;
28264 	duk_uint_t target_ustart, source_ustart, source_uend;
28265 	duk_uint_t copy_size = 0;
28266 
28267 	/* [ targetBuffer targetStart sourceStart sourceEnd ] */
28268 
28269 	h_this = duk__require_bufobj_this(thr);
28270 	h_bufarg = duk__require_bufobj_value(thr, 0);
28271 	DUK_ASSERT(h_this != NULL);
28272 	DUK_ASSERT(h_bufarg != NULL);
28273 	source_length = (duk_int_t) h_this->length;
28274 	target_length = (duk_int_t) h_bufarg->length;
28275 
28276 	target_start = duk_to_int(thr, 1);
28277 	source_start = duk_to_int(thr, 2);
28278 	if (duk_is_undefined(thr, 3)) {
28279 		source_end = source_length;
28280 	} else {
28281 		source_end = duk_to_int(thr, 3);
28282 	}
28283 
28284 	DUK_DDD(DUK_DDDPRINT("checking copy args: target_start=%ld, target_length=%ld, "
28285 	                     "source_start=%ld, source_end=%ld, source_length=%ld",
28286 	                     (long) target_start, (long) h_bufarg->length,
28287 	                     (long) source_start, (long) source_end, (long) source_length));
28288 
28289 	/* This behavior mostly mimics Node.js now. */
28290 
28291 	if (source_start < 0 || source_end < 0 || target_start < 0) {
28292 		/* Negative offsets cause a RangeError. */
28293 		goto fail_bounds;
28294 	}
28295 	source_ustart = (duk_uint_t) source_start;
28296 	source_uend = (duk_uint_t) source_end;
28297 	target_ustart = (duk_uint_t) target_start;
28298 	if (source_ustart >= source_uend ||  /* crossed offsets or zero size */
28299 	    source_ustart >= (duk_uint_t) source_length ||  /* source out-of-bounds (but positive) */
28300 	    target_ustart >= (duk_uint_t) target_length) {  /* target out-of-bounds (but positive) */
28301 		goto silent_ignore;
28302 	}
28303 	if (source_uend >= (duk_uint_t) source_length) {
28304 		/* Source end clamped silently to available length. */
28305 		source_uend = (duk_uint_t) source_length;
28306 	}
28307 	copy_size = source_uend - source_ustart;
28308 	if (target_ustart + copy_size > (duk_uint_t) target_length) {
28309 		/* Clamp to target's end if too long.
28310 		 *
28311 		 * NOTE: there's no overflow possibility in the comparison;
28312 		 * both target_ustart and copy_size are >= 0 and based on
28313 		 * values in duk_int_t range.  Adding them as duk_uint_t
28314 		 * values is then guaranteed not to overflow.
28315 		 */
28316 		DUK_ASSERT(target_ustart + copy_size >= target_ustart);  /* no overflow */
28317 		DUK_ASSERT(target_ustart + copy_size >= copy_size);  /* no overflow */
28318 		copy_size = (duk_uint_t) target_length - target_ustart;
28319 	}
28320 
28321 	DUK_DDD(DUK_DDDPRINT("making copy: target_ustart=%lu source_ustart=%lu copy_size=%lu",
28322 	                     (unsigned long) target_ustart, (unsigned long) source_ustart,
28323 	                     (unsigned long) copy_size));
28324 
28325 	DUK_ASSERT(copy_size >= 1);
28326 	DUK_ASSERT(source_ustart <= (duk_uint_t) source_length);
28327 	DUK_ASSERT(source_ustart + copy_size <= (duk_uint_t) source_length);
28328 	DUK_ASSERT(target_ustart <= (duk_uint_t) target_length);
28329 	DUK_ASSERT(target_ustart + copy_size <= (duk_uint_t) target_length);
28330 
28331 	/* Ensure copy is covered by underlying buffers. */
28332 	DUK_ASSERT(h_bufarg->buf != NULL);  /* length check */
28333 	DUK_ASSERT(h_this->buf != NULL);    /* length check */
28334 	if (DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufarg, target_ustart + copy_size) &&
28335 	    DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, source_ustart + copy_size)) {
28336 		/* Must use memmove() because copy area may overlap (source and target
28337 		 * buffer may be the same, or from different slices.
28338 		 */
28339 		duk_memmove_unsafe((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart),
28340 		                   (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + source_ustart),
28341 		                   (size_t) copy_size);
28342 	} else {
28343 		DUK_DDD(DUK_DDDPRINT("buffer copy not covered by underlying buffer(s), ignoring"));
28344 	}
28345 
28346  silent_ignore:
28347 	/* Return value is like write(), number of bytes written.
28348 	 * The return value matters because of code like:
28349 	 * "off += buf.copy(...)".
28350          */
28351 	duk_push_uint(thr, copy_size);
28352 	return 1;
28353 
28354  fail_bounds:
28355 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
28356 }
28357 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28358 
28359 /*
28360  *  TypedArray.prototype.set()
28361  *
28362  *  TypedArray set() is pretty interesting to implement because:
28363  *
28364  *    - The source argument may be a plain array or a typedarray.  If the
28365  *      source is a TypedArray, values are decoded and re-encoded into the
28366  *      target (not as a plain byte copy).  This may happen even when the
28367  *      element byte size is the same, e.g. integer values may be re-encoded
28368  *      into floats.
28369  *
28370  *    - Source and target may refer to the same underlying buffer, so that
28371  *      the set() operation may overlap.  The specification requires that this
28372  *      must work as if a copy was made before the operation.  Note that this
28373  *      is NOT a simple memmove() situation because the source and target
28374  *      byte sizes may be different -- e.g. a 4-byte source (Int8Array) may
28375  *      expand to a 16-byte target (Uint32Array) so that the target overlaps
28376  *      the source both from beginning and the end (unlike in typical memmove).
28377  *
28378  *    - Even if 'buf' pointers of the source and target differ, there's no
28379  *      guarantee that their memory areas don't overlap.  This may be the
28380  *      case with external buffers.
28381  *
28382  *  Even so, it is nice to optimize for the common case:
28383  *
28384  *    - Source and target separate buffers or non-overlapping.
28385  *
28386  *    - Source and target have a compatible type so that a plain byte copy
28387  *      is possible.  Note that while e.g. uint8 and int8 are compatible
28388  *      (coercion one way or another doesn't change the byte representation),
28389  *      e.g. int8 and uint8clamped are NOT compatible when writing int8
28390  *      values into uint8clamped typedarray (-1 would clamp to 0 for instance).
28391  *
28392  *  See test-bi-typedarray-proto-set.js.
28393  */
28394 
28395 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_typedarray_set(duk_hthread * thr)28396 DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_hthread *thr) {
28397 	duk_hbufobj *h_this;
28398 	duk_hobject *h_obj;
28399 	duk_uarridx_t i, n;
28400 	duk_int_t offset_signed;
28401 	duk_uint_t offset_elems;
28402 	duk_uint_t offset_bytes;
28403 
28404 	h_this = duk__require_bufobj_this(thr);
28405 	DUK_ASSERT(h_this != NULL);
28406 	DUK_HBUFOBJ_ASSERT_VALID(h_this);
28407 
28408 	if (h_this->buf == NULL) {
28409 		DUK_DDD(DUK_DDDPRINT("source neutered, skip copy"));
28410 		return 0;
28411 	}
28412 
28413 	duk_hbufobj_promote_plain(thr, 0);
28414 	h_obj = duk_require_hobject(thr, 0);
28415 
28416 	/* XXX: V8 throws a TypeError for negative values.  Would it
28417 	 * be more useful to interpret negative offsets here from the
28418 	 * end of the buffer too?
28419 	 */
28420 	offset_signed = duk_to_int(thr, 1);
28421 	if (offset_signed < 0) {
28422 		/* For some reason this is a TypeError (at least in V8). */
28423 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28424 	}
28425 	offset_elems = (duk_uint_t) offset_signed;
28426 	offset_bytes = offset_elems << h_this->shift;
28427 	if ((offset_bytes >> h_this->shift) != offset_elems) {
28428 		/* Byte length would overflow. */
28429 		/* XXX: easier check with less code? */
28430 		goto fail_args;
28431 	}
28432 	if (offset_bytes > h_this->length) {
28433 		/* Equality may be OK but >length not.  Checking
28434 		 * this explicitly avoids some overflow cases
28435 		 * below.
28436 		 */
28437 		goto fail_args;
28438 	}
28439 	DUK_ASSERT(offset_bytes <= h_this->length);
28440 
28441 	/* Fast path: source is a TypedArray (or any bufobj). */
28442 
28443 	if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
28444 		duk_hbufobj *h_bufarg;
28445 #if !defined(DUK_USE_PREFER_SIZE)
28446 		duk_uint16_t comp_mask;
28447 #endif
28448 		duk_small_int_t no_overlap = 0;
28449 		duk_uint_t src_length;
28450 		duk_uint_t dst_length;
28451 		duk_uint_t dst_length_elems;
28452 		duk_uint8_t *p_src_base;
28453 		duk_uint8_t *p_src_end;
28454 		duk_uint8_t *p_src;
28455 		duk_uint8_t *p_dst_base;
28456 		duk_uint8_t *p_dst;
28457 		duk_small_uint_t src_elem_size;
28458 		duk_small_uint_t dst_elem_size;
28459 
28460 		h_bufarg = (duk_hbufobj *) h_obj;
28461 		DUK_HBUFOBJ_ASSERT_VALID(h_bufarg);
28462 
28463 		if (h_bufarg->buf == NULL) {
28464 			DUK_DDD(DUK_DDDPRINT("target neutered, skip copy"));
28465 			return 0;
28466 		}
28467 
28468 		/* Nominal size check. */
28469 		src_length = h_bufarg->length;  /* bytes in source */
28470 		dst_length_elems = (src_length >> h_bufarg->shift);  /* elems in source and dest */
28471 		dst_length = dst_length_elems << h_this->shift;  /* bytes in dest */
28472 		if ((dst_length >> h_this->shift) != dst_length_elems) {
28473 			/* Byte length would overflow. */
28474 			/* XXX: easier check with less code? */
28475 			goto fail_args;
28476 		}
28477 		DUK_DDD(DUK_DDDPRINT("nominal size check: src_length=%ld, dst_length=%ld",
28478 		                     (long) src_length, (long) dst_length));
28479 		DUK_ASSERT(offset_bytes <= h_this->length);
28480 		if (dst_length > h_this->length - offset_bytes) {
28481 			/* Overflow not an issue because subtraction is used on the right
28482 			 * side and guaranteed to be >= 0.
28483 			 */
28484 			DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
28485 			goto fail_args;
28486 		}
28487 		if (!DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, offset_bytes + dst_length)) {
28488 			DUK_DDD(DUK_DDDPRINT("copy not covered by underlying target buffer, ignore"));
28489 			return 0;
28490 		}
28491 
28492 		p_src_base = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
28493 		p_dst_base = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset_bytes;
28494 
28495 		/* Check actual underlying buffers for validity and that they
28496 		 * cover the copy.  No side effects are allowed after the check
28497 		 * so that the validity status doesn't change.
28498 		 */
28499 		if (!DUK_HBUFOBJ_VALID_SLICE(h_this) ||
28500 		    !DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
28501 			/* The condition could be more narrow and check for the
28502 			 * copy area only, but there's no need for fine grained
28503 			 * behavior when the underlying buffer is misconfigured.
28504 			 */
28505 			DUK_DDD(DUK_DDDPRINT("source and/or target not covered by underlying buffer, skip copy"));
28506 			return 0;
28507 		}
28508 
28509 		/* We want to do a straight memory copy if possible: this is
28510 		 * an important operation because .set() is the TypedArray
28511 		 * way to copy chunks of memory.  However, because set()
28512 		 * conceptually works in terms of elements, not all views are
28513 		 * compatible with direct byte copying.
28514 		 *
28515 		 * If we do manage a direct copy, the "overlap issue" handled
28516 		 * below can just be solved using memmove() because the source
28517 		 * and destination element sizes are necessarily equal.
28518 		 */
28519 
28520 #if !defined(DUK_USE_PREFER_SIZE)
28521 		DUK_ASSERT(h_this->elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
28522 		comp_mask = duk__buffer_elemtype_copy_compatible[h_this->elem_type];
28523 		if (comp_mask & (1 << h_bufarg->elem_type)) {
28524 			DUK_ASSERT(src_length == dst_length);
28525 
28526 			DUK_DDD(DUK_DDDPRINT("fast path: able to use memmove() because views are compatible"));
28527 			duk_memmove_unsafe((void *) p_dst_base, (const void *) p_src_base, (size_t) dst_length);
28528 			return 0;
28529 		}
28530 		DUK_DDD(DUK_DDDPRINT("fast path: views are not compatible with a byte copy, copy by item"));
28531 #endif  /* !DUK_USE_PREFER_SIZE */
28532 
28533 		/* We want to avoid making a copy to process set() but that's
28534 		 * not always possible: the source and the target may overlap
28535 		 * and because element sizes are different, the overlap cannot
28536 		 * always be handled with a memmove() or choosing the copy
28537 		 * direction in a certain way.  For example, if source type is
28538 		 * uint8 and target type is uint32, the target area may exceed
28539 		 * the source area from both ends!
28540 		 *
28541 		 * Note that because external buffers may point to the same
28542 		 * memory areas, we must ultimately make this check using
28543 		 * pointers.
28544 		 *
28545 		 * NOTE: careful with side effects: any side effect may cause
28546 		 * a buffer resize (or external buffer pointer/length update)!
28547 		 */
28548 
28549 		DUK_DDD(DUK_DDDPRINT("overlap check: p_src_base=%p, src_length=%ld, "
28550 		                     "p_dst_base=%p, dst_length=%ld",
28551 		                     (void *) p_src_base, (long) src_length,
28552 		                     (void *) p_dst_base, (long) dst_length));
28553 
28554 		if (p_src_base >= p_dst_base + dst_length ||  /* source starts after dest ends */
28555 		    p_src_base + src_length <= p_dst_base) {   /* source ends before dest starts */
28556 			no_overlap = 1;
28557 		}
28558 
28559 		if (!no_overlap) {
28560 			/* There's overlap: the desired end result is that
28561 			 * conceptually a copy is made to avoid "trampling"
28562 			 * of source data by destination writes.  We make
28563 			 * an actual temporary copy to handle this case.
28564 			 */
28565 			duk_uint8_t *p_src_copy;
28566 
28567 			DUK_DDD(DUK_DDDPRINT("there is overlap, make a copy of the source"));
28568 			p_src_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_length);
28569 			DUK_ASSERT(p_src_copy != NULL);
28570 			duk_memcpy_unsafe((void *) p_src_copy, (const void *) p_src_base, (size_t) src_length);
28571 
28572 			p_src_base = p_src_copy;  /* use p_src_base from now on */
28573 		}
28574 		/* Value stack intentionally mixed size here. */
28575 
28576 		DUK_DDD(DUK_DDDPRINT("after overlap check: p_src_base=%p, src_length=%ld, "
28577 		                     "p_dst_base=%p, dst_length=%ld, valstack top=%ld",
28578 		                     (void *) p_src_base, (long) src_length,
28579 		                     (void *) p_dst_base, (long) dst_length,
28580 		                     (long) duk_get_top(thr)));
28581 
28582 		/* Ready to make the copy.  We must proceed element by element
28583 		 * and must avoid any side effects that might cause the buffer
28584 		 * validity check above to become invalid.
28585 		 *
28586 		 * Although we work through the value stack here, only plain
28587 		 * numbers are handled which should be side effect safe.
28588 		 */
28589 
28590 		src_elem_size = (duk_small_uint_t) (1U << h_bufarg->shift);
28591 		dst_elem_size = (duk_small_uint_t) (1U << h_this->shift);
28592 		p_src = p_src_base;
28593 		p_dst = p_dst_base;
28594 		p_src_end = p_src_base + src_length;
28595 
28596 		while (p_src != p_src_end) {
28597 			DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
28598 			                     "p_src=%p, p_src_end=%p, p_dst=%p",
28599 			                     (void *) p_src, (void *) p_src_end, (void *) p_dst));
28600 			/* A validated read() is always a number, so it's write coercion
28601 			 * is always side effect free an won't invalidate pointers etc.
28602 			 */
28603 			duk_hbufobj_push_validated_read(thr, h_bufarg, p_src, src_elem_size);
28604 			duk_hbufobj_validated_write(thr, h_this, p_dst, dst_elem_size);
28605 			duk_pop(thr);
28606 			p_src += src_elem_size;
28607 			p_dst += dst_elem_size;
28608 		}
28609 
28610 		return 0;
28611 	} else {
28612 		/* Slow path: quite slow, but we save space by using the property code
28613 		 * to write coerce target values.  We don't need to worry about overlap
28614 		 * here because the source is not a TypedArray.
28615 		 *
28616 		 * We could use the bufobj write coercion helper but since the
28617 		 * property read may have arbitrary side effects, full validity checks
28618 		 * would be needed for every element anyway.
28619 		 */
28620 
28621 		n = (duk_uarridx_t) duk_get_length(thr, 0);
28622 		DUK_ASSERT(offset_bytes <= h_this->length);
28623 		if ((n << h_this->shift) > h_this->length - offset_bytes) {
28624 			/* Overflow not an issue because subtraction is used on the right
28625 			 * side and guaranteed to be >= 0.
28626 			 */
28627 			DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
28628 			goto fail_args;
28629 		}
28630 
28631 		/* There's no need to check for buffer validity status for the
28632 		 * target here: the property access code will do that for each
28633 		 * element.  Moreover, if we did check the validity here, side
28634 		 * effects from reading the source argument might invalidate
28635 		 * the results anyway.
28636 		 */
28637 
28638 		DUK_ASSERT_TOP(thr, 2);
28639 		duk_push_this(thr);
28640 
28641 		for (i = 0; i < n; i++) {
28642 			duk_get_prop_index(thr, 0, i);
28643 			duk_put_prop_index(thr, 2, offset_elems + i);
28644 		}
28645 	}
28646 
28647 	return 0;
28648 
28649  fail_args:
28650 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
28651 }
28652 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28653 
28654 /*
28655  *  Node.js Buffer.prototype.slice([start], [end])
28656  *  ArrayBuffer.prototype.slice(begin, [end])
28657  *  TypedArray.prototype.subarray(begin, [end])
28658  *
28659  *  The API calls are almost identical; negative indices are counted from end
28660  *  of buffer, and final indices are clamped (allowing crossed indices).  Main
28661  *  differences:
28662  *
28663  *    - Copy/view behavior; Node.js .slice() and TypedArray .subarray() create
28664  *      views, ArrayBuffer .slice() creates a copy
28665  *
28666  *    - Resulting object has a different class and prototype depending on the
28667  *      call (or 'this' argument)
28668  *
28669  *    - TypedArray .subarray() arguments are element indices, not byte offsets
28670  *
28671  *    - Plain buffer argument creates a plain buffer slice
28672  */
28673 
28674 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk__arraybuffer_plain_slice(duk_hthread * thr,duk_hbuffer * h_val)28675 DUK_LOCAL void duk__arraybuffer_plain_slice(duk_hthread *thr, duk_hbuffer *h_val) {
28676 	duk_int_t start_offset, end_offset;
28677 	duk_uint_t slice_length;
28678 	duk_uint8_t *p_copy;
28679 	duk_size_t copy_length;
28680 
28681 	duk__clamp_startend_negidx_shifted(thr,
28682 	                                   (duk_int_t) DUK_HBUFFER_GET_SIZE(h_val),
28683 	                                   0 /*buffer_shift*/,
28684 	                                   0 /*idx_start*/,
28685 	                                   1 /*idx_end*/,
28686 	                                   &start_offset,
28687 	                                   &end_offset);
28688 	DUK_ASSERT(end_offset <= (duk_int_t) DUK_HBUFFER_GET_SIZE(h_val));
28689 	DUK_ASSERT(start_offset >= 0);
28690 	DUK_ASSERT(end_offset >= start_offset);
28691 	slice_length = (duk_uint_t) (end_offset - start_offset);
28692 
28693 	p_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) slice_length);
28694 	DUK_ASSERT(p_copy != NULL);
28695 	copy_length = slice_length;
28696 
28697 	duk_memcpy_unsafe((void *) p_copy,
28698 	                  (const void *) ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_val) + start_offset),
28699 	                  copy_length);
28700 }
28701 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
28702 
28703 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
28704 /* Shared helper for slice/subarray operation.
28705  * Magic: 0x01=isView, 0x02=copy, 0x04=Node.js Buffer special handling.
28706  */
duk_bi_buffer_slice_shared(duk_hthread * thr)28707 DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_hthread *thr) {
28708 	duk_small_int_t magic;
28709 	duk_small_uint_t res_class_num;
28710 	duk_small_int_t res_proto_bidx;
28711 	duk_hbufobj *h_this;
28712 	duk_hbufobj *h_bufobj;
28713 	duk_hbuffer *h_val;
28714 	duk_int_t start_offset, end_offset;
28715 	duk_uint_t slice_length;
28716 	duk_tval *tv;
28717 
28718 	/* [ start end ] */
28719 
28720 	magic = duk_get_current_magic(thr);
28721 
28722 	tv = duk_get_borrowed_this_tval(thr);
28723 	DUK_ASSERT(tv != NULL);
28724 
28725 	if (DUK_TVAL_IS_BUFFER(tv)) {
28726 		/* For plain buffers return a plain buffer slice. */
28727 		h_val = DUK_TVAL_GET_BUFFER(tv);
28728 		DUK_ASSERT(h_val != NULL);
28729 
28730 		if (magic & 0x02) {
28731 			/* Make copy: ArrayBuffer.prototype.slice() uses this. */
28732 			duk__arraybuffer_plain_slice(thr, h_val);
28733 			return 1;
28734 		} else {
28735 			/* View into existing buffer: cannot be done if the
28736 			 * result is a plain buffer because there's no slice
28737 			 * info.  So return an ArrayBuffer instance; coerce
28738 			 * the 'this' binding into an object and behave as if
28739 			 * the original call was for an Object-coerced plain
28740 			 * buffer (handled automatically by duk__require_bufobj_this()).
28741 			 */
28742 
28743 			DUK_DDD(DUK_DDDPRINT("slice() doesn't handle view into plain buffer, coerce 'this' to ArrayBuffer object"));
28744 			/* fall through */
28745 		}
28746 	}
28747 	tv = NULL;  /* No longer valid nor needed. */
28748 
28749 	h_this = duk__require_bufobj_this(thr);
28750 
28751 	/* Slice offsets are element (not byte) offsets, which only matters
28752 	 * for TypedArray views, Node.js Buffer and ArrayBuffer have shift
28753 	 * zero so byte and element offsets are the same.  Negative indices
28754 	 * are counted from end of slice, crossed indices are allowed (and
28755 	 * result in zero length result), and final values are clamped
28756 	 * against the current slice.  There's intentionally no check
28757 	 * against the underlying buffer here.
28758 	 */
28759 
28760 	duk__clamp_startend_negidx_shifted(thr,
28761 	                                   (duk_int_t) h_this->length,
28762 	                                   (duk_uint8_t) h_this->shift,
28763 	                                   0 /*idx_start*/,
28764 	                                   1 /*idx_end*/,
28765 	                                   &start_offset,
28766 	                                   &end_offset);
28767 	DUK_ASSERT(end_offset >= start_offset);
28768 	DUK_ASSERT(start_offset >= 0);
28769 	DUK_ASSERT(end_offset >= 0);
28770 	slice_length = (duk_uint_t) (end_offset - start_offset);
28771 
28772 	/* The resulting buffer object gets the same class and prototype as
28773 	 * the buffer in 'this', e.g. if the input is a Uint8Array the
28774 	 * result is a Uint8Array; if the input is a Float32Array, the
28775 	 * result is a Float32Array.  The result internal prototype should
28776 	 * be the default prototype for the class (e.g. initial value of
28777 	 * Uint8Array.prototype), not copied from the argument (Duktape 1.x
28778 	 * did that).
28779 	 *
28780 	 * Node.js Buffers have special handling: they're Uint8Arrays as far
28781 	 * as the internal class is concerned, so the new Buffer should also
28782 	 * be an Uint8Array but inherit from Buffer.prototype.
28783 	 */
28784 	res_class_num = DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_this);
28785 	DUK_ASSERT(res_class_num >= DUK_HOBJECT_CLASS_BUFOBJ_MIN);  /* type check guarantees */
28786 	DUK_ASSERT(res_class_num <= DUK_HOBJECT_CLASS_BUFOBJ_MAX);
28787 	res_proto_bidx = duk__buffer_proto_from_classnum[res_class_num - DUK_HOBJECT_CLASS_BUFOBJ_MIN];
28788 	if (magic & 0x04) {
28789 		res_proto_bidx = DUK_BIDX_NODEJS_BUFFER_PROTOTYPE;
28790 	}
28791 	h_bufobj = duk_push_bufobj_raw(thr,
28792 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
28793 	                               DUK_HOBJECT_FLAG_BUFOBJ |
28794 	                               DUK_HOBJECT_CLASS_AS_FLAGS(res_class_num),
28795 	                               res_proto_bidx);
28796 	DUK_ASSERT(h_bufobj != NULL);
28797 
28798 	DUK_ASSERT(h_bufobj->length == 0);
28799 	h_bufobj->shift = h_this->shift;  /* inherit */
28800 	h_bufobj->elem_type = h_this->elem_type;  /* inherit */
28801 	h_bufobj->is_typedarray = magic & 0x01;
28802 	DUK_ASSERT(h_bufobj->is_typedarray == 0 || h_bufobj->is_typedarray == 1);
28803 
28804 	h_val = h_this->buf;
28805 	if (h_val == NULL) {
28806 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28807 	}
28808 
28809 	if (magic & 0x02) {
28810 		/* non-zero: make copy */
28811 		duk_uint8_t *p_copy;
28812 		duk_size_t copy_length;
28813 
28814 		p_copy = (duk_uint8_t *) duk_push_fixed_buffer_zero(thr, (duk_size_t) slice_length);  /* must be zeroed, not all bytes always copied */
28815 		DUK_ASSERT(p_copy != NULL);
28816 
28817 		/* Copy slice, respecting underlying buffer limits; remainder
28818 		 * is left as zero.
28819 		 */
28820 		copy_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, slice_length);
28821 		duk_memcpy_unsafe((void *) p_copy,
28822 		                  (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
28823 		                  copy_length);
28824 
28825 		h_val = duk_known_hbuffer(thr, -1);
28826 
28827 		h_bufobj->buf = h_val;
28828 		DUK_HBUFFER_INCREF(thr, h_val);
28829 		h_bufobj->length = slice_length;
28830 		DUK_ASSERT(h_bufobj->offset == 0);
28831 
28832 		duk_pop(thr);  /* reachable so pop OK */
28833 	} else {
28834 		h_bufobj->buf = h_val;
28835 		DUK_HBUFFER_INCREF(thr, h_val);
28836 		h_bufobj->length = slice_length;
28837 		h_bufobj->offset = h_this->offset + (duk_uint_t) start_offset;
28838 
28839 		/* Copy the .buffer property, needed for TypedArray.prototype.subarray().
28840 		 *
28841 		 * XXX: limit copy only for TypedArray classes specifically?
28842 		 */
28843 
28844 		DUK_ASSERT(h_bufobj->buf_prop == NULL);
28845 		h_bufobj->buf_prop = h_this->buf_prop;  /* may be NULL */
28846 		DUK_HOBJECT_INCREF_ALLOWNULL(thr, (duk_hobject *) h_bufobj->buf_prop);
28847 	}
28848 	/* unbalanced stack on purpose */
28849 
28850 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
28851 	return 1;
28852 }
28853 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28854 
28855 /*
28856  *  Node.js Buffer.isEncoding()
28857  */
28858 
28859 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_is_encoding(duk_hthread * thr)28860 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_hthread *thr) {
28861 	const char *encoding;
28862 
28863 	/* only accept lowercase 'utf8' now. */
28864 
28865 	encoding = duk_to_string(thr, 0);
28866 	DUK_ASSERT(duk_is_string(thr, 0));  /* guaranteed by duk_to_string() */
28867 	duk_push_boolean(thr, DUK_STRCMP(encoding, "utf8") == 0);
28868 	return 1;
28869 }
28870 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28871 
28872 /*
28873  *  Node.js Buffer.isBuffer()
28874  */
28875 
28876 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_is_buffer(duk_hthread * thr)28877 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_hthread *thr) {
28878 	duk_hobject *h;
28879 	duk_hobject *h_proto;
28880 	duk_bool_t ret = 0;
28881 
28882 	DUK_ASSERT(duk_get_top(thr) >= 1);  /* nargs */
28883 	h = duk_get_hobject(thr, 0);
28884 	if (h != NULL) {
28885 		h_proto = thr->builtins[DUK_BIDX_NODEJS_BUFFER_PROTOTYPE];
28886 		DUK_ASSERT(h_proto != NULL);
28887 
28888 		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
28889 		if (h != NULL) {
28890 			ret = duk_hobject_prototype_chain_contains(thr, h, h_proto, 0 /*ignore_loop*/);
28891 		}
28892 	}
28893 
28894 	duk_push_boolean(thr, ret);
28895 	return 1;
28896 }
28897 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28898 
28899 /*
28900  *  Node.js Buffer.byteLength()
28901  */
28902 
28903 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_byte_length(duk_hthread * thr)28904 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_hthread *thr) {
28905 	const char *str;
28906 	duk_size_t len;
28907 
28908 	/* At the moment Buffer(<str>) will just use the string bytes as
28909 	 * is (ignoring encoding), so we return the string length here
28910 	 * unconditionally.
28911 	 */
28912 
28913 	/* XXX: to be revised; Old Node.js behavior just coerces any buffer
28914 	 * values to string:
28915 	 * $ node
28916 	 * > Buffer.byteLength(new Uint32Array(10))
28917 	 * 20
28918 	 * > Buffer.byteLength(new Uint32Array(100))
28919 	 * 20
28920 	 * (The 20 comes from '[object Uint32Array]'.length
28921 	 */
28922 
28923 	str = duk_to_lstring(thr, 0, &len);
28924 	DUK_UNREF(str);
28925 	duk_push_size_t(thr, len);
28926 	return 1;
28927 }
28928 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28929 
28930 /*
28931  *  Node.js Buffer.concat()
28932  */
28933 
28934 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_concat(duk_hthread * thr)28935 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_hthread *thr) {
28936 	duk_hobject *h_arg;
28937 	duk_uint_t total_length;
28938 	duk_hbufobj *h_bufobj;
28939 	duk_hbufobj *h_bufres;
28940 	duk_hbuffer *h_val;
28941 	duk_uint_t i, n;
28942 	duk_uint8_t *p;
28943 	duk_size_t space_left;
28944 	duk_size_t copy_size;
28945 
28946 	/* Node.js accepts only actual Arrays. */
28947 	h_arg = duk_require_hobject(thr, 0);
28948 	if (DUK_HOBJECT_GET_CLASS_NUMBER(h_arg) != DUK_HOBJECT_CLASS_ARRAY) {
28949 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28950 	}
28951 
28952 	/* Compute result length and validate argument buffers. */
28953 	n = (duk_uint_t) duk_get_length(thr, 0);
28954 	total_length = 0;
28955 	for (i = 0; i < n; i++) {
28956 		/* Neutered checks not necessary here: neutered buffers have
28957 		 * zero 'length' so we'll effectively skip them.
28958 		 */
28959 		DUK_ASSERT_TOP(thr, 2);  /* [ array totalLength ] */
28960 		duk_get_prop_index(thr, 0, (duk_uarridx_t) i);  /* -> [ array totalLength buf ] */
28961 		h_bufobj = duk__require_bufobj_value(thr, 2);
28962 		DUK_ASSERT(h_bufobj != NULL);
28963 		total_length += h_bufobj->length;
28964 		if (DUK_UNLIKELY(total_length < h_bufobj->length)) {
28965 			DUK_DCERROR_RANGE_INVALID_ARGS(thr);  /* Wrapped. */
28966 		}
28967 		duk_pop(thr);
28968 	}
28969 	/* In Node.js v0.12.1 a 1-element array is special and won't create a
28970 	 * copy, this was fixed later so an explicit check no longer needed.
28971 	 */
28972 
28973 	/* User totalLength overrides a computed length, but we'll check
28974 	 * every copy in the copy loop.  Note that duk_to_int() can
28975 	 * technically have arbitrary side effects so we need to recheck
28976 	 * the buffers in the copy loop.
28977 	 */
28978 	if (!duk_is_undefined(thr, 1) && n > 0) {
28979 		/* For n == 0, Node.js ignores totalLength argument and
28980 		 * returns a zero length buffer.
28981 		 */
28982 		duk_int_t total_length_signed;
28983 		total_length_signed = duk_to_int(thr, 1);
28984 		if (total_length_signed < 0) {
28985 			DUK_DCERROR_RANGE_INVALID_ARGS(thr);
28986 		}
28987 		total_length = (duk_uint_t) total_length_signed;
28988 	}
28989 
28990 	h_bufres = duk_push_bufobj_raw(thr,
28991 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
28992 	                               DUK_HOBJECT_FLAG_BUFOBJ |
28993 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_UINT8ARRAY),
28994 	                               DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
28995 	DUK_ASSERT(h_bufres != NULL);
28996 
28997 	p = (duk_uint8_t *) duk_push_fixed_buffer_zero(thr, total_length);  /* must be zeroed, all bytes not necessarily written over */
28998 	DUK_ASSERT(p != NULL);
28999 	space_left = (duk_size_t) total_length;
29000 
29001 	for (i = 0; i < n; i++) {
29002 		DUK_ASSERT_TOP(thr, 4);  /* [ array totalLength bufres buf ] */
29003 
29004 		duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
29005 		h_bufobj = duk__require_bufobj_value(thr, 4);
29006 		DUK_ASSERT(h_bufobj != NULL);
29007 
29008 		copy_size = h_bufobj->length;
29009 		if (copy_size > space_left) {
29010 			copy_size = space_left;
29011 		}
29012 
29013 		if (h_bufobj->buf != NULL &&
29014 		    DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
29015 			duk_memcpy_unsafe((void *) p,
29016 			                  (const void *) DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj),
29017 			                  copy_size);
29018 		} else {
29019 			/* Just skip, leaving zeroes in the result. */
29020 			;
29021 		}
29022 		p += copy_size;
29023 		space_left -= copy_size;
29024 
29025 		duk_pop(thr);
29026 	}
29027 
29028 	h_val = duk_known_hbuffer(thr, -1);
29029 
29030 	duk__set_bufobj_buffer(thr, h_bufres, h_val);
29031 	h_bufres->is_typedarray = 1;
29032 	DUK_HBUFOBJ_ASSERT_VALID(h_bufres);
29033 
29034 	duk_pop(thr);  /* pop plain buffer, now reachable through h_bufres */
29035 
29036 	return 1;  /* return h_bufres */
29037 }
29038 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29039 
29040 /*
29041  *  Shared readfield and writefield methods
29042  *
29043  *  The readfield/writefield methods need support for endianness and field
29044  *  types.  All offsets are byte based so no offset shifting is needed.
29045  */
29046 
29047 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29048 /* Format of magic, bits:
29049  *   0...1: field type; 0=uint8, 1=uint16, 2=uint32, 3=float, 4=double, 5=unused, 6=unused, 7=unused
29050  *       3: endianness: 0=little, 1=big
29051  *       4: signed: 1=yes, 0=no
29052  *       5: typedarray: 1=yes, 0=no
29053  */
29054 #define  DUK__FLD_8BIT         0
29055 #define  DUK__FLD_16BIT        1
29056 #define  DUK__FLD_32BIT        2
29057 #define  DUK__FLD_FLOAT        3
29058 #define  DUK__FLD_DOUBLE       4
29059 #define  DUK__FLD_VARINT       5
29060 #define  DUK__FLD_BIGENDIAN    (1 << 3)
29061 #define  DUK__FLD_SIGNED       (1 << 4)
29062 #define  DUK__FLD_TYPEDARRAY   (1 << 5)
29063 
29064 /* XXX: split into separate functions for each field type? */
duk_bi_buffer_readfield(duk_hthread * thr)29065 DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
29066 	duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(thr);
29067 	duk_small_int_t magic_ftype;
29068 	duk_small_int_t magic_bigendian;
29069 	duk_small_int_t magic_signed;
29070 	duk_small_int_t magic_typedarray;
29071 	duk_small_int_t endswap;
29072 	duk_hbufobj *h_this;
29073 	duk_bool_t no_assert;
29074 	duk_int_t offset_signed;
29075 	duk_uint_t offset;
29076 	duk_uint_t buffer_length;
29077 	duk_uint_t check_length;
29078 	duk_uint8_t *buf;
29079 	duk_double_union du;
29080 
29081 	magic_ftype = magic & 0x0007;
29082 	magic_bigendian = magic & 0x0008;
29083 	magic_signed = magic & 0x0010;
29084 	magic_typedarray = magic & 0x0020;
29085 
29086 	h_this = duk__require_bufobj_this(thr);  /* XXX: very inefficient for plain buffers */
29087 	DUK_ASSERT(h_this != NULL);
29088 	buffer_length = h_this->length;
29089 
29090 	/* [ offset noAssert                 ], when ftype != DUK__FLD_VARINT */
29091 	/* [ offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
29092 	/* [ offset littleEndian             ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
29093 
29094 	/* Handle TypedArray vs. Node.js Buffer arg differences */
29095 	if (magic_typedarray) {
29096 		no_assert = 0;
29097 #if defined(DUK_USE_INTEGER_LE)
29098 		endswap = !duk_to_boolean(thr, 1);  /* 1=little endian */
29099 #else
29100 		endswap = duk_to_boolean(thr, 1);  /* 1=little endian */
29101 #endif
29102 	} else {
29103 		no_assert = duk_to_boolean(thr, (magic_ftype == DUK__FLD_VARINT) ? 2 : 1);
29104 #if defined(DUK_USE_INTEGER_LE)
29105 		endswap = magic_bigendian;
29106 #else
29107 		endswap = !magic_bigendian;
29108 #endif
29109 	}
29110 
29111 	/* Offset is coerced first to signed integer range and then to unsigned.
29112 	 * This ensures we can add a small byte length (1-8) to the offset in
29113 	 * bound checks and not wrap.
29114 	 */
29115 	offset_signed = duk_to_int(thr, 0);
29116 	offset = (duk_uint_t) offset_signed;
29117 	if (offset_signed < 0) {
29118 		goto fail_bounds;
29119 	}
29120 
29121 	DUK_DDD(DUK_DDDPRINT("readfield, buffer_length=%ld, offset=%ld, no_assert=%d, "
29122 	                     "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
29123 	                     "endswap=%d",
29124 	                     (long) buffer_length, (long) offset, (int) no_assert,
29125 	                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
29126 	                     (int) (magic_signed >> 4), (int) endswap));
29127 
29128 	/* Update 'buffer_length' to be the effective, safe limit which
29129 	 * takes into account the underlying buffer.  This value will be
29130 	 * potentially invalidated by any side effect.
29131 	 */
29132 	check_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);
29133 	DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
29134 	                     (long) buffer_length, (long) check_length));
29135 
29136 	if (h_this->buf) {
29137 		buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
29138 	} else {
29139 		/* Neutered.  We could go into the switch-case safely with
29140 		 * buf == NULL because check_length == 0.  To avoid scanbuild
29141 		 * warnings, fail directly instead.
29142 		 */
29143 		DUK_ASSERT(check_length == 0);
29144 		goto fail_neutered;
29145 	}
29146 	DUK_ASSERT(buf != NULL);
29147 
29148 	switch (magic_ftype) {
29149 	case DUK__FLD_8BIT: {
29150 		duk_uint8_t tmp;
29151 		if (offset + 1U > check_length) {
29152 			goto fail_bounds;
29153 		}
29154 		tmp = buf[offset];
29155 		if (magic_signed) {
29156 			duk_push_int(thr, (duk_int_t) ((duk_int8_t) tmp));
29157 		} else {
29158 			duk_push_uint(thr, (duk_uint_t) tmp);
29159 		}
29160 		break;
29161 	}
29162 	case DUK__FLD_16BIT: {
29163 		duk_uint16_t tmp;
29164 		if (offset + 2U > check_length) {
29165 			goto fail_bounds;
29166 		}
29167 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 2);
29168 		tmp = du.us[0];
29169 		if (endswap) {
29170 			tmp = DUK_BSWAP16(tmp);
29171 		}
29172 		if (magic_signed) {
29173 			duk_push_int(thr, (duk_int_t) ((duk_int16_t) tmp));
29174 		} else {
29175 			duk_push_uint(thr, (duk_uint_t) tmp);
29176 		}
29177 		break;
29178 	}
29179 	case DUK__FLD_32BIT: {
29180 		duk_uint32_t tmp;
29181 		if (offset + 4U > check_length) {
29182 			goto fail_bounds;
29183 		}
29184 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 4);
29185 		tmp = du.ui[0];
29186 		if (endswap) {
29187 			tmp = DUK_BSWAP32(tmp);
29188 		}
29189 		if (magic_signed) {
29190 			duk_push_int(thr, (duk_int_t) ((duk_int32_t) tmp));
29191 		} else {
29192 			duk_push_uint(thr, (duk_uint_t) tmp);
29193 		}
29194 		break;
29195 	}
29196 	case DUK__FLD_FLOAT: {
29197 		duk_uint32_t tmp;
29198 		if (offset + 4U > check_length) {
29199 			goto fail_bounds;
29200 		}
29201 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 4);
29202 		if (endswap) {
29203 			tmp = du.ui[0];
29204 			tmp = DUK_BSWAP32(tmp);
29205 			du.ui[0] = tmp;
29206 		}
29207 		duk_push_number(thr, (duk_double_t) du.f[0]);
29208 		break;
29209 	}
29210 	case DUK__FLD_DOUBLE: {
29211 		if (offset + 8U > check_length) {
29212 			goto fail_bounds;
29213 		}
29214 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 8);
29215 		if (endswap) {
29216 			DUK_DBLUNION_BSWAP64(&du);
29217 		}
29218 		duk_push_number(thr, (duk_double_t) du.d);
29219 		break;
29220 	}
29221 	case DUK__FLD_VARINT: {
29222 		/* Node.js Buffer variable width integer field.  We don't really
29223 		 * care about speed here, so aim for shortest algorithm.
29224 		 */
29225 		duk_int_t field_bytelen;
29226 		duk_int_t i, i_step, i_end;
29227 #if defined(DUK_USE_64BIT_OPS)
29228 		duk_int64_t tmp;
29229 		duk_small_uint_t shift_tmp;
29230 #else
29231 		duk_double_t tmp;
29232 		duk_small_int_t highbyte;
29233 #endif
29234 		const duk_uint8_t *p;
29235 
29236 		field_bytelen = duk_get_int(thr, 1);  /* avoid side effects! */
29237 		if (field_bytelen < 1 || field_bytelen > 6) {
29238 			goto fail_field_length;
29239 		}
29240 		if (offset + (duk_uint_t) field_bytelen > check_length) {
29241 			goto fail_bounds;
29242 		}
29243 		p = (const duk_uint8_t *) (buf + offset);
29244 
29245 		/* Slow gathering of value using either 64-bit arithmetic
29246 		 * or IEEE doubles if 64-bit types not available.  Handling
29247 		 * of negative numbers is a bit non-obvious in both cases.
29248 		 */
29249 
29250 		if (magic_bigendian) {
29251 			/* Gather in big endian */
29252 			i = 0;
29253 			i_step = 1;
29254 			i_end = field_bytelen;  /* one i_step over */
29255 		} else {
29256 			/* Gather in little endian */
29257 			i = field_bytelen - 1;
29258 			i_step = -1;
29259 			i_end = -1;  /* one i_step over */
29260 		}
29261 
29262 #if defined(DUK_USE_64BIT_OPS)
29263 		tmp = 0;
29264 		do {
29265 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29266 			tmp = (tmp << 8) + (duk_int64_t) p[i];
29267 			i += i_step;
29268 		} while (i != i_end);
29269 
29270 		if (magic_signed) {
29271 			/* Shift to sign extend.  Left shift must be unsigned
29272 			 * to avoid undefined behavior; right shift must be
29273 			 * signed to sign extend properly.
29274 			 */
29275 			shift_tmp = (duk_small_uint_t) (64U - (duk_small_uint_t) field_bytelen * 8U);
29276 			tmp = (duk_int64_t) ((duk_uint64_t) tmp << shift_tmp) >> shift_tmp;
29277 		}
29278 
29279 		duk_push_i64(thr, tmp);
29280 #else
29281 		highbyte = p[i];
29282 		if (magic_signed && (highbyte & 0x80) != 0) {
29283 			/* 0xff => 255 - 256 = -1; 0x80 => 128 - 256 = -128 */
29284 			tmp = (duk_double_t) (highbyte - 256);
29285 		} else {
29286 			tmp = (duk_double_t) highbyte;
29287 		}
29288 		for (;;) {
29289 			i += i_step;
29290 			if (i == i_end) {
29291 				break;
29292 			}
29293 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29294 			tmp = (tmp * 256.0) + (duk_double_t) p[i];
29295 		}
29296 
29297 		duk_push_number(thr, tmp);
29298 #endif
29299 		break;
29300 	}
29301 	default: {  /* should never happen but default here */
29302 		goto fail_bounds;
29303 	}
29304 	}
29305 
29306 	return 1;
29307 
29308  fail_neutered:
29309  fail_field_length:
29310  fail_bounds:
29311 	if (no_assert) {
29312 		/* Node.js return value for noAssert out-of-bounds reads is
29313 		 * usually (but not always) NaN.  Return NaN consistently.
29314 		 */
29315 		duk_push_nan(thr);
29316 		return 1;
29317 	}
29318 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
29319 }
29320 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29321 
29322 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29323 /* XXX: split into separate functions for each field type? */
duk_bi_buffer_writefield(duk_hthread * thr)29324 DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
29325 	duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(thr);
29326 	duk_small_int_t magic_ftype;
29327 	duk_small_int_t magic_bigendian;
29328 	duk_small_int_t magic_signed;
29329 	duk_small_int_t magic_typedarray;
29330 	duk_small_int_t endswap;
29331 	duk_hbufobj *h_this;
29332 	duk_bool_t no_assert;
29333 	duk_int_t offset_signed;
29334 	duk_uint_t offset;
29335 	duk_uint_t buffer_length;
29336 	duk_uint_t check_length;
29337 	duk_uint8_t *buf;
29338 	duk_double_union du;
29339 	duk_int_t nbytes = 0;
29340 
29341 	magic_ftype = magic & 0x0007;
29342 	magic_bigendian = magic & 0x0008;
29343 	magic_signed = magic & 0x0010;
29344 	magic_typedarray = magic & 0x0020;
29345 	DUK_UNREF(magic_signed);
29346 
29347 	h_this = duk__require_bufobj_this(thr);  /* XXX: very inefficient for plain buffers */
29348 	DUK_ASSERT(h_this != NULL);
29349 	buffer_length = h_this->length;
29350 
29351 	/* [ value  offset noAssert                 ], when ftype != DUK__FLD_VARINT */
29352 	/* [ value  offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
29353 	/* [ offset value  littleEndian             ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
29354 
29355 	/* Handle TypedArray vs. Node.js Buffer arg differences */
29356 	if (magic_typedarray) {
29357 		no_assert = 0;
29358 #if defined(DUK_USE_INTEGER_LE)
29359 		endswap = !duk_to_boolean(thr, 2);  /* 1=little endian */
29360 #else
29361 		endswap = duk_to_boolean(thr, 2);  /* 1=little endian */
29362 #endif
29363 		duk_swap(thr, 0, 1);  /* offset/value order different from Node.js */
29364 	} else {
29365 		no_assert = duk_to_boolean(thr, (magic_ftype == DUK__FLD_VARINT) ? 3 : 2);
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, 1);
29378 	offset = (duk_uint_t) offset_signed;
29379 
29380 	/* We need 'nbytes' even for a failed offset; return value must be
29381 	 * (offset + nbytes) even when write fails due to invalid offset.
29382 	 */
29383 	if (magic_ftype != DUK__FLD_VARINT) {
29384 		DUK_ASSERT(magic_ftype >= 0 && magic_ftype < (duk_small_int_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t)));
29385 		nbytes = duk__buffer_nbytes_from_fldtype[magic_ftype];
29386 	} else {
29387 		nbytes = duk_get_int(thr, 2);
29388 		if (nbytes < 1 || nbytes > 6) {
29389 			goto fail_field_length;
29390 		}
29391 	}
29392 	DUK_ASSERT(nbytes >= 1 && nbytes <= 8);
29393 
29394 	/* Now we can check offset validity. */
29395 	if (offset_signed < 0) {
29396 		goto fail_bounds;
29397 	}
29398 
29399 	DUK_DDD(DUK_DDDPRINT("writefield, value=%!T, buffer_length=%ld, offset=%ld, no_assert=%d, "
29400 	                     "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
29401 	                     "endswap=%d",
29402 	                     duk_get_tval(thr, 0), (long) buffer_length, (long) offset, (int) no_assert,
29403 	                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
29404 	                     (int) (magic_signed >> 4), (int) endswap));
29405 
29406 	/* Coerce value to a number before computing check_length, so that
29407 	 * the field type specific coercion below can't have side effects
29408 	 * that would invalidate check_length.
29409 	 */
29410 	duk_to_number(thr, 0);
29411 
29412 	/* Update 'buffer_length' to be the effective, safe limit which
29413 	 * takes into account the underlying buffer.  This value will be
29414 	 * potentially invalidated by any side effect.
29415 	 */
29416 	check_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);
29417 	DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
29418 	                     (long) buffer_length, (long) check_length));
29419 
29420 	if (h_this->buf) {
29421 		buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
29422 	} else {
29423 		/* Neutered.  We could go into the switch-case safely with
29424 		 * buf == NULL because check_length == 0.  To avoid scanbuild
29425 		 * warnings, fail directly instead.
29426 		 */
29427 		DUK_ASSERT(check_length == 0);
29428 		goto fail_neutered;
29429 	}
29430 	DUK_ASSERT(buf != NULL);
29431 
29432 	switch (magic_ftype) {
29433 	case DUK__FLD_8BIT: {
29434 		if (offset + 1U > check_length) {
29435 			goto fail_bounds;
29436 		}
29437 		/* sign doesn't matter when writing */
29438 		buf[offset] = (duk_uint8_t) duk_to_uint32(thr, 0);
29439 		break;
29440 	}
29441 	case DUK__FLD_16BIT: {
29442 		duk_uint16_t tmp;
29443 		if (offset + 2U > check_length) {
29444 			goto fail_bounds;
29445 		}
29446 		tmp = (duk_uint16_t) duk_to_uint32(thr, 0);
29447 		if (endswap) {
29448 			tmp = DUK_BSWAP16(tmp);
29449 		}
29450 		du.us[0] = tmp;
29451 		/* sign doesn't matter when writing */
29452 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 2);
29453 		break;
29454 	}
29455 	case DUK__FLD_32BIT: {
29456 		duk_uint32_t tmp;
29457 		if (offset + 4U > check_length) {
29458 			goto fail_bounds;
29459 		}
29460 		tmp = (duk_uint32_t) duk_to_uint32(thr, 0);
29461 		if (endswap) {
29462 			tmp = DUK_BSWAP32(tmp);
29463 		}
29464 		du.ui[0] = tmp;
29465 		/* sign doesn't matter when writing */
29466 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 4);
29467 		break;
29468 	}
29469 	case DUK__FLD_FLOAT: {
29470 		duk_uint32_t tmp;
29471 		if (offset + 4U > check_length) {
29472 			goto fail_bounds;
29473 		}
29474 		du.f[0] = (duk_float_t) duk_to_number(thr, 0);
29475 		if (endswap) {
29476 			tmp = du.ui[0];
29477 			tmp = DUK_BSWAP32(tmp);
29478 			du.ui[0] = tmp;
29479 		}
29480 		/* sign doesn't matter when writing */
29481 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 4);
29482 		break;
29483 	}
29484 	case DUK__FLD_DOUBLE: {
29485 		if (offset + 8U > check_length) {
29486 			goto fail_bounds;
29487 		}
29488 		du.d = (duk_double_t) duk_to_number(thr, 0);
29489 		if (endswap) {
29490 			DUK_DBLUNION_BSWAP64(&du);
29491 		}
29492 		/* sign doesn't matter when writing */
29493 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 8);
29494 		break;
29495 	}
29496 	case DUK__FLD_VARINT: {
29497 		/* Node.js Buffer variable width integer field.  We don't really
29498 		 * care about speed here, so aim for shortest algorithm.
29499 		 */
29500 		duk_int_t field_bytelen;
29501 		duk_int_t i, i_step, i_end;
29502 #if defined(DUK_USE_64BIT_OPS)
29503 		duk_int64_t tmp;
29504 #else
29505 		duk_double_t tmp;
29506 #endif
29507 		duk_uint8_t *p;
29508 
29509 		field_bytelen = (duk_int_t) nbytes;
29510 		if (offset + (duk_uint_t) field_bytelen > check_length) {
29511 			goto fail_bounds;
29512 		}
29513 
29514 		/* Slow writing of value using either 64-bit arithmetic
29515 		 * or IEEE doubles if 64-bit types not available.  There's
29516 		 * no special sign handling when writing varints.
29517 		 */
29518 
29519 		if (magic_bigendian) {
29520 			/* Write in big endian */
29521 			i = field_bytelen;  /* one i_step added at top of loop */
29522 			i_step = -1;
29523 			i_end = 0;
29524 		} else {
29525 			/* Write in little endian */
29526 			i = -1;  /* one i_step added at top of loop */
29527 			i_step = 1;
29528 			i_end = field_bytelen - 1;
29529 		}
29530 
29531 		/* XXX: The duk_to_number() cast followed by integer coercion
29532 		 * is platform specific so NaN, +/- Infinity, and out-of-bounds
29533 		 * values result in platform specific output now.
29534 		 * See: test-bi-nodejs-buffer-proto-varint-special.js
29535 		 */
29536 
29537 #if defined(DUK_USE_64BIT_OPS)
29538 		tmp = (duk_int64_t) duk_to_number(thr, 0);
29539 		p = (duk_uint8_t *) (buf + offset);
29540 		do {
29541 			i += i_step;
29542 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29543 			p[i] = (duk_uint8_t) (tmp & 0xff);
29544 			tmp = tmp >> 8;  /* unnecessary shift for last byte */
29545 		} while (i != i_end);
29546 #else
29547 		tmp = duk_to_number(thr, 0);
29548 		p = (duk_uint8_t *) (buf + offset);
29549 		do {
29550 			i += i_step;
29551 			tmp = DUK_FLOOR(tmp);
29552 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29553 			p[i] = (duk_uint8_t) (DUK_FMOD(tmp, 256.0));
29554 			tmp = tmp / 256.0;  /* unnecessary div for last byte */
29555 		} while (i != i_end);
29556 #endif
29557 		break;
29558 	}
29559 	default: {  /* should never happen but default here */
29560 		goto fail_bounds;
29561 	}
29562 	}
29563 
29564 	/* Node.js Buffer: return offset + #bytes written (i.e. next
29565 	 * write offset).
29566 	 */
29567 	if (magic_typedarray) {
29568 		/* For TypedArrays 'undefined' return value is specified
29569 		 * by ES2015 (matches V8).
29570 		 */
29571 		return 0;
29572 	}
29573 	duk_push_uint(thr, offset + (duk_uint_t) nbytes);
29574 	return 1;
29575 
29576  fail_neutered:
29577  fail_field_length:
29578  fail_bounds:
29579 	if (no_assert) {
29580 		/* Node.js return value for failed writes is offset + #bytes
29581 		 * that would have been written.
29582 		 */
29583 		/* XXX: for negative input offsets, 'offset' will be a large
29584 		 * positive value so the result here is confusing.
29585 		 */
29586 		if (magic_typedarray) {
29587 			return 0;
29588 		}
29589 		duk_push_uint(thr, offset + (duk_uint_t) nbytes);
29590 		return 1;
29591 	}
29592 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
29593 }
29594 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29595 
29596 /*
29597  *  Accessors for .buffer, .byteLength, .byteOffset
29598  */
29599 
29600 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk__autospawn_arraybuffer(duk_hthread * thr,duk_hbuffer * h_buf)29601 DUK_LOCAL duk_hbufobj *duk__autospawn_arraybuffer(duk_hthread *thr, duk_hbuffer *h_buf) {
29602 	duk_hbufobj *h_res;
29603 
29604 	h_res = duk_push_bufobj_raw(thr,
29605 	                            DUK_HOBJECT_FLAG_EXTENSIBLE |
29606 	                            DUK_HOBJECT_FLAG_BUFOBJ |
29607 	                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
29608 	                            DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
29609 	DUK_ASSERT(h_res != NULL);
29610 	DUK_UNREF(h_res);
29611 
29612 	duk__set_bufobj_buffer(thr, h_res, h_buf);
29613 	DUK_HBUFOBJ_ASSERT_VALID(h_res);
29614 	DUK_ASSERT(h_res->buf_prop == NULL);
29615 	return h_res;
29616 }
29617 
duk_bi_typedarray_buffer_getter(duk_hthread * thr)29618 DUK_INTERNAL duk_ret_t duk_bi_typedarray_buffer_getter(duk_hthread *thr) {
29619 	duk_hbufobj *h_bufobj;
29620 
29621 	h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
29622 	DUK_ASSERT(h_bufobj != NULL);
29623 	if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
29624 		DUK_DD(DUK_DDPRINT("autospawn ArrayBuffer for plain buffer"));
29625 		(void) duk__autospawn_arraybuffer(thr, (duk_hbuffer *) h_bufobj);
29626 		return 1;
29627 	} else {
29628 		if (h_bufobj->buf_prop == NULL &&
29629 		    DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_bufobj) != DUK_HOBJECT_CLASS_ARRAYBUFFER &&
29630 		    h_bufobj->buf != NULL) {
29631 			duk_hbufobj *h_arrbuf;
29632 
29633 			DUK_DD(DUK_DDPRINT("autospawn ArrayBuffer for typed array or DataView"));
29634 			h_arrbuf = duk__autospawn_arraybuffer(thr, h_bufobj->buf);
29635 
29636 			if (h_bufobj->buf_prop == NULL) {
29637 				/* Must recheck buf_prop, in case ArrayBuffer
29638 				 * alloc had a side effect which already filled
29639 				 * it!
29640 				 */
29641 
29642 				/* Set ArrayBuffer's .byteOffset and .byteLength based
29643 				 * on the view so that Arraybuffer[view.byteOffset]
29644 				 * matches view[0].
29645 				 */
29646 				h_arrbuf->offset = 0;
29647 				DUK_ASSERT(h_bufobj->offset + h_bufobj->length >= h_bufobj->offset);  /* Wrap check on creation. */
29648 				h_arrbuf->length = h_bufobj->offset + h_bufobj->length;
29649 				DUK_ASSERT(h_arrbuf->buf_prop == NULL);
29650 
29651 				DUK_ASSERT(h_bufobj->buf_prop == NULL);
29652 				h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
29653 				DUK_HBUFOBJ_INCREF(thr, h_arrbuf);  /* Now reachable and accounted for. */
29654 			}
29655 
29656 			/* Left on stack; pushed for the second time below (OK). */
29657 		}
29658 		if (h_bufobj->buf_prop) {
29659 			duk_push_hobject(thr, h_bufobj->buf_prop);
29660 			return 1;
29661 		}
29662 	}
29663 	return 0;
29664 }
29665 
duk_bi_typedarray_byteoffset_getter(duk_hthread * thr)29666 DUK_INTERNAL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_hthread *thr) {
29667 	duk_hbufobj *h_bufobj;
29668 
29669 	h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
29670 	DUK_ASSERT(h_bufobj != NULL);
29671 	if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
29672 		duk_push_uint(thr, 0);
29673 	} else {
29674 		/* If neutered must return 0; offset is zeroed during
29675 		 * neutering.
29676 		 */
29677 		duk_push_uint(thr, h_bufobj->offset);
29678 	}
29679 	return 1;
29680 }
29681 
duk_bi_typedarray_bytelength_getter(duk_hthread * thr)29682 DUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_hthread *thr) {
29683 	duk_hbufobj *h_bufobj;
29684 
29685 	h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
29686 	DUK_ASSERT(h_bufobj != NULL);
29687 	if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
29688 		duk_hbuffer *h_buf;
29689 
29690 		h_buf = (duk_hbuffer *) h_bufobj;
29691 		DUK_ASSERT(DUK_HBUFFER_GET_SIZE(h_buf) <= DUK_UINT_MAX);  /* Buffer limits. */
29692 		duk_push_uint(thr, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
29693 	} else {
29694 		/* If neutered must return 0; length is zeroed during
29695 		 * neutering.
29696 		 */
29697 		duk_push_uint(thr, h_bufobj->length);
29698 	}
29699 	return 1;
29700 }
29701 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29702 /* No .buffer getter without ArrayBuffer support. */
29703 #if 0
29704 DUK_INTERNAL duk_ret_t duk_bi_typedarray_buffer_getter(duk_hthread *thr) {
29705 	return 0;
29706 }
29707 #endif
29708 
duk_bi_typedarray_byteoffset_getter(duk_hthread * thr)29709 DUK_INTERNAL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_hthread *thr) {
29710 	duk_push_uint(thr, 0);
29711 	return 1;
29712 }
29713 
duk_bi_typedarray_bytelength_getter(duk_hthread * thr)29714 DUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_hthread *thr) {
29715 	duk_hbuffer *h_buf;
29716 
29717 	/* XXX: helper? */
29718 	duk_push_this(thr);
29719 	h_buf = duk_require_hbuffer(thr, -1);
29720 	duk_push_uint(thr, DUK_HBUFFER_GET_SIZE(h_buf));
29721 	return 1;
29722 }
29723 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29724 
29725 /* automatic undefs */
29726 #undef DUK__BUFOBJ_FLAG_PROMOTE
29727 #undef DUK__BUFOBJ_FLAG_THROW
29728 #undef DUK__FLD_16BIT
29729 #undef DUK__FLD_32BIT
29730 #undef DUK__FLD_8BIT
29731 #undef DUK__FLD_BIGENDIAN
29732 #undef DUK__FLD_DOUBLE
29733 #undef DUK__FLD_FLOAT
29734 #undef DUK__FLD_SIGNED
29735 #undef DUK__FLD_TYPEDARRAY
29736 #undef DUK__FLD_VARINT
29737 /*
29738  *  Date built-ins
29739  *
29740  *  Unlike most built-ins, Date has some platform dependencies for getting
29741  *  UTC time, converting between UTC and local time, and parsing and
29742  *  formatting time values.  These are all abstracted behind DUK_USE_xxx
29743  *  config options.  There are built-in platform specific providers for
29744  *  POSIX and Windows, but external providers can also be used.
29745  *
29746  *  See doc/datetime.rst.
29747  *
29748  */
29749 
29750 /* #include duk_internal.h -> already included */
29751 
29752 /* XXX: currently defines unnecessary symbols when DUK_USE_DATE_BUILTIN is disabled. */
29753 
29754 /*
29755  *  Forward declarations
29756  */
29757 
29758 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);
29759 DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval(duk_hthread *thr, duk_small_uint_t flags);
29760 DUK_LOCAL_DECL void duk__twodigit_year_fixup(duk_hthread *thr, duk_idx_t idx_val);
29761 DUK_LOCAL_DECL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk_double_t *dparts, duk_small_uint_t flags);
29762 
29763 /*
29764  *  Other file level defines
29765  */
29766 
29767 /* Debug macro to print all parts and dparts (used manually because of debug level). */
29768 #define  DUK__DPRINT_PARTS_AND_DPARTS(parts,dparts)  do { \
29769 		DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld, dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
29770 		                 (long) (parts)[0], (long) (parts)[1], \
29771 		                 (long) (parts)[2], (long) (parts)[3], \
29772 		                 (long) (parts)[4], (long) (parts)[5], \
29773 		                 (long) (parts)[6], (long) (parts)[7], \
29774 		                 (double) (dparts)[0], (double) (dparts)[1], \
29775 		                 (double) (dparts)[2], (double) (dparts)[3], \
29776 		                 (double) (dparts)[4], (double) (dparts)[5], \
29777 		                 (double) (dparts)[6], (double) (dparts)[7])); \
29778 	} while (0)
29779 #define  DUK__DPRINT_PARTS(parts)  do { \
29780 		DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld", \
29781 		                 (long) (parts)[0], (long) (parts)[1], \
29782 		                 (long) (parts)[2], (long) (parts)[3], \
29783 		                 (long) (parts)[4], (long) (parts)[5], \
29784 		                 (long) (parts)[6], (long) (parts)[7])); \
29785 	} while (0)
29786 #define  DUK__DPRINT_DPARTS(dparts)  do { \
29787 		DUK_D(DUK_DPRINT("dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
29788 		                 (double) (dparts)[0], (double) (dparts)[1], \
29789 		                 (double) (dparts)[2], (double) (dparts)[3], \
29790 		                 (double) (dparts)[4], (double) (dparts)[5], \
29791 		                 (double) (dparts)[6], (double) (dparts)[7])); \
29792 	} while (0)
29793 
29794 /* Equivalent year for DST calculations outside [1970,2038[ range, see
29795  * E5 Section 15.9.1.8.  Equivalent year has the same leap-year-ness and
29796  * starts with the same weekday on Jan 1.
29797  * https://bugzilla.mozilla.org/show_bug.cgi?id=351066
29798  */
29799 #define DUK__YEAR(x) ((duk_uint8_t) ((x) - 1970))
29800 DUK_LOCAL duk_uint8_t duk__date_equivyear[14] = {
29801 #if 1
29802 	/* This is based on V8 EquivalentYear() algorithm (see util/genequivyear.py):
29803 	 * http://code.google.com/p/v8/source/browse/trunk/src/date.h#146
29804 	 */
29805 
29806 	/* non-leap year: sunday, monday, ... */
29807 	DUK__YEAR(2023), DUK__YEAR(2035), DUK__YEAR(2019), DUK__YEAR(2031),
29808 	DUK__YEAR(2015), DUK__YEAR(2027), DUK__YEAR(2011),
29809 
29810 	/* leap year: sunday, monday, ... */
29811 	DUK__YEAR(2012), DUK__YEAR(2024), DUK__YEAR(2008), DUK__YEAR(2020),
29812 	DUK__YEAR(2032), DUK__YEAR(2016), DUK__YEAR(2028)
29813 #endif
29814 
29815 #if 0
29816 	/* This is based on Rhino EquivalentYear() algorithm:
29817 	 * https://github.com/mozilla/rhino/blob/f99cc11d616f0cdda2c42bde72b3484df6182947/src/org/mozilla/javascript/NativeDate.java
29818 	 */
29819 
29820 	/* non-leap year: sunday, monday, ... */
29821 	DUK__YEAR(1978), DUK__YEAR(1973), DUK__YEAR(1985), DUK__YEAR(1986),
29822 	DUK__YEAR(1981), DUK__YEAR(1971), DUK__YEAR(1977),
29823 
29824 	/* leap year: sunday, monday, ... */
29825 	DUK__YEAR(1984), DUK__YEAR(1996), DUK__YEAR(1980), DUK__YEAR(1992),
29826 	DUK__YEAR(1976), DUK__YEAR(1988), DUK__YEAR(1972)
29827 #endif
29828 };
29829 
29830 /*
29831  *  ISO 8601 subset parser.
29832  */
29833 
29834 /* Parser part count. */
29835 #define DUK__NUM_ISO8601_PARSER_PARTS  9
29836 
29837 /* Parser part indices. */
29838 #define DUK__PI_YEAR         0
29839 #define DUK__PI_MONTH        1
29840 #define DUK__PI_DAY          2
29841 #define DUK__PI_HOUR         3
29842 #define DUK__PI_MINUTE       4
29843 #define DUK__PI_SECOND       5
29844 #define DUK__PI_MILLISECOND  6
29845 #define DUK__PI_TZHOUR       7
29846 #define DUK__PI_TZMINUTE     8
29847 
29848 /* Parser part masks. */
29849 #define DUK__PM_YEAR         (1 << DUK__PI_YEAR)
29850 #define DUK__PM_MONTH        (1 << DUK__PI_MONTH)
29851 #define DUK__PM_DAY          (1 << DUK__PI_DAY)
29852 #define DUK__PM_HOUR         (1 << DUK__PI_HOUR)
29853 #define DUK__PM_MINUTE       (1 << DUK__PI_MINUTE)
29854 #define DUK__PM_SECOND       (1 << DUK__PI_SECOND)
29855 #define DUK__PM_MILLISECOND  (1 << DUK__PI_MILLISECOND)
29856 #define DUK__PM_TZHOUR       (1 << DUK__PI_TZHOUR)
29857 #define DUK__PM_TZMINUTE     (1 << DUK__PI_TZMINUTE)
29858 
29859 /* Parser separator indices. */
29860 #define DUK__SI_PLUS         0
29861 #define DUK__SI_MINUS        1
29862 #define DUK__SI_T            2
29863 #define DUK__SI_SPACE        3
29864 #define DUK__SI_COLON        4
29865 #define DUK__SI_PERIOD       5
29866 #define DUK__SI_Z            6
29867 #define DUK__SI_NUL          7
29868 
29869 /* Parser separator masks. */
29870 #define DUK__SM_PLUS         (1 << DUK__SI_PLUS)
29871 #define DUK__SM_MINUS        (1 << DUK__SI_MINUS)
29872 #define DUK__SM_T            (1 << DUK__SI_T)
29873 #define DUK__SM_SPACE        (1 << DUK__SI_SPACE)
29874 #define DUK__SM_COLON        (1 << DUK__SI_COLON)
29875 #define DUK__SM_PERIOD       (1 << DUK__SI_PERIOD)
29876 #define DUK__SM_Z            (1 << DUK__SI_Z)
29877 #define DUK__SM_NUL          (1 << DUK__SI_NUL)
29878 
29879 /* Rule control flags. */
29880 #define DUK__CF_NEG          (1 << 0)  /* continue matching, set neg_tzoffset flag */
29881 #define DUK__CF_ACCEPT       (1 << 1)  /* accept string */
29882 #define DUK__CF_ACCEPT_NUL   (1 << 2)  /* accept string if next char is NUL (otherwise reject) */
29883 
29884 #define DUK__PACK_RULE(partmask,sepmask,nextpart,flags)  \
29885 	((duk_uint32_t) (partmask) + \
29886 	 (((duk_uint32_t) (sepmask)) << 9) + \
29887 	 (((duk_uint32_t) (nextpart)) << 17) + \
29888 	 (((duk_uint32_t) (flags)) << 21))
29889 
29890 #define DUK__UNPACK_RULE(rule,var_nextidx,var_flags)  do { \
29891 		(var_nextidx) = (duk_small_uint_t) (((rule) >> 17) & 0x0f); \
29892 		(var_flags) = (duk_small_uint_t) ((rule) >> 21); \
29893 	} while (0)
29894 
29895 #define DUK__RULE_MASK_PART_SEP  0x1ffffUL
29896 
29897 /* Matching separator index is used in the control table */
29898 DUK_LOCAL const duk_uint8_t duk__parse_iso8601_seps[] = {
29899 	DUK_ASC_PLUS /*0*/, DUK_ASC_MINUS /*1*/, DUK_ASC_UC_T /*2*/, DUK_ASC_SPACE /*3*/,
29900 	DUK_ASC_COLON /*4*/, DUK_ASC_PERIOD /*5*/, DUK_ASC_UC_Z /*6*/, DUK_ASC_NUL /*7*/
29901 };
29902 
29903 /* Rule table: first matching rule is used to determine what to do next. */
29904 DUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[] = {
29905 	DUK__PACK_RULE(DUK__PM_YEAR, DUK__SM_MINUS, DUK__PI_MONTH, 0),
29906 	DUK__PACK_RULE(DUK__PM_MONTH, DUK__SM_MINUS, DUK__PI_DAY, 0),
29907 	DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY, DUK__SM_T | DUK__SM_SPACE, DUK__PI_HOUR, 0),
29908 	DUK__PACK_RULE(DUK__PM_HOUR, DUK__SM_COLON, DUK__PI_MINUTE, 0),
29909 	DUK__PACK_RULE(DUK__PM_MINUTE, DUK__SM_COLON, DUK__PI_SECOND, 0),
29910 	DUK__PACK_RULE(DUK__PM_SECOND, DUK__SM_PERIOD, DUK__PI_MILLISECOND, 0),
29911 	DUK__PACK_RULE(DUK__PM_TZHOUR, DUK__SM_COLON, DUK__PI_TZMINUTE, 0),
29912 	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),
29913 	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),
29914 	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),
29915 	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)
29916 
29917 	/* Note1: the specification doesn't require matching a time form with
29918 	 *        just hours ("HH"), but we accept it here, e.g. "2012-01-02T12Z".
29919 	 *
29920 	 * Note2: the specification doesn't require matching a timezone offset
29921 	 *        with just hours ("HH"), but accept it here, e.g. "2012-01-02T03:04:05+02"
29922 	 */
29923 };
29924 
duk__parse_string_iso8601_subset(duk_hthread * thr,const char * str)29925 DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_hthread *thr, const char *str) {
29926 	duk_int_t parts[DUK__NUM_ISO8601_PARSER_PARTS];
29927 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
29928 	duk_double_t d;
29929 	const duk_uint8_t *p;
29930 	duk_small_uint_t part_idx = 0;
29931 	duk_int_t accum = 0;
29932 	duk_small_uint_t ndigits = 0;
29933 	duk_bool_t neg_year = 0;
29934 	duk_bool_t neg_tzoffset = 0;
29935 	duk_uint_fast8_t ch;
29936 	duk_small_uint_t i;
29937 
29938 	/* During parsing, month and day are one-based; set defaults here. */
29939 	duk_memzero(parts, sizeof(parts));
29940 	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] == 0);  /* don't care value, year is mandatory */
29941 	parts[DUK_DATE_IDX_MONTH] = 1;
29942 	parts[DUK_DATE_IDX_DAY] = 1;
29943 
29944 	/* Special handling for year sign. */
29945 	p = (const duk_uint8_t *) str;
29946 	ch = p[0];
29947 	if (ch == DUK_ASC_PLUS) {
29948 		p++;
29949 	} else if (ch == DUK_ASC_MINUS) {
29950 		neg_year = 1;
29951 		p++;
29952 	}
29953 
29954 	for (;;) {
29955 		ch = *p++;
29956 		DUK_DDD(DUK_DDDPRINT("parsing, part_idx=%ld, char=%ld ('%c')",
29957 		                     (long) part_idx, (long) ch,
29958 		                     (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : DUK_ASC_QUESTION)));
29959 
29960 		if (ch >= DUK_ASC_0 && ch <= DUK_ASC_9) {
29961 			if (ndigits >= 9) {
29962 				DUK_DDD(DUK_DDDPRINT("too many digits -> reject"));
29963 				goto reject;
29964 			}
29965 			if (part_idx == DUK__PI_MILLISECOND && ndigits >= 3) {
29966 				/* ignore millisecond fractions after 3 */
29967 			} else {
29968 				accum = accum * 10 + ((duk_int_t) ch) - ((duk_int_t) DUK_ASC_0) + 0x00;
29969 				ndigits++;
29970 			}
29971 		} else {
29972 			duk_uint_fast32_t match_val;
29973 			duk_small_uint_t sep_idx;
29974 
29975 			if (ndigits <= 0) {
29976 				goto reject;
29977 			}
29978 			if (part_idx == DUK__PI_MILLISECOND) {
29979 				/* complete the millisecond field */
29980 				while (ndigits < 3) {
29981 					accum *= 10;
29982 					ndigits++;
29983 				}
29984 			}
29985 			parts[part_idx] = accum;
29986 			DUK_DDD(DUK_DDDPRINT("wrote part %ld -> value %ld", (long) part_idx, (long) accum));
29987 
29988 			accum = 0;
29989 			ndigits = 0;
29990 
29991 			for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t)); i++) {
29992 				if (duk__parse_iso8601_seps[i] == ch) {
29993 					break;
29994 				}
29995 			}
29996 			if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t))) {
29997 				DUK_DDD(DUK_DDDPRINT("separator character doesn't match -> reject"));
29998 				goto reject;
29999 			}
30000 
30001 			sep_idx = i;
30002 			match_val = (1UL << part_idx) + (1UL << (sep_idx + 9));  /* match against rule part/sep bits */
30003 
30004 			for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t)); i++) {
30005 				duk_uint_fast32_t rule = duk__parse_iso8601_control[i];
30006 				duk_small_uint_t nextpart;
30007 				duk_small_uint_t cflags;
30008 
30009 				DUK_DDD(DUK_DDDPRINT("part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, considering rule=0x%08lx",
30010 				                     (long) part_idx, (long) sep_idx,
30011 				                     (unsigned long) match_val, (unsigned long) rule));
30012 
30013 				if ((rule & match_val) != match_val) {
30014 					continue;
30015 				}
30016 
30017 				DUK__UNPACK_RULE(rule, nextpart, cflags);
30018 
30019 				DUK_DDD(DUK_DDDPRINT("rule match -> part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, "
30020 				                     "rule=0x%08lx -> nextpart=%ld, cflags=0x%02lx",
30021 				                     (long) part_idx, (long) sep_idx,
30022 				                     (unsigned long) match_val, (unsigned long) rule,
30023 				                     (long) nextpart, (unsigned long) cflags));
30024 
30025 				if (cflags & DUK__CF_NEG) {
30026 					neg_tzoffset = 1;
30027 				}
30028 
30029 				if (cflags & DUK__CF_ACCEPT) {
30030 					goto accept;
30031 				}
30032 
30033 				if (cflags & DUK__CF_ACCEPT_NUL) {
30034 					DUK_ASSERT(*(p - 1) != (char) 0);
30035 					if (*p == DUK_ASC_NUL) {
30036 						goto accept;
30037 					}
30038 					goto reject;
30039 				}
30040 
30041 				part_idx = nextpart;
30042 				break;
30043 			}  /* rule match */
30044 
30045 			if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t))) {
30046 				DUK_DDD(DUK_DDDPRINT("no rule matches -> reject"));
30047 				goto reject;
30048 			}
30049 
30050 			if (ch == 0) {
30051 				/* This shouldn't be necessary, but check just in case
30052 				 * to avoid any chance of overruns.
30053 				 */
30054 				DUK_DDD(DUK_DDDPRINT("NUL after rule matching (should not happen) -> reject"));
30055 				goto reject;
30056 			}
30057 		}  /* if-digit-else-ctrl */
30058 	}  /* char loop */
30059 
30060 	/* We should never exit the loop above. */
30061 	DUK_UNREACHABLE();
30062 
30063  reject:
30064 	DUK_DDD(DUK_DDDPRINT("reject"));
30065 	return 0;
30066 
30067  accept:
30068 	DUK_DDD(DUK_DDDPRINT("accept"));
30069 
30070 	/* Apply timezone offset to get the main parts in UTC */
30071 	if (neg_year) {
30072 		parts[DUK__PI_YEAR] = -parts[DUK__PI_YEAR];
30073 	}
30074 	if (neg_tzoffset) {
30075 		parts[DUK__PI_HOUR] += parts[DUK__PI_TZHOUR];
30076 		parts[DUK__PI_MINUTE] += parts[DUK__PI_TZMINUTE];
30077 	} else {
30078 		parts[DUK__PI_HOUR] -= parts[DUK__PI_TZHOUR];
30079 		parts[DUK__PI_MINUTE] -= parts[DUK__PI_TZMINUTE];
30080 	}
30081 	parts[DUK__PI_MONTH] -= 1;  /* zero-based month */
30082 	parts[DUK__PI_DAY] -= 1;  /* zero-based day */
30083 
30084 	/* Use double parts, they tolerate unnormalized time.
30085 	 *
30086 	 * Note: DUK_DATE_IDX_WEEKDAY is initialized with a bogus value (DUK__PI_TZHOUR)
30087 	 * on purpose.  It won't be actually used by duk_bi_date_get_timeval_from_dparts(),
30088 	 * but will make the value initialized just in case, and avoid any
30089 	 * potential for Valgrind issues.
30090 	 */
30091 	for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
30092 		DUK_DDD(DUK_DDDPRINT("part[%ld] = %ld", (long) i, (long) parts[i]));
30093 		dparts[i] = parts[i];
30094 	}
30095 
30096 	d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
30097 	duk_push_number(thr, d);
30098 	return 1;
30099 }
30100 
30101 /*
30102  *  Date/time parsing helper.
30103  *
30104  *  Parse a datetime string into a time value.  We must first try to parse
30105  *  the input according to the standard format in E5.1 Section 15.9.1.15.
30106  *  If that fails, we can try to parse using custom parsing, which can
30107  *  either be platform neutral (custom code) or platform specific (using
30108  *  existing platform API calls).
30109  *
30110  *  Note in particular that we must parse whatever toString(), toUTCString(),
30111  *  and toISOString() can produce; see E5.1 Section 15.9.4.2.
30112  *
30113  *  Returns 1 to allow tail calling.
30114  *
30115  *  There is much room for improvement here with respect to supporting
30116  *  alternative datetime formats.  For instance, V8 parses '2012-01-01' as
30117  *  UTC and '2012/01/01' as local time.
30118  */
30119 
duk__parse_string(duk_hthread * thr,const char * str)30120 DUK_LOCAL duk_ret_t duk__parse_string(duk_hthread *thr, const char *str) {
30121 	/* XXX: there is a small risk here: because the ISO 8601 parser is
30122 	 * very loose, it may end up parsing some datetime values which
30123 	 * would be better parsed with a platform specific parser.
30124 	 */
30125 
30126 	DUK_ASSERT(str != NULL);
30127 	DUK_DDD(DUK_DDDPRINT("parse datetime from string '%s'", (const char *) str));
30128 
30129 	if (duk__parse_string_iso8601_subset(thr, str) != 0) {
30130 		return 1;
30131 	}
30132 
30133 #if defined(DUK_USE_DATE_PARSE_STRING)
30134 	/* Contract, either:
30135 	 * - Push value on stack and return 1
30136 	 * - Don't push anything on stack and return 0
30137 	 */
30138 
30139 	if (DUK_USE_DATE_PARSE_STRING(thr, str) != 0) {
30140 		return 1;
30141 	}
30142 #else
30143 	/* No platform-specific parsing, this is not an error. */
30144 #endif
30145 
30146 	duk_push_nan(thr);
30147 	return 1;
30148 }
30149 
30150 /*
30151  *  Calendar helpers
30152  *
30153  *  Some helpers are used for getters and can operate on normalized values
30154  *  which can be represented with 32-bit signed integers.  Other helpers are
30155  *  needed by setters and operate on un-normalized double values, must watch
30156  *  out for non-finite numbers etc.
30157  */
30158 
30159 DUK_LOCAL duk_uint8_t duk__days_in_month[12] = {
30160 	(duk_uint8_t) 31, (duk_uint8_t) 28, (duk_uint8_t) 31, (duk_uint8_t) 30,
30161 	(duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 31,
30162 	(duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31
30163 };
30164 
30165 /* Maximum iteration count for computing UTC-to-local time offset when
30166  * creating an ECMAScript time value from local parts.
30167  */
30168 #define DUK__LOCAL_TZOFFSET_MAXITER   4
30169 
30170 /* Because 'day since epoch' can be negative and is used to compute weekday
30171  * using a modulo operation, add this multiple of 7 to avoid negative values
30172  * when year is below 1970 epoch.  ECMAScript time values are restricted to
30173  * +/- 100 million days from epoch, so this adder fits nicely into 32 bits.
30174  * Round to a multiple of 7 (= floor(100000000 / 7) * 7) and add margin.
30175  */
30176 #define DUK__WEEKDAY_MOD_ADDER  (20000000 * 7)  /* 0x08583b00 */
30177 
duk_bi_date_is_leap_year(duk_int_t year)30178 DUK_INTERNAL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year) {
30179 	if ((year % 4) != 0) {
30180 		return 0;
30181 	}
30182 	if ((year % 100) != 0) {
30183 		return 1;
30184 	}
30185 	if ((year % 400) != 0) {
30186 		return 0;
30187 	}
30188 	return 1;
30189 }
30190 
duk_bi_date_timeval_in_valid_range(duk_double_t x)30191 DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x) {
30192 	return (x >= -DUK_DATE_MSEC_100M_DAYS && x <= DUK_DATE_MSEC_100M_DAYS);
30193 }
30194 
duk_bi_date_timeval_in_leeway_range(duk_double_t x)30195 DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x) {
30196 	return (x >= -DUK_DATE_MSEC_100M_DAYS_LEEWAY && x <= DUK_DATE_MSEC_100M_DAYS_LEEWAY);
30197 }
30198 
duk_bi_date_year_in_valid_range(duk_double_t x)30199 DUK_INTERNAL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t x) {
30200 	return (x >= DUK_DATE_MIN_ECMA_YEAR && x <= DUK_DATE_MAX_ECMA_YEAR);
30201 }
30202 
duk__timeclip(duk_double_t x)30203 DUK_LOCAL duk_double_t duk__timeclip(duk_double_t x) {
30204 	if (!DUK_ISFINITE(x)) {
30205 		return DUK_DOUBLE_NAN;
30206 	}
30207 
30208 	if (!duk_bi_date_timeval_in_valid_range(x)) {
30209 		return DUK_DOUBLE_NAN;
30210 	}
30211 
30212 	x = duk_js_tointeger_number(x);
30213 
30214 	/* Here we'd have the option to normalize -0 to +0. */
30215 	return x;
30216 }
30217 
30218 /* Integer division which floors also negative values correctly. */
duk__div_floor(duk_int_t a,duk_int_t b)30219 DUK_LOCAL duk_int_t duk__div_floor(duk_int_t a, duk_int_t b) {
30220 	DUK_ASSERT(b > 0);
30221 	if (a >= 0) {
30222 		return a / b;
30223 	} else {
30224 		/* e.g. a = -4, b = 5  -->  -4 - 5 + 1 / 5  -->  -8 / 5  -->  -1
30225 		 *      a = -5, b = 5  -->  -5 - 5 + 1 / 5  -->  -9 / 5  -->  -1
30226 		 *      a = -6, b = 5  -->  -6 - 5 + 1 / 5  -->  -10 / 5  -->  -2
30227 		 */
30228 		return (a - b + 1) / b;
30229 	}
30230 }
30231 
30232 /* Compute day number of the first day of a given year. */
duk__day_from_year(duk_int_t year)30233 DUK_LOCAL duk_int_t duk__day_from_year(duk_int_t year) {
30234 	/* Note: in integer arithmetic, (x / 4) is same as floor(x / 4) for non-negative
30235 	 * values, but is incorrect for negative ones.
30236 	 */
30237 	return 365 * (year - 1970)
30238 	       + duk__div_floor(year - 1969, 4)
30239 	       - duk__div_floor(year - 1901, 100)
30240 	       + duk__div_floor(year - 1601, 400);
30241 }
30242 
30243 /* 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)30244 DUK_LOCAL duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_within_year) {
30245 	duk_int_t year;
30246 	duk_int_t diff_days;
30247 
30248 	/* estimate year upwards (towards positive infinity), then back down;
30249 	 * two iterations should be enough
30250 	 */
30251 
30252 	if (day >= 0) {
30253 		year = 1970 + day / 365;
30254 	} else {
30255 		year = 1970 + day / 366;
30256 	}
30257 
30258 	for (;;) {
30259 		diff_days = duk__day_from_year(year) - day;
30260 		DUK_DDD(DUK_DDDPRINT("year=%ld day=%ld, diff_days=%ld", (long) year, (long) day, (long) diff_days));
30261 		if (diff_days <= 0) {
30262 			DUK_ASSERT(-diff_days < 366);  /* fits into duk_small_int_t */
30263 			*out_day_within_year = -diff_days;
30264 			DUK_DDD(DUK_DDDPRINT("--> year=%ld, day-within-year=%ld",
30265 			                     (long) year, (long) *out_day_within_year));
30266 			DUK_ASSERT(*out_day_within_year >= 0);
30267 			DUK_ASSERT(*out_day_within_year < (duk_bi_date_is_leap_year(year) ? 366 : 365));
30268 			return year;
30269 		}
30270 
30271 		/* Note: this is very tricky; we must never 'overshoot' the
30272 		 * correction downwards.
30273 		 */
30274 		year -= 1 + (diff_days - 1) / 366;  /* conservative */
30275 	}
30276 }
30277 
30278 /* Given a (year, month, day-within-month) triple, compute day number.
30279  * The input triple is un-normalized and may contain non-finite values.
30280  */
duk__make_day(duk_double_t year,duk_double_t month,duk_double_t day)30281 DUK_LOCAL duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_double_t day) {
30282 	duk_int_t day_num;
30283 	duk_bool_t is_leap;
30284 	duk_small_int_t i, n;
30285 
30286 	/* Assume that year, month, day are all coerced to whole numbers.
30287 	 * They may also be NaN or infinity, in which case this function
30288 	 * must return NaN or infinity to ensure time value becomes NaN.
30289 	 * If 'day' is NaN, the final return will end up returning a NaN,
30290 	 * so it doesn't need to be checked here.
30291 	 */
30292 
30293 	if (!DUK_ISFINITE(year) || !DUK_ISFINITE(month)) {
30294 		return DUK_DOUBLE_NAN;
30295 	}
30296 
30297 	year += DUK_FLOOR(month / 12.0);
30298 
30299 	month = DUK_FMOD(month, 12.0);
30300 	if (month < 0.0) {
30301 		/* handle negative values */
30302 		month += 12.0;
30303 	}
30304 
30305 	/* The algorithm in E5.1 Section 15.9.1.12 normalizes month, but
30306 	 * does not normalize the day-of-month (nor check whether or not
30307 	 * it is finite) because it's not necessary for finding the day
30308 	 * number which matches the (year,month) pair.
30309 	 *
30310 	 * We assume that duk__day_from_year() is exact here.
30311 	 *
30312 	 * Without an explicit infinity / NaN check in the beginning,
30313 	 * day_num would be a bogus integer here.
30314 	 *
30315 	 * It's possible for 'year' to be out of integer range here.
30316 	 * If so, we need to return NaN without integer overflow.
30317 	 * This fixes test-bug-setyear-overflow.js.
30318 	 */
30319 
30320 	if (!duk_bi_date_year_in_valid_range(year)) {
30321 		DUK_DD(DUK_DDPRINT("year not in ecmascript valid range, avoid integer overflow: %lf", (double) year));
30322 		return DUK_DOUBLE_NAN;
30323 	}
30324 	day_num = duk__day_from_year((duk_int_t) year);
30325 	is_leap = duk_bi_date_is_leap_year((duk_int_t) year);
30326 
30327 	n = (duk_small_int_t) month;
30328 	for (i = 0; i < n; i++) {
30329 		day_num += duk__days_in_month[i];
30330 		if (i == 1 && is_leap) {
30331 			day_num++;
30332 		}
30333 	}
30334 
30335 	/* If 'day' is NaN, returns NaN. */
30336 	return (duk_double_t) day_num + day;
30337 }
30338 
30339 /* Split time value into parts.  The time value may contain fractions (it may
30340  * come from duk_time_to_components() API call) which are truncated.  Possible
30341  * local time adjustment has already been applied when reading the time value.
30342  */
duk_bi_date_timeval_to_parts(duk_double_t d,duk_int_t * parts,duk_double_t * dparts,duk_small_uint_t flags)30343 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) {
30344 	duk_double_t d1, d2;
30345 	duk_int_t t1, t2;
30346 	duk_int_t day_since_epoch;
30347 	duk_int_t year;  /* does not fit into 16 bits */
30348 	duk_small_int_t day_in_year;
30349 	duk_small_int_t month;
30350 	duk_small_int_t day;
30351 	duk_small_int_t dim;
30352 	duk_int_t jan1_since_epoch;
30353 	duk_small_int_t jan1_weekday;
30354 	duk_int_t equiv_year;
30355 	duk_small_uint_t i;
30356 	duk_bool_t is_leap;
30357 	duk_small_int_t arridx;
30358 
30359 	DUK_ASSERT(DUK_ISFINITE(d));    /* caller checks */
30360 	d = DUK_FLOOR(d);  /* remove fractions if present */
30361 	DUK_ASSERT(DUK_FLOOR(d) == d);
30362 
30363 	/* The timevalue must be in valid ECMAScript range, but since a local
30364 	 * time offset can be applied, we need to allow a +/- 24h leeway to
30365 	 * the value.  In other words, although the UTC time is within the
30366 	 * ECMAScript range, the local part values can be just outside of it.
30367 	 */
30368 	DUK_UNREF(duk_bi_date_timeval_in_leeway_range);
30369 	DUK_ASSERT(duk_bi_date_timeval_in_leeway_range(d));
30370 
30371 	/* These computations are guaranteed to be exact for the valid
30372 	 * E5 time value range, assuming milliseconds without fractions.
30373 	 */
30374 	d1 = (duk_double_t) DUK_FMOD(d, (double) DUK_DATE_MSEC_DAY);
30375 	if (d1 < 0.0) {
30376 		/* deal with negative values */
30377 		d1 += (duk_double_t) DUK_DATE_MSEC_DAY;
30378 	}
30379 	d2 = DUK_FLOOR((double) (d / (duk_double_t) DUK_DATE_MSEC_DAY));
30380 	DUK_ASSERT(d2 * ((duk_double_t) DUK_DATE_MSEC_DAY) + d1 == d);
30381 	/* now expected to fit into a 32-bit integer */
30382 	t1 = (duk_int_t) d1;
30383 	t2 = (duk_int_t) d2;
30384 	day_since_epoch = t2;
30385 	DUK_ASSERT((duk_double_t) t1 == d1);
30386 	DUK_ASSERT((duk_double_t) t2 == d2);
30387 
30388 	/* t1 = milliseconds within day (fits 32 bit)
30389 	 * t2 = day number from epoch (fits 32 bit, may be negative)
30390 	 */
30391 
30392 	parts[DUK_DATE_IDX_MILLISECOND] = t1 % 1000; t1 /= 1000;
30393 	parts[DUK_DATE_IDX_SECOND] = t1 % 60; t1 /= 60;
30394 	parts[DUK_DATE_IDX_MINUTE] = t1 % 60; t1 /= 60;
30395 	parts[DUK_DATE_IDX_HOUR] = t1;
30396 	DUK_ASSERT(parts[DUK_DATE_IDX_MILLISECOND] >= 0 && parts[DUK_DATE_IDX_MILLISECOND] <= 999);
30397 	DUK_ASSERT(parts[DUK_DATE_IDX_SECOND] >= 0 && parts[DUK_DATE_IDX_SECOND] <= 59);
30398 	DUK_ASSERT(parts[DUK_DATE_IDX_MINUTE] >= 0 && parts[DUK_DATE_IDX_MINUTE] <= 59);
30399 	DUK_ASSERT(parts[DUK_DATE_IDX_HOUR] >= 0 && parts[DUK_DATE_IDX_HOUR] <= 23);
30400 
30401 	DUK_DDD(DUK_DDDPRINT("d=%lf, d1=%lf, d2=%lf, t1=%ld, t2=%ld, parts: hour=%ld min=%ld sec=%ld msec=%ld",
30402 	                     (double) d, (double) d1, (double) d2, (long) t1, (long) t2,
30403 	                     (long) parts[DUK_DATE_IDX_HOUR],
30404 	                     (long) parts[DUK_DATE_IDX_MINUTE],
30405 	                     (long) parts[DUK_DATE_IDX_SECOND],
30406 	                     (long) parts[DUK_DATE_IDX_MILLISECOND]));
30407 
30408 	/* This assert depends on the input parts representing time inside
30409 	 * the ECMAScript range.
30410 	 */
30411 	DUK_ASSERT(t2 + DUK__WEEKDAY_MOD_ADDER >= 0);
30412 	parts[DUK_DATE_IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7;  /* E5.1 Section 15.9.1.6 */
30413 	DUK_ASSERT(parts[DUK_DATE_IDX_WEEKDAY] >= 0 && parts[DUK_DATE_IDX_WEEKDAY] <= 6);
30414 
30415 	year = duk__year_from_day(t2, &day_in_year);
30416 	day = day_in_year;
30417 	is_leap = duk_bi_date_is_leap_year(year);
30418 	for (month = 0; month < 12; month++) {
30419 		dim = duk__days_in_month[month];
30420 		if (month == 1 && is_leap) {
30421 			dim++;
30422 		}
30423 		DUK_DDD(DUK_DDDPRINT("month=%ld, dim=%ld, day=%ld",
30424 		                     (long) month, (long) dim, (long) day));
30425 		if (day < dim) {
30426 			break;
30427 		}
30428 		day -= dim;
30429 	}
30430 	DUK_DDD(DUK_DDDPRINT("final month=%ld", (long) month));
30431 	DUK_ASSERT(month >= 0 && month <= 11);
30432 	DUK_ASSERT(day >= 0 && day <= 31);
30433 
30434 	/* Equivalent year mapping, used to avoid DST trouble when platform
30435 	 * may fail to provide reasonable DST answers for dates outside the
30436 	 * ordinary range (e.g. 1970-2038).  An equivalent year has the same
30437 	 * leap-year-ness as the original year and begins on the same weekday
30438 	 * (Jan 1).
30439 	 *
30440 	 * The year 2038 is avoided because there seem to be problems with it
30441 	 * on some platforms.  The year 1970 is also avoided as there were
30442 	 * practical problems with it; an equivalent year is used for it too,
30443 	 * which breaks some DST computations for 1970 right now, see e.g.
30444 	 * test-bi-date-tzoffset-brute-fi.js.
30445 	 */
30446 	if ((flags & DUK_DATE_FLAG_EQUIVYEAR) && (year < 1971 || year > 2037)) {
30447 		DUK_ASSERT(is_leap == 0 || is_leap == 1);
30448 
30449 		jan1_since_epoch = day_since_epoch - day_in_year;  /* day number for Jan 1 since epoch */
30450 		DUK_ASSERT(jan1_since_epoch + DUK__WEEKDAY_MOD_ADDER >= 0);
30451 		jan1_weekday = (jan1_since_epoch + 4 + DUK__WEEKDAY_MOD_ADDER) % 7;  /* E5.1 Section 15.9.1.6 */
30452 		DUK_ASSERT(jan1_weekday >= 0 && jan1_weekday <= 6);
30453 		arridx = jan1_weekday;
30454 		if (is_leap) {
30455 			arridx += 7;
30456 		}
30457 		DUK_ASSERT(arridx >= 0 && arridx < (duk_small_int_t) (sizeof(duk__date_equivyear) / sizeof(duk_uint8_t)));
30458 
30459 		equiv_year = (duk_int_t) duk__date_equivyear[arridx] + 1970;
30460 		year = equiv_year;
30461 		DUK_DDD(DUK_DDDPRINT("equiv year mapping, year=%ld, day_in_year=%ld, day_since_epoch=%ld, "
30462 		                     "jan1_since_epoch=%ld, jan1_weekday=%ld -> equiv year %ld",
30463 		                     (long) year, (long) day_in_year, (long) day_since_epoch,
30464 		                     (long) jan1_since_epoch, (long) jan1_weekday, (long) equiv_year));
30465 	}
30466 
30467 	parts[DUK_DATE_IDX_YEAR] = year;
30468 	parts[DUK_DATE_IDX_MONTH] = month;
30469 	parts[DUK_DATE_IDX_DAY] = day;
30470 
30471 	if (flags & DUK_DATE_FLAG_ONEBASED) {
30472 		parts[DUK_DATE_IDX_MONTH]++;  /* zero-based -> one-based */
30473 		parts[DUK_DATE_IDX_DAY]++;    /* -""- */
30474 	}
30475 
30476 	if (dparts != NULL) {
30477 		for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
30478 			dparts[i] = (duk_double_t) parts[i];
30479 		}
30480 	}
30481 }
30482 
30483 /* Compute time value from (double) parts.  The parts can be either UTC
30484  * or local time; if local, they need to be (conceptually) converted into
30485  * UTC time.  The parts may represent valid or invalid time, and may be
30486  * wildly out of range (but may cancel each other and still come out in
30487  * the valid Date range).
30488  */
duk_bi_date_get_timeval_from_dparts(duk_double_t * dparts,duk_small_uint_t flags)30489 DUK_INTERNAL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags) {
30490 #if defined(DUK_USE_PARANOID_DATE_COMPUTATION)
30491 	/* See comments below on MakeTime why these are volatile. */
30492 	volatile duk_double_t tmp_time;
30493 	volatile duk_double_t tmp_day;
30494 	volatile duk_double_t d;
30495 #else
30496 	duk_double_t tmp_time;
30497 	duk_double_t tmp_day;
30498 	duk_double_t d;
30499 #endif
30500 	duk_small_uint_t i;
30501 	duk_int_t tzoff, tzoffprev1, tzoffprev2;
30502 
30503 	/* Expects 'this' at top of stack on entry. */
30504 
30505 	/* Coerce all finite parts with ToInteger().  ToInteger() must not
30506 	 * be called for NaN/Infinity because it will convert e.g. NaN to
30507 	 * zero.  If ToInteger() has already been called, this has no side
30508 	 * effects and is idempotent.
30509 	 *
30510 	 * Don't read dparts[DUK_DATE_IDX_WEEKDAY]; it will cause Valgrind
30511 	 * issues if the value is uninitialized.
30512 	 */
30513 	for (i = 0; i <= DUK_DATE_IDX_MILLISECOND; i++) {
30514 		/* SCANBUILD: scan-build complains here about assigned value
30515 		 * being garbage or undefined.  This is correct but operating
30516 		 * on undefined values has no ill effect and is ignored by the
30517 		 * caller in the case where this happens.
30518 		 */
30519 		d = dparts[i];
30520 		if (DUK_ISFINITE(d)) {
30521 			dparts[i] = duk_js_tointeger_number(d);
30522 		}
30523 	}
30524 
30525 	/* Use explicit steps in computation to try to ensure that
30526 	 * computation happens with intermediate results coerced to
30527 	 * double values (instead of using something more accurate).
30528 	 * E.g. E5.1 Section 15.9.1.11 requires use of IEEE 754
30529 	 * rules (= ECMAScript '+' and '*' operators).
30530 	 *
30531 	 * Without 'volatile' even this approach fails on some platform
30532 	 * and compiler combinations.  For instance, gcc 4.8.1 on Ubuntu
30533 	 * 64-bit, with -m32 and without -std=c99, test-bi-date-canceling.js
30534 	 * would fail because of some optimizations when computing tmp_time
30535 	 * (MakeTime below).  Adding 'volatile' to tmp_time solved this
30536 	 * particular problem (annoyingly, also adding debug prints or
30537 	 * running the executable under valgrind hides it).
30538 	 */
30539 
30540 	/* MakeTime */
30541 	tmp_time = 0.0;
30542 	tmp_time += dparts[DUK_DATE_IDX_HOUR] * ((duk_double_t) DUK_DATE_MSEC_HOUR);
30543 	tmp_time += dparts[DUK_DATE_IDX_MINUTE] * ((duk_double_t) DUK_DATE_MSEC_MINUTE);
30544 	tmp_time += dparts[DUK_DATE_IDX_SECOND] * ((duk_double_t) DUK_DATE_MSEC_SECOND);
30545 	tmp_time += dparts[DUK_DATE_IDX_MILLISECOND];
30546 
30547 	/* MakeDay */
30548 	tmp_day = duk__make_day(dparts[DUK_DATE_IDX_YEAR], dparts[DUK_DATE_IDX_MONTH], dparts[DUK_DATE_IDX_DAY]);
30549 
30550 	/* MakeDate */
30551 	d = tmp_day * ((duk_double_t) DUK_DATE_MSEC_DAY) + tmp_time;
30552 
30553 	DUK_DDD(DUK_DDDPRINT("time=%lf day=%lf --> timeval=%lf",
30554 	                     (double) tmp_time, (double) tmp_day, (double) d));
30555 
30556 	/* Optional UTC conversion. */
30557 	if (flags & DUK_DATE_FLAG_LOCALTIME) {
30558 		/* DUK_USE_DATE_GET_LOCAL_TZOFFSET() needs to be called with a
30559 		 * time value computed from UTC parts.  At this point we only
30560 		 * have 'd' which is a time value computed from local parts, so
30561 		 * it is off by the UTC-to-local time offset which we don't know
30562 		 * yet.  The current solution for computing the UTC-to-local
30563 		 * time offset is to iterate a few times and detect a fixed
30564 		 * point or a two-cycle loop (or a sanity iteration limit),
30565 		 * see test-bi-date-local-parts.js and test-bi-date-tzoffset-basic-fi.js.
30566 		 *
30567 		 * E5.1 Section 15.9.1.9:
30568 		 * UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA)
30569 		 *
30570 		 * For NaN/inf, DUK_USE_DATE_GET_LOCAL_TZOFFSET() returns 0.
30571 		 */
30572 
30573 #if 0
30574 		/* Old solution: don't iterate, incorrect */
30575 		tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
30576 		DUK_DDD(DUK_DDDPRINT("tzoffset w/o iteration, tzoff=%ld", (long) tzoff));
30577 		d -= tzoff * 1000L;
30578 		DUK_UNREF(tzoffprev1);
30579 		DUK_UNREF(tzoffprev2);
30580 #endif
30581 
30582 		/* Iteration solution */
30583 		tzoff = 0;
30584 		tzoffprev1 = 999999999L;  /* invalid value which never matches */
30585 		for (i = 0; i < DUK__LOCAL_TZOFFSET_MAXITER; i++) {
30586 			tzoffprev2 = tzoffprev1;
30587 			tzoffprev1 = tzoff;
30588 			tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d - tzoff * 1000L);
30589 			DUK_DDD(DUK_DDDPRINT("tzoffset iteration, i=%d, tzoff=%ld, tzoffprev1=%ld tzoffprev2=%ld",
30590 			                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
30591 			if (tzoff == tzoffprev1) {
30592 				DUK_DDD(DUK_DDDPRINT("tzoffset iteration finished, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
30593 				                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
30594 				break;
30595 			} else if (tzoff == tzoffprev2) {
30596 				/* Two value cycle, see e.g. test-bi-date-tzoffset-basic-fi.js.
30597 				 * In these cases, favor a higher tzoffset to get a consistent
30598 				 * result which is independent of iteration count.  Not sure if
30599 				 * this is a generically correct solution.
30600 				 */
30601 				DUK_DDD(DUK_DDDPRINT("tzoffset iteration two-value cycle, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
30602 				                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
30603 				if (tzoffprev1 > tzoff) {
30604 					tzoff = tzoffprev1;
30605 				}
30606 				break;
30607 			}
30608 		}
30609 		DUK_DDD(DUK_DDDPRINT("tzoffset iteration, tzoff=%ld", (long) tzoff));
30610 		d -= tzoff * 1000L;
30611 	}
30612 
30613 	/* TimeClip(), which also handles Infinity -> NaN conversion */
30614 	d = duk__timeclip(d);
30615 
30616 	return d;
30617 }
30618 
30619 /*
30620  *  API oriented helpers
30621  */
30622 
30623 /* Push 'this' binding, check that it is a Date object; then push the
30624  * internal time value.  At the end, stack is: [ ... this timeval ].
30625  * Returns the time value.  Local time adjustment is done if requested.
30626  */
duk__push_this_get_timeval_tzoffset(duk_hthread * thr,duk_small_uint_t flags,duk_int_t * out_tzoffset)30627 DUK_LOCAL duk_double_t duk__push_this_get_timeval_tzoffset(duk_hthread *thr, duk_small_uint_t flags, duk_int_t *out_tzoffset) {
30628 	duk_hobject *h;
30629 	duk_double_t d;
30630 	duk_int_t tzoffset = 0;
30631 
30632 	duk_push_this(thr);
30633 	h = duk_get_hobject(thr, -1);  /* XXX: getter with class check, useful in built-ins */
30634 	if (h == NULL || DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_DATE) {
30635 		DUK_ERROR_TYPE(thr, "expected Date");
30636 		DUK_WO_NORETURN(return 0.0;);
30637 	}
30638 
30639 	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
30640 	d = duk_to_number_m1(thr);
30641 	duk_pop(thr);
30642 
30643 	if (DUK_ISNAN(d)) {
30644 		if (flags & DUK_DATE_FLAG_NAN_TO_ZERO) {
30645 			d = 0.0;
30646 		}
30647 		if (flags & DUK_DATE_FLAG_NAN_TO_RANGE_ERROR) {
30648 			DUK_ERROR_RANGE(thr, "Invalid Date");
30649 			DUK_WO_NORETURN(return 0.0;);
30650 		}
30651 	}
30652 	/* if no NaN handling flag, may still be NaN here, but not Inf */
30653 	DUK_ASSERT(!DUK_ISINF(d));
30654 
30655 	if (flags & DUK_DATE_FLAG_LOCALTIME) {
30656 		/* Note: DST adjustment is determined using UTC time.
30657 		 * If 'd' is NaN, tzoffset will be 0.
30658 		 */
30659 		tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);  /* seconds */
30660 		d += tzoffset * 1000L;
30661 	}
30662 	if (out_tzoffset) {
30663 		*out_tzoffset = tzoffset;
30664 	}
30665 
30666 	/* [ ... this ] */
30667 	return d;
30668 }
30669 
duk__push_this_get_timeval(duk_hthread * thr,duk_small_uint_t flags)30670 DUK_LOCAL duk_double_t duk__push_this_get_timeval(duk_hthread *thr, duk_small_uint_t flags) {
30671 	return duk__push_this_get_timeval_tzoffset(thr, flags, NULL);
30672 }
30673 
30674 /* Set timeval to 'this' from dparts, push the new time value onto the
30675  * value stack and return 1 (caller can then tail call us).  Expects
30676  * the value stack to contain 'this' on the stack top.
30677  */
duk__set_this_timeval_from_dparts(duk_hthread * thr,duk_double_t * dparts,duk_small_uint_t flags)30678 DUK_LOCAL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk_double_t *dparts, duk_small_uint_t flags) {
30679 	duk_double_t d;
30680 
30681 	/* [ ... this ] */
30682 
30683 	d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
30684 	duk_push_number(thr, d);  /* -> [ ... this timeval_new ] */
30685 	duk_dup_top(thr);         /* -> [ ... this timeval_new timeval_new ] */
30686 
30687 	/* Must force write because e.g. .setYear() must work even when
30688 	 * the Date instance is frozen.
30689 	 */
30690 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
30691 
30692 	/* Stack top: new time value, return 1 to allow tail calls. */
30693 	return 1;
30694 }
30695 
30696 /* '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)30697 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) {
30698 	char yearstr[8];   /* "-123456\0" */
30699 	char tzstr[8];     /* "+11:22\0" */
30700 	char sep = (flags & DUK_DATE_FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE;
30701 
30702 	DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
30703 	DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
30704 	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= -999999 && parts[DUK_DATE_IDX_YEAR] <= 999999);
30705 
30706 	/* Note: %06d for positive value, %07d for negative value to include
30707 	 * sign and 6 digits.
30708 	 */
30709 	DUK_SNPRINTF(yearstr,
30710 	             sizeof(yearstr),
30711 	             (parts[DUK_DATE_IDX_YEAR] >= 0 && parts[DUK_DATE_IDX_YEAR] <= 9999) ? "%04ld" :
30712 	                    ((parts[DUK_DATE_IDX_YEAR] >= 0) ? "+%06ld" : "%07ld"),
30713 	             (long) parts[DUK_DATE_IDX_YEAR]);
30714 	yearstr[sizeof(yearstr) - 1] = (char) 0;
30715 
30716 	if (flags & DUK_DATE_FLAG_LOCALTIME) {
30717 		/* tzoffset seconds are dropped; 16 bits suffice for
30718 		 * time offset in minutes
30719 		 */
30720 		const char *fmt;
30721 		duk_small_int_t tmp, arg_hours, arg_minutes;
30722 
30723 		if (tzoffset >= 0) {
30724 			tmp = tzoffset;
30725 			fmt = "+%02d:%02d";
30726 		} else {
30727 			tmp = -tzoffset;
30728 			fmt = "-%02d:%02d";
30729 		}
30730 		tmp = tmp / 60;
30731 		arg_hours = tmp / 60;
30732 		arg_minutes = tmp % 60;
30733 		DUK_ASSERT(arg_hours <= 24);  /* Even less is actually guaranteed for a valid tzoffset. */
30734 		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. */
30735 
30736 		DUK_SNPRINTF(tzstr, sizeof(tzstr), fmt, (int) arg_hours, (int) arg_minutes);
30737 		tzstr[sizeof(tzstr) - 1] = (char) 0;
30738 	} else {
30739 		tzstr[0] = DUK_ASC_UC_Z;
30740 		tzstr[1] = (char) 0;
30741 	}
30742 
30743 	/* Unlike year, the other parts fit into 16 bits so %d format
30744 	 * is portable.
30745 	 */
30746 	if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
30747 		DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d%c%02d:%02d:%02d.%03d%s",
30748 		            (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY], (int) sep,
30749 		            (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
30750 		            (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], (const char *) tzstr);
30751 	} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
30752 		DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d",
30753 		            (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY]);
30754 	} else {
30755 		DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
30756 		DUK_SPRINTF((char *) out_buf, "%02d:%02d:%02d.%03d%s",
30757 		            (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
30758 		            (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND],
30759 		            (const char *) tzstr);
30760 	}
30761 }
30762 
30763 /* Helper for string conversion calls: check 'this' binding, get the
30764  * internal time value, and format date and/or time in a few formats.
30765  * Return value allows tail calls.
30766  */
duk__to_string_helper(duk_hthread * thr,duk_small_uint_t flags)30767 DUK_LOCAL duk_ret_t duk__to_string_helper(duk_hthread *thr, duk_small_uint_t flags) {
30768 	duk_double_t d;
30769 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
30770 	duk_int_t tzoffset;  /* seconds, doesn't fit into 16 bits */
30771 	duk_bool_t rc;
30772 	duk_uint8_t buf[DUK_BI_DATE_ISO8601_BUFSIZE];
30773 
30774 	DUK_UNREF(rc);  /* unreferenced with some options */
30775 
30776 	d = duk__push_this_get_timeval_tzoffset(thr, flags, &tzoffset);
30777 	if (DUK_ISNAN(d)) {
30778 		duk_push_hstring_stridx(thr, DUK_STRIDX_INVALID_DATE);
30779 		return 1;
30780 	}
30781 	DUK_ASSERT(DUK_ISFINITE(d));
30782 
30783 	/* formatters always get one-based month/day-of-month */
30784 	duk_bi_date_timeval_to_parts(d, parts, NULL, DUK_DATE_FLAG_ONEBASED);
30785 	DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
30786 	DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
30787 
30788 	if (flags & DUK_DATE_FLAG_TOSTRING_LOCALE) {
30789 		/* try locale specific formatter; if it refuses to format the
30790 		 * string, fall back to an ISO 8601 formatted value in local
30791 		 * time.
30792 		 */
30793 #if defined(DUK_USE_DATE_FORMAT_STRING)
30794 		/* Contract, either:
30795 		 * - Push string to value stack and return 1
30796 		 * - Don't push anything and return 0
30797 		 */
30798 
30799 		rc = DUK_USE_DATE_FORMAT_STRING(thr, parts, tzoffset, flags);
30800 		if (rc != 0) {
30801 			return 1;
30802 		}
30803 #else
30804 		/* No locale specific formatter; this is OK, we fall back
30805 		 * to ISO 8601.
30806 		 */
30807 #endif
30808 	}
30809 
30810 	/* Different calling convention than above used because the helper
30811 	 * is shared.
30812 	 */
30813 	duk__format_parts_iso8601(parts, tzoffset, flags, buf);
30814 	duk_push_string(thr, (const char *) buf);
30815 	return 1;
30816 }
30817 
30818 /* Helper for component getter calls: check 'this' binding, get the
30819  * internal time value, split it into parts (either as UTC time or
30820  * local time), push a specified component as a return value to the
30821  * value stack and return 1 (caller can then tail call us).
30822  */
duk__get_part_helper(duk_hthread * thr,duk_small_uint_t flags_and_idx)30823 DUK_LOCAL duk_ret_t duk__get_part_helper(duk_hthread *thr, duk_small_uint_t flags_and_idx) {
30824 	duk_double_t d;
30825 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
30826 	duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK_DATE_FLAG_VALUE_SHIFT);  /* unpack args */
30827 
30828 	DUK_ASSERT_DISABLE(idx_part >= 0);  /* unsigned */
30829 	DUK_ASSERT(idx_part < DUK_DATE_IDX_NUM_PARTS);
30830 
30831 	d = duk__push_this_get_timeval(thr, flags_and_idx);
30832 	if (DUK_ISNAN(d)) {
30833 		duk_push_nan(thr);
30834 		return 1;
30835 	}
30836 	DUK_ASSERT(DUK_ISFINITE(d));
30837 
30838 	duk_bi_date_timeval_to_parts(d, parts, NULL, flags_and_idx);  /* no need to mask idx portion */
30839 
30840 	/* Setter APIs detect special year numbers (0...99) and apply a +1900
30841 	 * only in certain cases.  The legacy getYear() getter applies -1900
30842 	 * unconditionally.
30843 	 */
30844 	duk_push_int(thr, (flags_and_idx & DUK_DATE_FLAG_SUB1900) ? parts[idx_part] - 1900 : parts[idx_part]);
30845 	return 1;
30846 }
30847 
30848 /* Helper for component setter calls: check 'this' binding, get the
30849  * internal time value, split it into parts (either as UTC time or
30850  * local time), modify one or more components as specified, recompute
30851  * the time value, set it as the internal value.  Finally, push the
30852  * new time value as a return value to the value stack and return 1
30853  * (caller can then tail call us).
30854  */
duk__set_part_helper(duk_hthread * thr,duk_small_uint_t flags_and_maxnargs)30855 DUK_LOCAL duk_ret_t duk__set_part_helper(duk_hthread *thr, duk_small_uint_t flags_and_maxnargs) {
30856 	duk_double_t d;
30857 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
30858 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
30859 	duk_idx_t nargs;
30860 	duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK_DATE_FLAG_VALUE_SHIFT);  /* unpack args */
30861 	duk_small_uint_t idx_first, idx;
30862 	duk_small_uint_t i;
30863 
30864 	nargs = duk_get_top(thr);
30865 	d = duk__push_this_get_timeval(thr, flags_and_maxnargs);
30866 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
30867 
30868 	if (DUK_ISFINITE(d)) {
30869 		duk_bi_date_timeval_to_parts(d, parts, dparts, flags_and_maxnargs);
30870 	} else {
30871 		/* NaN timevalue: we need to coerce the arguments, but
30872 		 * the resulting internal timestamp needs to remain NaN.
30873 		 * This works but is not pretty: parts and dparts will
30874 		 * be partially uninitialized, but we only write to them.
30875 		 */
30876 	}
30877 
30878 	/*
30879 	 *  Determining which datetime components to overwrite based on
30880 	 *  stack arguments is a bit complicated, but important to factor
30881 	 *  out from setters themselves for compactness.
30882 	 *
30883 	 *  If DUK_DATE_FLAG_TIMESETTER, maxnargs indicates setter type:
30884 	 *
30885 	 *   1 -> millisecond
30886 	 *   2 -> second, [millisecond]
30887 	 *   3 -> minute, [second], [millisecond]
30888 	 *   4 -> hour, [minute], [second], [millisecond]
30889 	 *
30890 	 *  Else:
30891 	 *
30892 	 *   1 -> date
30893 	 *   2 -> month, [date]
30894 	 *   3 -> year, [month], [date]
30895 	 *
30896 	 *  By comparing nargs and maxnargs (and flags) we know which
30897 	 *  components to override.  We rely on part index ordering.
30898 	 */
30899 
30900 	if (flags_and_maxnargs & DUK_DATE_FLAG_TIMESETTER) {
30901 		DUK_ASSERT(maxnargs >= 1 && maxnargs <= 4);
30902 		idx_first = DUK_DATE_IDX_MILLISECOND - (maxnargs - 1);
30903 	} else {
30904 		DUK_ASSERT(maxnargs >= 1 && maxnargs <= 3);
30905 		idx_first = DUK_DATE_IDX_DAY - (maxnargs - 1);
30906 	}
30907 	DUK_ASSERT_DISABLE(idx_first >= 0);  /* unsigned */
30908 	DUK_ASSERT(idx_first < DUK_DATE_IDX_NUM_PARTS);
30909 
30910 	for (i = 0; i < maxnargs; i++) {
30911 		if ((duk_idx_t) i >= nargs) {
30912 			/* no argument given -> leave components untouched */
30913 			break;
30914 		}
30915 		idx = idx_first + i;
30916 		DUK_ASSERT_DISABLE(idx >= 0);  /* unsigned */
30917 		DUK_ASSERT(idx < DUK_DATE_IDX_NUM_PARTS);
30918 
30919 		if (idx == DUK_DATE_IDX_YEAR && (flags_and_maxnargs & DUK_DATE_FLAG_YEAR_FIXUP)) {
30920 			duk__twodigit_year_fixup(thr, (duk_idx_t) i);
30921 		}
30922 
30923 		dparts[idx] = duk_to_number(thr, (duk_idx_t) i);
30924 
30925 		if (idx == DUK_DATE_IDX_DAY) {
30926 			/* Day-of-month is one-based in the API, but zero-based
30927 			 * internally, so fix here.  Note that month is zero-based
30928 			 * both in the API and internally.
30929 			 */
30930 			/* SCANBUILD: complains about use of uninitialized values.
30931 			 * The complaint is correct, but operating in undefined
30932 			 * values here is intentional in some cases and the caller
30933 			 * ignores the results.
30934 			 */
30935 			dparts[idx] -= 1.0;
30936 		}
30937 	}
30938 
30939 	/* Leaves new timevalue on stack top and returns 1, which is correct
30940 	 * for part setters.
30941 	 */
30942 	if (DUK_ISFINITE(d)) {
30943 		return duk__set_this_timeval_from_dparts(thr, dparts, flags_and_maxnargs);
30944 	} else {
30945 		/* Internal timevalue is already NaN, so don't touch it. */
30946 		duk_push_nan(thr);
30947 		return 1;
30948 	}
30949 }
30950 
30951 /* Apply ToNumber() to specified index; if ToInteger(val) in [0,99], add
30952  * 1900 and replace value at idx_val.
30953  */
duk__twodigit_year_fixup(duk_hthread * thr,duk_idx_t idx_val)30954 DUK_LOCAL void duk__twodigit_year_fixup(duk_hthread *thr, duk_idx_t idx_val) {
30955 	duk_double_t d;
30956 
30957 	/* XXX: idx_val would fit into 16 bits, but using duk_small_uint_t
30958 	 * might not generate better code due to casting.
30959 	 */
30960 
30961 	/* E5 Sections 15.9.3.1, B.2.4, B.2.5 */
30962 	duk_to_number(thr, idx_val);
30963 	if (duk_is_nan(thr, idx_val)) {
30964 		return;
30965 	}
30966 	duk_dup(thr, idx_val);
30967 	duk_to_int(thr, -1);
30968 	d = duk_get_number(thr, -1);  /* get as double to handle huge numbers correctly */
30969 	if (d >= 0.0 && d <= 99.0) {
30970 		d += 1900.0;
30971 		duk_push_number(thr, d);
30972 		duk_replace(thr, idx_val);
30973 	}
30974 	duk_pop(thr);
30975 }
30976 
30977 /* Set datetime parts from stack arguments, defaulting any missing values.
30978  * Day-of-week is not set; it is not required when setting the time value.
30979  */
duk__set_parts_from_args(duk_hthread * thr,duk_double_t * dparts,duk_idx_t nargs)30980 DUK_LOCAL void duk__set_parts_from_args(duk_hthread *thr, duk_double_t *dparts, duk_idx_t nargs) {
30981 	duk_double_t d;
30982 	duk_small_uint_t i;
30983 	duk_small_uint_t idx;
30984 
30985 	/* Causes a ToNumber() coercion, but doesn't break coercion order since
30986 	 * year is coerced first anyway.
30987 	 */
30988 	duk__twodigit_year_fixup(thr, 0);
30989 
30990 	/* There are at most 7 args, but we use 8 here so that also
30991 	 * DUK_DATE_IDX_WEEKDAY gets initialized (to zero) to avoid the potential
30992 	 * for any Valgrind gripes later.
30993 	 */
30994 	for (i = 0; i < 8; i++) {
30995 		/* Note: rely on index ordering */
30996 		idx = DUK_DATE_IDX_YEAR + i;
30997 		if ((duk_idx_t) i < nargs) {
30998 			d = duk_to_number(thr, (duk_idx_t) i);
30999 			if (idx == DUK_DATE_IDX_DAY) {
31000 				/* Convert day from one-based to zero-based (internal).  This may
31001 				 * cause the day part to be negative, which is OK.
31002 				 */
31003 				d -= 1.0;
31004 			}
31005 		} else {
31006 			/* All components default to 0 except day-of-month which defaults
31007 			 * to 1.  However, because our internal day-of-month is zero-based,
31008 			 * it also defaults to zero here.
31009 			 */
31010 			d = 0.0;
31011 		}
31012 		dparts[idx] = d;
31013 	}
31014 
31015 	DUK_DDD(DUK_DDDPRINT("parts from args -> %lf %lf %lf %lf %lf %lf %lf %lf",
31016 	                     (double) dparts[0], (double) dparts[1],
31017 	                     (double) dparts[2], (double) dparts[3],
31018 	                     (double) dparts[4], (double) dparts[5],
31019 	                     (double) dparts[6], (double) dparts[7]));
31020 }
31021 
31022 /*
31023  *  Indirect magic value lookup for Date methods.
31024  *
31025  *  Date methods don't put their control flags into the function magic value
31026  *  because they wouldn't fit into a LIGHTFUNC's magic field.  Instead, the
31027  *  magic value is set to an index pointing to the array of control flags
31028  *  below.
31029  *
31030  *  This must be kept in strict sync with genbuiltins.py!
31031  */
31032 
31033 static duk_uint16_t duk__date_magics[] = {
31034 	/* 0: toString */
31035 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,
31036 
31037 	/* 1: toDateString */
31038 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_LOCALTIME,
31039 
31040 	/* 2: toTimeString */
31041 	DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,
31042 
31043 	/* 3: toLocaleString */
31044 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
31045 
31046 	/* 4: toLocaleDateString */
31047 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
31048 
31049 	/* 5: toLocaleTimeString */
31050 	DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
31051 
31052 	/* 6: toUTCString */
31053 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME,
31054 
31055 	/* 7: toISOString */
31056 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_NAN_TO_RANGE_ERROR + DUK_DATE_FLAG_SEP_T,
31057 
31058 	/* 8: getFullYear */
31059 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
31060 
31061 	/* 9: getUTCFullYear */
31062 	0 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
31063 
31064 	/* 10: getMonth */
31065 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),
31066 
31067 	/* 11: getUTCMonth */
31068 	0 + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),
31069 
31070 	/* 12: getDate */
31071 	DUK_DATE_FLAG_ONEBASED + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),
31072 
31073 	/* 13: getUTCDate */
31074 	DUK_DATE_FLAG_ONEBASED + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),
31075 
31076 	/* 14: getDay */
31077 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),
31078 
31079 	/* 15: getUTCDay */
31080 	0 + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),
31081 
31082 	/* 16: getHours */
31083 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),
31084 
31085 	/* 17: getUTCHours */
31086 	0 + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),
31087 
31088 	/* 18: getMinutes */
31089 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),
31090 
31091 	/* 19: getUTCMinutes */
31092 	0 + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),
31093 
31094 	/* 20: getSeconds */
31095 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),
31096 
31097 	/* 21: getUTCSeconds */
31098 	0 + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),
31099 
31100 	/* 22: getMilliseconds */
31101 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),
31102 
31103 	/* 23: getUTCMilliseconds */
31104 	0 + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),
31105 
31106 	/* 24: setMilliseconds */
31107 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
31108 
31109 	/* 25: setUTCMilliseconds */
31110 	DUK_DATE_FLAG_TIMESETTER + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
31111 
31112 	/* 26: setSeconds */
31113 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
31114 
31115 	/* 27: setUTCSeconds */
31116 	DUK_DATE_FLAG_TIMESETTER + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
31117 
31118 	/* 28: setMinutes */
31119 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
31120 
31121 	/* 29: setUTCMinutes */
31122 	DUK_DATE_FLAG_TIMESETTER + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
31123 
31124 	/* 30: setHours */
31125 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (4 << DUK_DATE_FLAG_VALUE_SHIFT),
31126 
31127 	/* 31: setUTCHours */
31128 	DUK_DATE_FLAG_TIMESETTER + (4 << DUK_DATE_FLAG_VALUE_SHIFT),
31129 
31130 	/* 32: setDate */
31131 	DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
31132 
31133 	/* 33: setUTCDate */
31134 	0 + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
31135 
31136 	/* 34: setMonth */
31137 	DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
31138 
31139 	/* 35: setUTCMonth */
31140 	0 + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
31141 
31142 	/* 36: setFullYear */
31143 	DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
31144 
31145 	/* 37: setUTCFullYear */
31146 	DUK_DATE_FLAG_NAN_TO_ZERO + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
31147 
31148 	/* 38: getYear */
31149 	DUK_DATE_FLAG_LOCALTIME + DUK_DATE_FLAG_SUB1900 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
31150 
31151 	/* 39: setYear */
31152 	DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_YEAR_FIXUP + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
31153 };
31154 
duk__date_get_indirect_magic(duk_hthread * thr)31155 DUK_LOCAL duk_small_uint_t duk__date_get_indirect_magic(duk_hthread *thr) {
31156 	duk_small_uint_t magicidx = (duk_small_uint_t) duk_get_current_magic(thr);
31157 	DUK_ASSERT(magicidx < (duk_small_int_t) (sizeof(duk__date_magics) / sizeof(duk_uint16_t)));
31158 	return (duk_small_uint_t) duk__date_magics[magicidx];
31159 }
31160 
31161 #if defined(DUK_USE_DATE_BUILTIN)
31162 /*
31163  *  Constructor calls
31164  */
31165 
duk_bi_date_constructor(duk_hthread * thr)31166 DUK_INTERNAL duk_ret_t duk_bi_date_constructor(duk_hthread *thr) {
31167 	duk_idx_t nargs = duk_get_top(thr);
31168 	duk_bool_t is_cons = duk_is_constructor_call(thr);
31169 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
31170 	duk_double_t d;
31171 
31172 	DUK_DDD(DUK_DDDPRINT("Date constructor, nargs=%ld, is_cons=%ld", (long) nargs, (long) is_cons));
31173 
31174 	(void) duk_push_object_helper(thr,
31175 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
31176 	                              DUK_HOBJECT_FLAG_FASTREFS |
31177 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATE),
31178 	                              DUK_BIDX_DATE_PROTOTYPE);
31179 
31180 	/* Unlike most built-ins, the internal [[PrimitiveValue]] of a Date
31181 	 * is mutable.
31182 	 */
31183 
31184 	if (nargs == 0 || !is_cons) {
31185 		d = duk__timeclip(duk_time_get_ecmascript_time_nofrac(thr));
31186 		duk_push_number(thr, d);
31187 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
31188 		if (!is_cons) {
31189 			/* called as a normal function: return new Date().toString() */
31190 			duk_to_string(thr, -1);
31191 		}
31192 		return 1;
31193 	} else if (nargs == 1) {
31194 		const char *str;
31195 		duk_to_primitive(thr, 0, DUK_HINT_NONE);
31196 		str = duk_get_string_notsymbol(thr, 0);
31197 		if (str) {
31198 			duk__parse_string(thr, str);
31199 			duk_replace(thr, 0);  /* may be NaN */
31200 		}
31201 		d = duk__timeclip(duk_to_number(thr, 0));  /* symbols fail here */
31202 		duk_push_number(thr, d);
31203 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
31204 		return 1;
31205 	}
31206 
31207 	duk__set_parts_from_args(thr, dparts, nargs);
31208 
31209 	/* Parts are in local time, convert when setting. */
31210 
31211 	(void) duk__set_this_timeval_from_dparts(thr, dparts, DUK_DATE_FLAG_LOCALTIME /*flags*/);  /* -> [ ... this timeval ] */
31212 	duk_pop(thr);  /* -> [ ... this ] */
31213 	return 1;
31214 }
31215 
duk_bi_date_constructor_parse(duk_hthread * thr)31216 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_parse(duk_hthread *thr) {
31217 	return duk__parse_string(thr, duk_to_string(thr, 0));
31218 }
31219 
duk_bi_date_constructor_utc(duk_hthread * thr)31220 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_utc(duk_hthread *thr) {
31221 	duk_idx_t nargs = duk_get_top(thr);
31222 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
31223 	duk_double_t d;
31224 
31225 	/* Behavior for nargs < 2 is implementation dependent: currently we'll
31226 	 * set a NaN time value (matching V8 behavior) in this case.
31227 	 */
31228 
31229 	if (nargs < 2) {
31230 		duk_push_nan(thr);
31231 	} else {
31232 		duk__set_parts_from_args(thr, dparts, nargs);
31233 		d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
31234 		duk_push_number(thr, d);
31235 	}
31236 	return 1;
31237 }
31238 
duk_bi_date_constructor_now(duk_hthread * thr)31239 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_now(duk_hthread *thr) {
31240 	duk_double_t d;
31241 
31242 	d = duk_time_get_ecmascript_time_nofrac(thr);
31243 	DUK_ASSERT(duk__timeclip(d) == d);  /* TimeClip() should never be necessary */
31244 	duk_push_number(thr, d);
31245 	return 1;
31246 }
31247 
31248 /*
31249  *  String/JSON conversions
31250  *
31251  *  Human readable conversions are now basically ISO 8601 with a space
31252  *  (instead of 'T') as the date/time separator.  This is a good baseline
31253  *  and is platform independent.
31254  *
31255  *  A shared native helper to provide many conversions.  Magic value contains
31256  *  a set of flags.  The helper provides:
31257  *
31258  *    toString()
31259  *    toDateString()
31260  *    toTimeString()
31261  *    toLocaleString()
31262  *    toLocaleDateString()
31263  *    toLocaleTimeString()
31264  *    toUTCString()
31265  *    toISOString()
31266  *
31267  *  Notes:
31268  *
31269  *    - Date.prototype.toGMTString() and Date.prototype.toUTCString() are
31270  *      required to be the same ECMAScript function object (!), so it is
31271  *      omitted from here.
31272  *
31273  *    - Date.prototype.toUTCString(): E5.1 specification does not require a
31274  *      specific format, but result should be human readable.  The
31275  *      specification suggests using ISO 8601 format with a space (instead
31276  *      of 'T') separator if a more human readable format is not available.
31277  *
31278  *    - Date.prototype.toISOString(): unlike other conversion functions,
31279  *      toISOString() requires a RangeError for invalid date values.
31280  */
31281 
duk_bi_date_prototype_tostring_shared(duk_hthread * thr)31282 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_hthread *thr) {
31283 	duk_small_uint_t flags = duk__date_get_indirect_magic(thr);
31284 	return duk__to_string_helper(thr, flags);
31285 }
31286 
duk_bi_date_prototype_value_of(duk_hthread * thr)31287 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_value_of(duk_hthread *thr) {
31288 	/* This native function is also used for Date.prototype.getTime()
31289 	 * as their behavior is identical.
31290 	 */
31291 
31292 	duk_double_t d = duk__push_this_get_timeval(thr, 0 /*flags*/);  /* -> [ this ] */
31293 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
31294 	duk_push_number(thr, d);
31295 	return 1;
31296 }
31297 
duk_bi_date_prototype_to_json(duk_hthread * thr)31298 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_to_json(duk_hthread *thr) {
31299 	/* Note: toJSON() is a generic function which works even if 'this'
31300 	 * is not a Date.  The sole argument is ignored.
31301 	 */
31302 
31303 	duk_push_this(thr);
31304 	duk_to_object(thr, -1);
31305 
31306 	duk_dup_top(thr);
31307 	duk_to_primitive(thr, -1, DUK_HINT_NUMBER);
31308 	if (duk_is_number(thr, -1)) {
31309 		duk_double_t d = duk_get_number(thr, -1);
31310 		if (!DUK_ISFINITE(d)) {
31311 			duk_push_null(thr);
31312 			return 1;
31313 		}
31314 	}
31315 	duk_pop(thr);
31316 
31317 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_ISO_STRING);
31318 	duk_dup_m2(thr);  /* -> [ O toIsoString O ] */
31319 	duk_call_method(thr, 0);
31320 	return 1;
31321 }
31322 
31323 /*
31324  *  Getters.
31325  *
31326  *  Implementing getters is quite easy.  The internal time value is either
31327  *  NaN, or represents milliseconds (without fractions) from Jan 1, 1970.
31328  *  The internal time value can be converted to integer parts, and each
31329  *  part will be normalized and will fit into a 32-bit signed integer.
31330  *
31331  *  A shared native helper to provide all getters.  Magic value contains
31332  *  a set of flags and also packs the date component index argument.  The
31333  *  helper provides:
31334  *
31335  *    getFullYear()
31336  *    getUTCFullYear()
31337  *    getMonth()
31338  *    getUTCMonth()
31339  *    getDate()
31340  *    getUTCDate()
31341  *    getDay()
31342  *    getUTCDay()
31343  *    getHours()
31344  *    getUTCHours()
31345  *    getMinutes()
31346  *    getUTCMinutes()
31347  *    getSeconds()
31348  *    getUTCSeconds()
31349  *    getMilliseconds()
31350  *    getUTCMilliseconds()
31351  *    getYear()
31352  *
31353  *  Notes:
31354  *
31355  *    - Date.prototype.getDate(): 'date' means day-of-month, and is
31356  *      zero-based in internal calculations but public API expects it to
31357  *      be one-based.
31358  *
31359  *    - Date.prototype.getTime() and Date.prototype.valueOf() have identical
31360  *      behavior.  They have separate function objects, but share the same C
31361  *      function (duk_bi_date_prototype_value_of).
31362  */
31363 
duk_bi_date_prototype_get_shared(duk_hthread * thr)31364 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_shared(duk_hthread *thr) {
31365 	duk_small_uint_t flags_and_idx = duk__date_get_indirect_magic(thr);
31366 	return duk__get_part_helper(thr, flags_and_idx);
31367 }
31368 
duk_bi_date_prototype_get_timezone_offset(duk_hthread * thr)31369 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_hthread *thr) {
31370 	/*
31371 	 *  Return (t - LocalTime(t)) in minutes:
31372 	 *
31373 	 *    t - LocalTime(t) = t - (t + LocalTZA + DaylightSavingTA(t))
31374 	 *                     = -(LocalTZA + DaylightSavingTA(t))
31375 	 *
31376 	 *  where DaylightSavingTA() is checked for time 't'.
31377 	 *
31378 	 *  Note that the sign of the result is opposite to common usage,
31379 	 *  e.g. for EE(S)T which normally is +2h or +3h from UTC, this
31380 	 *  function returns -120 or -180.
31381 	 *
31382 	 */
31383 
31384 	duk_double_t d;
31385 	duk_int_t tzoffset;
31386 
31387 	/* Note: DST adjustment is determined using UTC time. */
31388 	d = duk__push_this_get_timeval(thr, 0 /*flags*/);
31389 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
31390 	if (DUK_ISNAN(d)) {
31391 		duk_push_nan(thr);
31392 	} else {
31393 		DUK_ASSERT(DUK_ISFINITE(d));
31394 		tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
31395 		duk_push_int(thr, -tzoffset / 60);
31396 	}
31397 	return 1;
31398 }
31399 
31400 /*
31401  *  Setters.
31402  *
31403  *  Setters are a bit more complicated than getters.  Component setters
31404  *  break down the current time value into its (normalized) component
31405  *  parts, replace one or more components with -unnormalized- new values,
31406  *  and the components are then converted back into a time value.  As an
31407  *  example of using unnormalized values:
31408  *
31409  *    var d = new Date(1234567890);
31410  *
31411  *  is equivalent to:
31412  *
31413  *    var d = new Date(0);
31414  *    d.setUTCMilliseconds(1234567890);
31415  *
31416  *  A shared native helper to provide almost all setters.  Magic value
31417  *  contains a set of flags and also packs the "maxnargs" argument.  The
31418  *  helper provides:
31419  *
31420  *    setMilliseconds()
31421  *    setUTCMilliseconds()
31422  *    setSeconds()
31423  *    setUTCSeconds()
31424  *    setMinutes()
31425  *    setUTCMinutes()
31426  *    setHours()
31427  *    setUTCHours()
31428  *    setDate()
31429  *    setUTCDate()
31430  *    setMonth()
31431  *    setUTCMonth()
31432  *    setFullYear()
31433  *    setUTCFullYear()
31434  *    setYear()
31435  *
31436  *  Notes:
31437  *
31438  *    - Date.prototype.setYear() (Section B addition): special year check
31439  *      is omitted.  NaN / Infinity will just flow through and ultimately
31440  *      result in a NaN internal time value.
31441  *
31442  *    - Date.prototype.setYear() does not have optional arguments for
31443  *      setting month and day-in-month (like setFullYear()), but we indicate
31444  *      'maxnargs' to be 3 to get the year written to the correct component
31445  *      index in duk__set_part_helper().  The function has nargs == 1, so only
31446  *      the year will be set regardless of actual argument count.
31447  */
31448 
duk_bi_date_prototype_set_shared(duk_hthread * thr)31449 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_shared(duk_hthread *thr) {
31450 	duk_small_uint_t flags_and_maxnargs = duk__date_get_indirect_magic(thr);
31451 	return duk__set_part_helper(thr, flags_and_maxnargs);
31452 }
31453 
duk_bi_date_prototype_set_time(duk_hthread * thr)31454 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_time(duk_hthread *thr) {
31455 	duk_double_t d;
31456 
31457 	(void) duk__push_this_get_timeval(thr, 0 /*flags*/); /* -> [ timeval this ] */
31458 	d = duk__timeclip(duk_to_number(thr, 0));
31459 	duk_push_number(thr, d);
31460 	duk_dup_top(thr);
31461 	/* Must force write because .setTime() must work even when
31462 	 * the Date instance is frozen.
31463 	 */
31464 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
31465 	/* -> [ timeval this timeval ] */
31466 
31467 	return 1;
31468 }
31469 
31470 /*
31471  *  Misc.
31472  */
31473 
31474 #if defined(DUK_USE_SYMBOL_BUILTIN)
duk_bi_date_prototype_toprimitive(duk_hthread * thr)31475 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_toprimitive(duk_hthread *thr) {
31476 	duk_size_t hintlen;
31477 	const char *hintstr;
31478 	duk_int_t hint;
31479 
31480 	/* Invokes OrdinaryToPrimitive() with suitable hint.  Note that the
31481 	 * method is generic, and works on non-Date arguments too.
31482 	 *
31483 	 * https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype-@@toprimitive
31484 	 */
31485 
31486 	duk_push_this(thr);
31487 	duk_require_object(thr, -1);
31488 	DUK_ASSERT_TOP(thr, 2);
31489 
31490 	hintstr = duk_require_lstring(thr, 0, &hintlen);
31491 	if ((hintlen == 6 && DUK_STRCMP(hintstr, "string") == 0) ||
31492 	    (hintlen == 7 && DUK_STRCMP(hintstr, "default") == 0)) {
31493 		hint = DUK_HINT_STRING;
31494 	} else if (hintlen == 6 && DUK_STRCMP(hintstr, "number") == 0) {
31495 		hint = DUK_HINT_NUMBER;
31496 	} else {
31497 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
31498 	}
31499 
31500 	duk_to_primitive_ordinary(thr, -1, hint);
31501 	return 1;
31502 }
31503 #endif  /* DUK_USE_SYMBOL_BUILTIN */
31504 
31505 #endif  /* DUK_USE_DATE_BUILTIN */
31506 
31507 /* automatic undefs */
31508 #undef DUK__CF_ACCEPT
31509 #undef DUK__CF_ACCEPT_NUL
31510 #undef DUK__CF_NEG
31511 #undef DUK__DPRINT_DPARTS
31512 #undef DUK__DPRINT_PARTS
31513 #undef DUK__DPRINT_PARTS_AND_DPARTS
31514 #undef DUK__LOCAL_TZOFFSET_MAXITER
31515 #undef DUK__NUM_ISO8601_PARSER_PARTS
31516 #undef DUK__PACK_RULE
31517 #undef DUK__PI_DAY
31518 #undef DUK__PI_HOUR
31519 #undef DUK__PI_MILLISECOND
31520 #undef DUK__PI_MINUTE
31521 #undef DUK__PI_MONTH
31522 #undef DUK__PI_SECOND
31523 #undef DUK__PI_TZHOUR
31524 #undef DUK__PI_TZMINUTE
31525 #undef DUK__PI_YEAR
31526 #undef DUK__PM_DAY
31527 #undef DUK__PM_HOUR
31528 #undef DUK__PM_MILLISECOND
31529 #undef DUK__PM_MINUTE
31530 #undef DUK__PM_MONTH
31531 #undef DUK__PM_SECOND
31532 #undef DUK__PM_TZHOUR
31533 #undef DUK__PM_TZMINUTE
31534 #undef DUK__PM_YEAR
31535 #undef DUK__RULE_MASK_PART_SEP
31536 #undef DUK__SI_COLON
31537 #undef DUK__SI_MINUS
31538 #undef DUK__SI_NUL
31539 #undef DUK__SI_PERIOD
31540 #undef DUK__SI_PLUS
31541 #undef DUK__SI_SPACE
31542 #undef DUK__SI_T
31543 #undef DUK__SI_Z
31544 #undef DUK__SM_COLON
31545 #undef DUK__SM_MINUS
31546 #undef DUK__SM_NUL
31547 #undef DUK__SM_PERIOD
31548 #undef DUK__SM_PLUS
31549 #undef DUK__SM_SPACE
31550 #undef DUK__SM_T
31551 #undef DUK__SM_Z
31552 #undef DUK__UNPACK_RULE
31553 #undef DUK__WEEKDAY_MOD_ADDER
31554 #undef DUK__YEAR
31555 /*
31556  *  Unix-like Date providers
31557  *
31558  *  Generally useful Unix / POSIX / ANSI Date providers.
31559  */
31560 
31561 /* #include duk_internal.h -> already included */
31562 
31563 /* The necessary #includes are in place in duk_config.h. */
31564 
31565 /* Buffer sizes for some UNIX calls.  Larger than strictly necessary
31566  * to avoid Valgrind errors.
31567  */
31568 #define DUK__STRPTIME_BUF_SIZE  64
31569 #define DUK__STRFTIME_BUF_SIZE  64
31570 
31571 #if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
31572 /* Get current ECMAScript time (= UNIX/Posix time, but in milliseconds). */
duk_bi_date_get_now_gettimeofday(void)31573 DUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(void) {
31574 	struct timeval tv;
31575 	duk_double_t d;
31576 
31577 	if (gettimeofday(&tv, NULL) != 0) {
31578 		DUK_D(DUK_DPRINT("gettimeofday() failed"));
31579 		return 0.0;
31580 	}
31581 
31582 	/* As of Duktape 2.2.0 allow fractions. */
31583 	d = ((duk_double_t) tv.tv_sec) * 1000.0 +
31584 	    ((duk_double_t) tv.tv_usec) / 1000.0;
31585 
31586 	return d;
31587 }
31588 #endif  /* DUK_USE_DATE_NOW_GETTIMEOFDAY */
31589 
31590 #if defined(DUK_USE_DATE_NOW_TIME)
31591 /* Not a very good provider: only full seconds are available. */
duk_bi_date_get_now_time(void)31592 DUK_INTERNAL duk_double_t duk_bi_date_get_now_time(void) {
31593 	time_t t;
31594 
31595 	t = time(NULL);
31596 	if (t == (time_t) -1) {
31597 		DUK_D(DUK_DPRINT("time() failed"));
31598 		return 0.0;
31599 	}
31600 	return ((duk_double_t) t) * 1000.0;
31601 }
31602 #endif  /* DUK_USE_DATE_NOW_TIME */
31603 
31604 #if defined(DUK_USE_DATE_TZO_GMTIME) || defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S)
31605 /* Get local time offset (in seconds) for a certain (UTC) instant 'd'. */
duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d)31606 DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) {
31607 	time_t t, t1, t2;
31608 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
31609 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
31610 	struct tm tms[2];
31611 #if defined(DUK_USE_DATE_TZO_GMTIME)
31612 	struct tm *tm_ptr;
31613 #endif
31614 
31615 	/* For NaN/inf, the return value doesn't matter. */
31616 	if (!DUK_ISFINITE(d)) {
31617 		return 0;
31618 	}
31619 
31620 	/* If not within ECMAScript range, some integer time calculations
31621 	 * won't work correctly (and some asserts will fail), so bail out
31622 	 * if so.  This fixes test-bug-date-insane-setyear.js.  There is
31623 	 * a +/- 24h leeway in this range check to avoid a test262 corner
31624 	 * case documented in test-bug-date-timeval-edges.js.
31625 	 */
31626 	if (!duk_bi_date_timeval_in_leeway_range(d)) {
31627 		DUK_DD(DUK_DDPRINT("timeval not within valid range, skip tzoffset computation to avoid integer overflows"));
31628 		return 0;
31629 	}
31630 
31631 	/*
31632 	 *  This is a bit tricky to implement portably.  The result depends
31633 	 *  on the timestamp (specifically, DST depends on the timestamp).
31634 	 *  If e.g. UNIX APIs are used, they'll have portability issues with
31635 	 *  very small and very large years.
31636 	 *
31637 	 *  Current approach:
31638 	 *
31639 	 *  - Stay within portable UNIX limits by using equivalent year mapping.
31640 	 *    Avoid year 1970 and 2038 as some conversions start to fail, at
31641 	 *    least on some platforms.  Avoiding 1970 means that there are
31642 	 *    currently DST discrepancies for 1970.
31643 	 *
31644 	 *  - Create a UTC and local time breakdowns from 't'.  Then create
31645 	 *    a time_t using gmtime() and localtime() and compute the time
31646 	 *    difference between the two.
31647 	 *
31648 	 *  Equivalent year mapping (E5 Section 15.9.1.8):
31649 	 *
31650 	 *    If the host environment provides functionality for determining
31651 	 *    daylight saving time, the implementation of ECMAScript is free
31652 	 *    to map the year in question to an equivalent year (same
31653 	 *    leap-year-ness and same starting week day for the year) for which
31654 	 *    the host environment provides daylight saving time information.
31655 	 *    The only restriction is that all equivalent years should produce
31656 	 *    the same result.
31657 	 *
31658 	 *  This approach is quite reasonable but not entirely correct, e.g.
31659 	 *  the specification also states (E5 Section 15.9.1.8):
31660 	 *
31661 	 *    The implementation of ECMAScript should not try to determine
31662 	 *    whether the exact time was subject to daylight saving time, but
31663 	 *    just whether daylight saving time would have been in effect if
31664 	 *    the _current daylight saving time algorithm_ had been used at the
31665 	 *    time.  This avoids complications such as taking into account the
31666 	 *    years that the locale observed daylight saving time year round.
31667 	 *
31668 	 *  Since we rely on the platform APIs for conversions between local
31669 	 *  time and UTC, we can't guarantee the above.  Rather, if the platform
31670 	 *  has historical DST rules they will be applied.  This seems to be the
31671 	 *  general preferred direction in ECMAScript standardization (or at least
31672 	 *  implementations) anyway, and even the equivalent year mapping should
31673 	 *  be disabled if the platform is known to handle DST properly for the
31674 	 *  full ECMAScript range.
31675 	 *
31676 	 *  The following has useful discussion and links:
31677 	 *
31678 	 *    https://bugzilla.mozilla.org/show_bug.cgi?id=351066
31679 	 */
31680 
31681 	duk_bi_date_timeval_to_parts(d, parts, dparts, DUK_DATE_FLAG_EQUIVYEAR /*flags*/);
31682 	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= 1970 && parts[DUK_DATE_IDX_YEAR] <= 2038);
31683 
31684 	d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
31685 	DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0);  /* unsigned 31-bit range */
31686 	t = (time_t) (d / 1000.0);
31687 	DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t));
31688 
31689 	duk_memzero((void *) tms, sizeof(struct tm) * 2);
31690 
31691 #if defined(DUK_USE_DATE_TZO_GMTIME_R)
31692 	(void) gmtime_r(&t, &tms[0]);
31693 	(void) localtime_r(&t, &tms[1]);
31694 #elif defined(DUK_USE_DATE_TZO_GMTIME_S)
31695 	(void) gmtime_s(&t, &tms[0]);
31696 	(void) localtime_s(&t, &tms[1]);
31697 #elif defined(DUK_USE_DATE_TZO_GMTIME)
31698 	tm_ptr = gmtime(&t);
31699 	duk_memcpy((void *) &tms[0], tm_ptr, sizeof(struct tm));
31700 	tm_ptr = localtime(&t);
31701 	duk_memcpy((void *) &tms[1], tm_ptr, sizeof(struct tm));
31702 #else
31703 #error internal error
31704 #endif
31705 	DUK_DDD(DUK_DDDPRINT("gmtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
31706 	                     "wday:%ld,yday:%ld,isdst:%ld}",
31707 	                     (long) tms[0].tm_sec, (long) tms[0].tm_min, (long) tms[0].tm_hour,
31708 	                     (long) tms[0].tm_mday, (long) tms[0].tm_mon, (long) tms[0].tm_year,
31709 	                     (long) tms[0].tm_wday, (long) tms[0].tm_yday, (long) tms[0].tm_isdst));
31710 	DUK_DDD(DUK_DDDPRINT("localtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
31711 	                     "wday:%ld,yday:%ld,isdst:%ld}",
31712 	                     (long) tms[1].tm_sec, (long) tms[1].tm_min, (long) tms[1].tm_hour,
31713 	                     (long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year,
31714 	                     (long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst));
31715 
31716 	/* tm_isdst is both an input and an output to mktime(), use 0 to
31717 	 * avoid DST handling in mktime():
31718 	 * - https://github.com/svaarala/duktape/issues/406
31719 	 * - http://stackoverflow.com/questions/8558919/mktime-and-tm-isdst
31720 	 */
31721 	tms[0].tm_isdst = 0;
31722 	tms[1].tm_isdst = 0;
31723 	t1 = mktime(&tms[0]);  /* UTC */
31724 	t2 = mktime(&tms[1]);  /* local */
31725 	if (t1 == (time_t) -1 || t2 == (time_t) -1) {
31726 		/* This check used to be for (t < 0) but on some platforms
31727 		 * time_t is unsigned and apparently the proper way to detect
31728 		 * an mktime() error return is the cast above.  See e.g.:
31729 		 * http://pubs.opengroup.org/onlinepubs/009695299/functions/mktime.html
31730 		 */
31731 		goto mktime_error;
31732 	}
31733 	DUK_DDD(DUK_DDDPRINT("t1=%ld (utc), t2=%ld (local)", (long) t1, (long) t2));
31734 
31735 	/* Compute final offset in seconds, positive if local time ahead of
31736 	 * UTC (returned value is UTC-to-local offset).
31737 	 *
31738 	 * difftime() returns a double, so coercion to int generates quite
31739 	 * a lot of code.  Direct subtraction is not portable, however.
31740 	 * XXX: allow direct subtraction on known platforms.
31741 	 */
31742 #if 0
31743 	return (duk_int_t) (t2 - t1);
31744 #endif
31745 	return (duk_int_t) difftime(t2, t1);
31746 
31747  mktime_error:
31748 	/* XXX: return something more useful, so that caller can throw? */
31749 	DUK_D(DUK_DPRINT("mktime() failed, d=%lf", (double) d));
31750 	return 0;
31751 }
31752 #endif  /* DUK_USE_DATE_TZO_GMTIME */
31753 
31754 #if defined(DUK_USE_DATE_PRS_STRPTIME)
duk_bi_date_parse_string_strptime(duk_hthread * thr,const char * str)31755 DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, const char *str) {
31756 	struct tm tm;
31757 	time_t t;
31758 	char buf[DUK__STRPTIME_BUF_SIZE];
31759 
31760 	/* Copy to buffer with slack to avoid Valgrind gripes from strptime. */
31761 	DUK_ASSERT(str != NULL);
31762 	duk_memzero(buf, sizeof(buf));  /* valgrind whine without this */
31763 	DUK_SNPRINTF(buf, sizeof(buf), "%s", (const char *) str);
31764 	buf[sizeof(buf) - 1] = (char) 0;
31765 
31766 	DUK_DDD(DUK_DDDPRINT("parsing: '%s'", (const char *) buf));
31767 
31768 	duk_memzero(&tm, sizeof(tm));
31769 	if (strptime((const char *) buf, "%c", &tm) != NULL) {
31770 		DUK_DDD(DUK_DDDPRINT("before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
31771 		                     "wday:%ld,yday:%ld,isdst:%ld}",
31772 		                     (long) tm.tm_sec, (long) tm.tm_min, (long) tm.tm_hour,
31773 		                     (long) tm.tm_mday, (long) tm.tm_mon, (long) tm.tm_year,
31774 		                     (long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst));
31775 		tm.tm_isdst = -1;  /* negative: dst info not available */
31776 
31777 		t = mktime(&tm);
31778 		DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
31779 		if (t >= 0) {
31780 			duk_push_number(thr, ((duk_double_t) t) * 1000.0);
31781 			return 1;
31782 		}
31783 	}
31784 
31785 	return 0;
31786 }
31787 #endif  /* DUK_USE_DATE_PRS_STRPTIME */
31788 
31789 #if defined(DUK_USE_DATE_PRS_GETDATE)
duk_bi_date_parse_string_getdate(duk_hthread * thr,const char * str)31790 DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const char *str) {
31791 	struct tm tm;
31792 	duk_small_int_t rc;
31793 	time_t t;
31794 
31795 	/* For this to work, DATEMSK must be set, so this is not very
31796 	 * convenient for an embeddable interpreter.
31797 	 */
31798 
31799 	duk_memzero(&tm, sizeof(struct tm));
31800 	rc = (duk_small_int_t) getdate_r(str, &tm);
31801 	DUK_DDD(DUK_DDDPRINT("getdate_r() -> %ld", (long) rc));
31802 
31803 	if (rc == 0) {
31804 		t = mktime(&tm);
31805 		DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
31806 		if (t >= 0) {
31807 			duk_push_number(thr, (duk_double_t) t);
31808 			return 1;
31809 		}
31810 	}
31811 
31812 	return 0;
31813 }
31814 #endif  /* DUK_USE_DATE_PRS_GETDATE */
31815 
31816 #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)31817 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) {
31818 	char buf[DUK__STRFTIME_BUF_SIZE];
31819 	struct tm tm;
31820 	const char *fmt;
31821 
31822 	DUK_UNREF(tzoffset);
31823 
31824 	/* If the platform doesn't support the entire ECMAScript range, we need
31825 	 * to return 0 so that the caller can fall back to the default formatter.
31826 	 *
31827 	 * For now, assume that if time_t is 8 bytes or more, the whole ECMAScript
31828 	 * range is supported.  For smaller time_t values (4 bytes in practice),
31829 	 * assumes that the signed 32-bit range is supported.
31830 	 *
31831 	 * XXX: detect this more correctly per platform.  The size of time_t is
31832 	 * probably not an accurate guarantee of strftime() supporting or not
31833 	 * supporting a large time range (the full ECMAScript range).
31834 	 */
31835 	if (sizeof(time_t) < 8 &&
31836 	    (parts[DUK_DATE_IDX_YEAR] < 1970 || parts[DUK_DATE_IDX_YEAR] > 2037)) {
31837 		/* be paranoid for 32-bit time values (even avoiding negative ones) */
31838 		return 0;
31839 	}
31840 
31841 	duk_memzero(&tm, sizeof(tm));
31842 	tm.tm_sec = parts[DUK_DATE_IDX_SECOND];
31843 	tm.tm_min = parts[DUK_DATE_IDX_MINUTE];
31844 	tm.tm_hour = parts[DUK_DATE_IDX_HOUR];
31845 	tm.tm_mday = parts[DUK_DATE_IDX_DAY];       /* already one-based */
31846 	tm.tm_mon = parts[DUK_DATE_IDX_MONTH] - 1;  /* one-based -> zero-based */
31847 	tm.tm_year = parts[DUK_DATE_IDX_YEAR] - 1900;
31848 	tm.tm_wday = parts[DUK_DATE_IDX_WEEKDAY];
31849 	tm.tm_isdst = 0;
31850 
31851 	duk_memzero(buf, sizeof(buf));
31852 	if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
31853 		fmt = "%c";
31854 	} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
31855 		fmt = "%x";
31856 	} else {
31857 		DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
31858 		fmt = "%X";
31859 	}
31860 	(void) strftime(buf, sizeof(buf) - 1, fmt, &tm);
31861 	DUK_ASSERT(buf[sizeof(buf) - 1] == 0);
31862 
31863 	duk_push_string(thr, buf);
31864 	return 1;
31865 }
31866 #endif  /* DUK_USE_DATE_FMT_STRFTIME */
31867 
31868 #if defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)
duk_bi_date_get_monotonic_time_clock_gettime(void)31869 DUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_clock_gettime(void) {
31870 	struct timespec ts;
31871 
31872 	if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
31873 		return (duk_double_t) ts.tv_sec * 1000.0 + (duk_double_t) ts.tv_nsec / 1000000.0;
31874 	} else {
31875 		DUK_D(DUK_DPRINT("clock_gettime(CLOCK_MONOTONIC) failed"));
31876 		return 0.0;
31877 	}
31878 }
31879 #endif
31880 
31881 /* automatic undefs */
31882 #undef DUK__STRFTIME_BUF_SIZE
31883 #undef DUK__STRPTIME_BUF_SIZE
31884 /*
31885  *  Windows Date providers
31886  *
31887  *  Platform specific links:
31888  *
31889  *    - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx
31890  */
31891 
31892 /* #include duk_internal.h -> already included */
31893 
31894 /* The necessary #includes are in place in duk_config.h. */
31895 
31896 #if defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS)
31897 /* Shared Windows helpers. */
duk__convert_systime_to_ularge(const SYSTEMTIME * st,ULARGE_INTEGER * res)31898 DUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEGER *res) {
31899 	FILETIME ft;
31900 	if (SystemTimeToFileTime(st, &ft) == 0) {
31901 		DUK_D(DUK_DPRINT("SystemTimeToFileTime() failed, returning 0"));
31902 		res->QuadPart = 0;
31903 	} else {
31904 		res->LowPart = ft.dwLowDateTime;
31905 		res->HighPart = ft.dwHighDateTime;
31906 	}
31907 }
31908 
31909 #if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
duk__convert_filetime_to_ularge(const FILETIME * ft,ULARGE_INTEGER * res)31910 DUK_LOCAL void duk__convert_filetime_to_ularge(const FILETIME *ft, ULARGE_INTEGER *res) {
31911 	res->LowPart = ft->dwLowDateTime;
31912 	res->HighPart = ft->dwHighDateTime;
31913 }
31914 #endif  /* DUK_USE_DATE_NOW_WINDOWS_SUBMS */
31915 
duk__set_systime_jan1970(SYSTEMTIME * st)31916 DUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) {
31917 	duk_memzero((void *) st, sizeof(*st));
31918 	st->wYear = 1970;
31919 	st->wMonth = 1;
31920 	st->wDayOfWeek = 4;  /* not sure whether or not needed; Thursday */
31921 	st->wDay = 1;
31922 	DUK_ASSERT(st->wHour == 0);
31923 	DUK_ASSERT(st->wMinute == 0);
31924 	DUK_ASSERT(st->wSecond == 0);
31925 	DUK_ASSERT(st->wMilliseconds == 0);
31926 }
31927 #endif  /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */
31928 
31929 #if defined(DUK_USE_DATE_NOW_WINDOWS)
duk_bi_date_get_now_windows(void)31930 DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows(void) {
31931 	/* Suggested step-by-step method from documentation of RtlTimeToSecondsSince1970:
31932 	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724928(v=vs.85).aspx
31933 	 */
31934 	SYSTEMTIME st1, st2;
31935 	ULARGE_INTEGER tmp1, tmp2;
31936 
31937 	GetSystemTime(&st1);
31938 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
31939 
31940 	duk__set_systime_jan1970(&st2);
31941 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
31942 
31943 	/* Difference is in 100ns units, convert to milliseconds, keeping
31944 	 * fractions since Duktape 2.2.0.  This is only theoretical because
31945 	 * SYSTEMTIME is limited to milliseconds.
31946 	 */
31947 	return (duk_double_t) ((LONGLONG) tmp1.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000.0;
31948 }
31949 #endif  /* DUK_USE_DATE_NOW_WINDOWS */
31950 
31951 #if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
duk_bi_date_get_now_windows_subms(void)31952 DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows_subms(void) {
31953 	/* Variant of the basic algorithm using GetSystemTimePreciseAsFileTime()
31954 	 * for more accuracy.
31955 	 */
31956 	FILETIME ft1;
31957 	SYSTEMTIME st2;
31958 	ULARGE_INTEGER tmp1, tmp2;
31959 
31960 	GetSystemTimePreciseAsFileTime(&ft1);
31961 	duk__convert_filetime_to_ularge((const FILETIME *) &ft1, &tmp1);
31962 
31963 	duk__set_systime_jan1970(&st2);
31964 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
31965 
31966 	/* Difference is in 100ns units, convert to milliseconds, keeping
31967 	 * fractions since Duktape 2.2.0.
31968 	 */
31969 	return (duk_double_t) ((LONGLONG) tmp1.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000.0;
31970 }
31971 #endif  /* DUK_USE_DATE_NOW_WINDOWS */
31972 
31973 #if defined(DUK_USE_DATE_TZO_WINDOWS)
duk_bi_date_get_local_tzoffset_windows(duk_double_t d)31974 DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) {
31975 	SYSTEMTIME st1;
31976 	SYSTEMTIME st2;
31977 	SYSTEMTIME st3;
31978 	ULARGE_INTEGER tmp1;
31979 	ULARGE_INTEGER tmp2;
31980 	ULARGE_INTEGER tmp3;
31981 	FILETIME ft1;
31982 
31983 	/* XXX: handling of timestamps outside Windows supported range.
31984 	 * How does Windows deal with dates before 1600?  Does windows
31985 	 * support all ECMAScript years (like -200000 and +200000)?
31986 	 * Should equivalent year mapping be used here too?  If so, use
31987 	 * a shared helper (currently integrated into timeval-to-parts).
31988 	 */
31989 
31990 	/* Use the approach described in "Remarks" of FileTimeToLocalFileTime:
31991 	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx
31992 	 */
31993 
31994 	duk__set_systime_jan1970(&st1);
31995 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
31996 	tmp2.QuadPart = (ULONGLONG) (d * 10000.0);  /* millisec -> 100ns units since jan 1, 1970 */
31997 	tmp2.QuadPart += tmp1.QuadPart;             /* input 'd' in Windows UTC, 100ns units */
31998 
31999 	ft1.dwLowDateTime = tmp2.LowPart;
32000 	ft1.dwHighDateTime = tmp2.HighPart;
32001 	if (FileTimeToSystemTime((const FILETIME *) &ft1, &st2) == 0) {
32002 		DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0"));
32003 		return 0;
32004 	}
32005 	if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) {
32006 		DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0"));
32007 		return 0;
32008 	}
32009 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3);
32010 
32011 	/* Positive if local time ahead of UTC. */
32012 	return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / DUK_I64_CONSTANT(10000000));  /* seconds */
32013 }
32014 #endif  /* DUK_USE_DATE_TZO_WINDOWS */
32015 
32016 #if defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST)
duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d)32017 DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d) {
32018 	SYSTEMTIME st1;
32019 	SYSTEMTIME st2;
32020 	FILETIME ft1;
32021 	FILETIME ft2;
32022 	ULARGE_INTEGER tmp1;
32023 	ULARGE_INTEGER tmp2;
32024 
32025 	/* Do a similar computation to duk_bi_date_get_local_tzoffset_windows
32026 	 * but without accounting for daylight savings time.  Use this on
32027 	 * Windows platforms (like Durango) that don't support the
32028 	 * SystemTimeToTzSpecificLocalTime() call.
32029 	 */
32030 
32031 	/* current time not needed for this computation */
32032 	DUK_UNREF(d);
32033 
32034 	duk__set_systime_jan1970(&st1);
32035 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
32036 
32037 	ft1.dwLowDateTime = tmp1.LowPart;
32038 	ft1.dwHighDateTime = tmp1.HighPart;
32039 	if (FileTimeToLocalFileTime((const FILETIME *) &ft1, &ft2) == 0) {
32040 		DUK_D(DUK_DPRINT("FileTimeToLocalFileTime() failed, return tzoffset 0"));
32041 		return 0;
32042 	}
32043 	if (FileTimeToSystemTime((const FILETIME *) &ft2, &st2) == 0) {
32044 		DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0"));
32045 		return 0;
32046 	}
32047 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
32048 
32049 	return (duk_int_t) (((LONGLONG) tmp2.QuadPart - (LONGLONG) tmp1.QuadPart) / DUK_I64_CONSTANT(10000000));  /* seconds */
32050 }
32051 #endif  /* DUK_USE_DATE_TZO_WINDOWS_NO_DST */
32052 
32053 #if defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC)
duk_bi_date_get_monotonic_time_windows_qpc(void)32054 DUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void) {
32055 	LARGE_INTEGER count, freq;
32056 
32057 	/* There are legacy issues with QueryPerformanceCounter():
32058 	 * - Potential jumps: https://support.microsoft.com/en-us/help/274323/performance-counter-value-may-unexpectedly-leap-forward
32059 	 * - Differences between cores (XP): https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx#qpc_support_in_windows_versions
32060 	 *
32061 	 * We avoid these by enabling QPC by default only for Vista or later.
32062 	 */
32063 
32064 	if (QueryPerformanceCounter(&count) && QueryPerformanceFrequency(&freq)) {
32065 		/* XXX: QueryPerformanceFrequency() can be cached */
32066 		return (duk_double_t) count.QuadPart / (duk_double_t) freq.QuadPart * 1000.0;
32067 	} else {
32068 		/* MSDN: "On systems that run Windows XP or later, the function
32069 		 * will always succeed and will thus never return zero."
32070 		 * Provide minimal error path just in case user enables this
32071 		 * feature in pre-XP Windows.
32072 		 */
32073 		return 0.0;
32074 	}
32075 }
32076 #endif  /* DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC */
32077 /*
32078  *  Duktape built-ins
32079  *
32080  *  Size optimization note: it might seem that vararg multipurpose functions
32081  *  like fin(), enc(), and dec() are not very size optimal, but using a single
32082  *  user-visible ECMAScript function saves a lot of run-time footprint; each
32083  *  Function instance takes >100 bytes.  Using a shared native helper and a
32084  *  'magic' value won't save much if there are multiple Function instances
32085  *  anyway.
32086  */
32087 
32088 /* #include duk_internal.h -> already included */
32089 
32090 #if defined(DUK_USE_DUKTAPE_BUILTIN)
32091 
duk_bi_duktape_object_info(duk_hthread * thr)32092 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_info(duk_hthread *thr) {
32093 	duk_inspect_value(thr, -1);
32094 	return 1;
32095 }
32096 
duk_bi_duktape_object_act(duk_hthread * thr)32097 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_act(duk_hthread *thr) {
32098 	duk_int_t level;
32099 
32100 	level = duk_to_int(thr, 0);
32101 	duk_inspect_callstack_entry(thr, level);
32102 	return 1;
32103 }
32104 
duk_bi_duktape_object_gc(duk_hthread * thr)32105 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_gc(duk_hthread *thr) {
32106 	duk_small_uint_t flags;
32107 
32108 	flags = (duk_small_uint_t) duk_get_uint(thr, 0);
32109 	duk_heap_mark_and_sweep(thr->heap, flags);
32110 
32111 	/* XXX: Not sure what the best return value would be in the API.
32112 	 * Return true for now.
32113 	 */
32114 	duk_push_true(thr);
32115 	return 1;
32116 }
32117 
32118 #if defined(DUK_USE_FINALIZER_SUPPORT)
duk_bi_duktape_object_fin(duk_hthread * thr)32119 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_fin(duk_hthread *thr) {
32120 	(void) duk_require_hobject(thr, 0);
32121 	if (duk_get_top(thr) >= 2) {
32122 		/* Set: currently a finalizer is disabled by setting it to
32123 		 * undefined; this does not remove the property at the moment.
32124 		 * The value could be type checked to be either a function
32125 		 * or something else; if something else, the property could
32126 		 * be deleted.  Must use duk_set_finalizer() to keep
32127 		 * DUK_HOBJECT_FLAG_HAVE_FINALIZER in sync.
32128 		 */
32129 		duk_set_top(thr, 2);
32130 		duk_set_finalizer(thr, 0);
32131 		return 0;
32132 	} else {
32133 		/* Get. */
32134 		DUK_ASSERT(duk_get_top(thr) == 1);
32135 		duk_get_finalizer(thr, 0);
32136 		return 1;
32137 	}
32138 }
32139 #endif  /* DUK_USE_FINALIZER_SUPPORT */
32140 
duk_bi_duktape_object_enc(duk_hthread * thr)32141 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_enc(duk_hthread *thr) {
32142 	duk_hstring *h_str;
32143 
32144 	/* Vararg function: must be careful to check/require arguments.
32145 	 * The JSON helpers accept invalid indices and treat them like
32146 	 * non-existent optional parameters.
32147 	 */
32148 
32149 	h_str = duk_require_hstring(thr, 0);  /* Could reject symbols, but no point: won't match comparisons. */
32150 	duk_require_valid_index(thr, 1);
32151 
32152 	if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
32153 		duk_set_top(thr, 2);
32154 		duk_hex_encode(thr, 1);
32155 		DUK_ASSERT_TOP(thr, 2);
32156 	} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
32157 		duk_set_top(thr, 2);
32158 		duk_base64_encode(thr, 1);
32159 		DUK_ASSERT_TOP(thr, 2);
32160 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
32161 	} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
32162 		duk_bi_json_stringify_helper(thr,
32163 		                             1 /*idx_value*/,
32164 		                             2 /*idx_replacer*/,
32165 		                             3 /*idx_space*/,
32166 		                             DUK_JSON_FLAG_EXT_CUSTOM |
32167 		                             DUK_JSON_FLAG_ASCII_ONLY |
32168 		                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
32169 #endif
32170 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
32171 	} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
32172 		duk_bi_json_stringify_helper(thr,
32173 		                             1 /*idx_value*/,
32174 		                             2 /*idx_replacer*/,
32175 		                             3 /*idx_space*/,
32176 		                             DUK_JSON_FLAG_EXT_COMPATIBLE |
32177 		                             DUK_JSON_FLAG_ASCII_ONLY /*flags*/);
32178 #endif
32179 	} else {
32180 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
32181 	}
32182 	return 1;
32183 }
32184 
duk_bi_duktape_object_dec(duk_hthread * thr)32185 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_dec(duk_hthread *thr) {
32186 	duk_hstring *h_str;
32187 
32188 	/* Vararg function: must be careful to check/require arguments.
32189 	 * The JSON helpers accept invalid indices and treat them like
32190 	 * non-existent optional parameters.
32191 	 */
32192 
32193 	h_str = duk_require_hstring(thr, 0);  /* Could reject symbols, but no point: won't match comparisons */
32194 	duk_require_valid_index(thr, 1);
32195 
32196 	if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
32197 		duk_set_top(thr, 2);
32198 		duk_hex_decode(thr, 1);
32199 		DUK_ASSERT_TOP(thr, 2);
32200 	} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
32201 		duk_set_top(thr, 2);
32202 		duk_base64_decode(thr, 1);
32203 		DUK_ASSERT_TOP(thr, 2);
32204 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
32205 	} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
32206 		duk_bi_json_parse_helper(thr,
32207 		                         1 /*idx_value*/,
32208 		                         2 /*idx_replacer*/,
32209 		                         DUK_JSON_FLAG_EXT_CUSTOM /*flags*/);
32210 #endif
32211 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
32212 	} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
32213 		duk_bi_json_parse_helper(thr,
32214 		                         1 /*idx_value*/,
32215 		                         2 /*idx_replacer*/,
32216 		                         DUK_JSON_FLAG_EXT_COMPATIBLE /*flags*/);
32217 #endif
32218 	} else {
32219 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
32220 	}
32221 	return 1;
32222 }
32223 
32224 /*
32225  *  Compact an object
32226  */
32227 
duk_bi_duktape_object_compact(duk_hthread * thr)32228 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_compact(duk_hthread *thr) {
32229 	DUK_ASSERT_TOP(thr, 1);
32230 	duk_compact(thr, 0);
32231 	return 1;  /* return the argument object */
32232 }
32233 
32234 #endif  /* DUK_USE_DUKTAPE_BUILTIN */
32235 /*
32236  *  WHATWG Encoding API built-ins
32237  *
32238  *  API specification: https://encoding.spec.whatwg.org/#api
32239  *  Web IDL: https://www.w3.org/TR/WebIDL/
32240  */
32241 
32242 /* #include duk_internal.h -> already included */
32243 
32244 /*
32245  *  Data structures for encoding/decoding
32246  */
32247 
32248 typedef struct {
32249 	duk_uint8_t *out;      /* where to write next byte(s) */
32250 	duk_codepoint_t lead;  /* lead surrogate */
32251 } duk__encode_context;
32252 
32253 typedef struct {
32254 	/* UTF-8 decoding state */
32255 	duk_codepoint_t codepoint;  /* built up incrementally */
32256 	duk_uint8_t upper;          /* max value of next byte (decode error otherwise) */
32257 	duk_uint8_t lower;          /* min value of next byte (ditto) */
32258 	duk_uint8_t needed;         /* how many more bytes we need */
32259 	duk_uint8_t bom_handled;    /* BOM seen or no longer expected */
32260 
32261 	/* Decoder configuration */
32262 	duk_uint8_t fatal;
32263 	duk_uint8_t ignore_bom;
32264 } duk__decode_context;
32265 
32266 /* The signed duk_codepoint_t type is used to signal a decoded codepoint
32267  * (>= 0) or various other states using negative values.
32268  */
32269 #define DUK__CP_CONTINUE   (-1)  /* continue to next byte, no completed codepoint */
32270 #define DUK__CP_ERROR      (-2)  /* decoding error */
32271 #define DUK__CP_RETRY      (-3)  /* decoding error; retry last byte */
32272 
32273 /*
32274  *  Raw helpers for encoding/decoding
32275  */
32276 
32277 /* Emit UTF-8 (= CESU-8) encoded U+FFFD (replacement char), i.e. ef bf bd. */
duk__utf8_emit_repl(duk_uint8_t * ptr)32278 DUK_LOCAL duk_uint8_t *duk__utf8_emit_repl(duk_uint8_t *ptr) {
32279 	*ptr++ = 0xef;
32280 	*ptr++ = 0xbf;
32281 	*ptr++ = 0xbd;
32282 	return ptr;
32283 }
32284 
duk__utf8_decode_init(duk__decode_context * dec_ctx)32285 DUK_LOCAL void duk__utf8_decode_init(duk__decode_context *dec_ctx) {
32286 	/* (Re)init the decoding state of 'dec_ctx' but leave decoder
32287 	 * configuration fields untouched.
32288 	 */
32289 	dec_ctx->codepoint = 0x0000L;
32290 	dec_ctx->upper = 0xbf;
32291 	dec_ctx->lower = 0x80;
32292 	dec_ctx->needed = 0;
32293 	dec_ctx->bom_handled = 0;
32294 }
32295 
duk__utf8_decode_next(duk__decode_context * dec_ctx,duk_uint8_t x)32296 DUK_LOCAL duk_codepoint_t duk__utf8_decode_next(duk__decode_context *dec_ctx, duk_uint8_t x) {
32297 	/*
32298 	 *  UTF-8 algorithm based on the Encoding specification:
32299 	 *  https://encoding.spec.whatwg.org/#utf-8-decoder
32300 	 *
32301 	 *  Two main states: decoding initial byte vs. decoding continuation
32302 	 *  bytes.  Shortest length encoding is validated by restricting the
32303 	 *  allowed range of first continuation byte using 'lower' and 'upper'.
32304 	 */
32305 
32306 	if (dec_ctx->needed == 0) {
32307 		/* process initial byte */
32308 		if (x <= 0x7f) {
32309 			/* U+0000-U+007F, 1 byte (ASCII) */
32310 			return (duk_codepoint_t) x;
32311 		} else if (x >= 0xc2 && x <= 0xdf) {
32312 			/* U+0080-U+07FF, 2 bytes */
32313 			dec_ctx->needed = 1;
32314 			dec_ctx->codepoint = x & 0x1f;
32315 			DUK_ASSERT(dec_ctx->lower == 0x80);
32316 			DUK_ASSERT(dec_ctx->upper == 0xbf);
32317 			return DUK__CP_CONTINUE;
32318 		} else if (x >= 0xe0 && x <= 0xef) {
32319 			/* U+0800-U+FFFF, 3 bytes */
32320 			if (x == 0xe0) {
32321 				dec_ctx->lower = 0xa0;
32322 				DUK_ASSERT(dec_ctx->upper == 0xbf);
32323 			} else if (x == 0xed) {
32324 				DUK_ASSERT(dec_ctx->lower == 0x80);
32325 				dec_ctx->upper = 0x9f;
32326 			}
32327 			dec_ctx->needed = 2;
32328 			dec_ctx->codepoint = x & 0x0f;
32329 			return DUK__CP_CONTINUE;
32330 		} else if (x >= 0xf0 && x <= 0xf4) {
32331 			/* U+010000-U+10FFFF, 4 bytes */
32332 			if (x == 0xf0) {
32333 				dec_ctx->lower = 0x90;
32334 				DUK_ASSERT(dec_ctx->upper == 0xbf);
32335 			} else if (x == 0xf4) {
32336 				DUK_ASSERT(dec_ctx->lower == 0x80);
32337 				dec_ctx->upper = 0x8f;
32338 			}
32339 			dec_ctx->needed = 3;
32340 			dec_ctx->codepoint = x & 0x07;
32341 			return DUK__CP_CONTINUE;
32342 		} else {
32343 			/* not a legal initial byte */
32344 			return DUK__CP_ERROR;
32345 		}
32346 	} else {
32347 		/* process continuation byte */
32348 		if (x >= dec_ctx->lower && x <= dec_ctx->upper) {
32349 			dec_ctx->lower = 0x80;
32350 			dec_ctx->upper = 0xbf;
32351 			dec_ctx->codepoint = (dec_ctx->codepoint << 6) | (x & 0x3f);
32352 			if (--dec_ctx->needed > 0) {
32353 				/* need more bytes */
32354 				return DUK__CP_CONTINUE;
32355 			} else {
32356 				/* got a codepoint */
32357 				duk_codepoint_t ret;
32358 				DUK_ASSERT(dec_ctx->codepoint <= 0x10ffffL);  /* Decoding rules guarantee. */
32359 				ret = dec_ctx->codepoint;
32360 				dec_ctx->codepoint = 0x0000L;
32361 				dec_ctx->needed = 0;
32362 				return ret;
32363 			}
32364 		} else {
32365 			/* We just encountered an illegal UTF-8 continuation byte.  This might
32366 			 * be the initial byte of the next character; if we return a plain
32367 			 * error status and the decoder is in replacement mode, the character
32368 			 * will be masked.  We still need to alert the caller to the error
32369 			 * though.
32370 			 */
32371 			dec_ctx->codepoint = 0x0000L;
32372 			dec_ctx->needed = 0;
32373 			dec_ctx->lower = 0x80;
32374 			dec_ctx->upper = 0xbf;
32375 			return DUK__CP_RETRY;
32376 		}
32377 	}
32378 }
32379 
32380 #if defined(DUK_USE_ENCODING_BUILTINS)
duk__utf8_encode_char(void * udata,duk_codepoint_t codepoint)32381 DUK_LOCAL void duk__utf8_encode_char(void *udata, duk_codepoint_t codepoint) {
32382 	duk__encode_context *enc_ctx;
32383 
32384 	DUK_ASSERT(codepoint >= 0);
32385 	enc_ctx = (duk__encode_context *) udata;
32386 	DUK_ASSERT(enc_ctx != NULL);
32387 
32388 #if !defined(DUK_USE_PREFER_SIZE)
32389 	if (codepoint <= 0x7f && enc_ctx->lead == 0x0000L) {
32390 		/* Fast path for ASCII. */
32391 		*enc_ctx->out++ = (duk_uint8_t) codepoint;
32392 		return;
32393 	}
32394 #endif
32395 
32396 	if (DUK_UNLIKELY(codepoint > 0x10ffffL)) {
32397 		/* cannot legally encode in UTF-8 */
32398 		codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
32399 	} else if (codepoint >= 0xd800L && codepoint <= 0xdfffL) {
32400 		if (codepoint <= 0xdbffL) {
32401 			/* high surrogate */
32402 			duk_codepoint_t prev_lead = enc_ctx->lead;
32403 			enc_ctx->lead = codepoint;
32404 			if (prev_lead == 0x0000L) {
32405 				/* high surrogate, no output */
32406 				return;
32407 			} else {
32408 				/* consecutive high surrogates, consider first one unpaired */
32409 				codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
32410 			}
32411 		} else {
32412 			/* low surrogate */
32413 			if (enc_ctx->lead != 0x0000L) {
32414 				codepoint = (duk_codepoint_t) (0x010000L + ((enc_ctx->lead - 0xd800L) << 10) + (codepoint - 0xdc00L));
32415 				enc_ctx->lead = 0x0000L;
32416 			} else {
32417 				/* unpaired low surrogate */
32418 				DUK_ASSERT(enc_ctx->lead == 0x0000L);
32419 				codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
32420 			}
32421 		}
32422 	} else {
32423 		if (enc_ctx->lead != 0x0000L) {
32424 			/* unpaired high surrogate: emit replacement character and the input codepoint */
32425 			enc_ctx->lead = 0x0000L;
32426 			enc_ctx->out = duk__utf8_emit_repl(enc_ctx->out);
32427 		}
32428 	}
32429 
32430 	/* Codepoint may be original input, a decoded surrogate pair, or may
32431 	 * have been replaced with U+FFFD.
32432 	 */
32433 	enc_ctx->out += duk_unicode_encode_xutf8((duk_ucodepoint_t) codepoint, enc_ctx->out);
32434 }
32435 #endif  /* DUK_USE_ENCODING_BUILTINS */
32436 
32437 /* Shared helper for buffer-to-string using a TextDecoder() compatible UTF-8
32438  * decoder.
32439  */
duk__decode_helper(duk_hthread * thr,duk__decode_context * dec_ctx)32440 DUK_LOCAL duk_ret_t duk__decode_helper(duk_hthread *thr, duk__decode_context *dec_ctx) {
32441 	const duk_uint8_t *input;
32442 	duk_size_t len = 0;
32443 	duk_size_t len_tmp;
32444 	duk_bool_t stream = 0;
32445 	duk_codepoint_t codepoint;
32446 	duk_uint8_t *output;
32447 	const duk_uint8_t *in;
32448 	duk_uint8_t *out;
32449 
32450 	DUK_ASSERT(dec_ctx != NULL);
32451 
32452 	/* Careful with input buffer pointer: any side effects involving
32453 	 * code execution (e.g. getters, coercion calls, and finalizers)
32454 	 * may cause a resize and invalidate a pointer we've read.  This
32455 	 * is why the pointer is actually looked up at the last minute.
32456 	 * Argument validation must still happen first to match WHATWG
32457 	 * required side effect order.
32458 	 */
32459 
32460 	if (duk_is_undefined(thr, 0)) {
32461 		duk_push_fixed_buffer_nozero(thr, 0);
32462 		duk_replace(thr, 0);
32463 	}
32464 	(void) duk_require_buffer_data(thr, 0, &len);  /* Need 'len', avoid pointer. */
32465 
32466 	if (duk_check_type_mask(thr, 1, DUK_TYPE_MASK_UNDEFINED |
32467 	                                DUK_TYPE_MASK_NULL |
32468 	                                DUK_TYPE_MASK_NONE)) {
32469 		/* Use defaults, treat missing value like undefined. */
32470 	} else {
32471 		duk_require_type_mask(thr, 1, DUK_TYPE_MASK_UNDEFINED |
32472 	                                      DUK_TYPE_MASK_NULL |
32473 	                                      DUK_TYPE_MASK_LIGHTFUNC |
32474 	                                      DUK_TYPE_MASK_BUFFER |
32475 		                              DUK_TYPE_MASK_OBJECT);
32476 		if (duk_get_prop_literal(thr, 1, "stream")) {
32477 			stream = duk_to_boolean(thr, -1);
32478 		}
32479 	}
32480 
32481 	/* Allowance is 3*len in the general case because all bytes may potentially
32482 	 * become U+FFFD.  If the first byte completes a non-BMP codepoint it will
32483 	 * decode to a CESU-8 surrogate pair (6 bytes) so we allow 3 extra bytes to
32484 	 * compensate: (1*3)+3 = 6.  Non-BMP codepoints are safe otherwise because
32485 	 * the 4->6 expansion is well under the 3x allowance.
32486 	 *
32487 	 * XXX: As with TextEncoder, need a better buffer allocation strategy here.
32488 	 */
32489 	if (len >= (DUK_HBUFFER_MAX_BYTELEN / 3) - 3) {
32490 		DUK_ERROR_TYPE(thr, DUK_STR_RESULT_TOO_LONG);
32491 		DUK_WO_NORETURN(return 0;);
32492 	}
32493 	output = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, 3 + (3 * len));  /* used parts will be always manually written over */
32494 
32495 	input = (const duk_uint8_t *) duk_get_buffer_data(thr, 0, &len_tmp);
32496 	DUK_ASSERT(input != NULL || len == 0);
32497 	if (DUK_UNLIKELY(len != len_tmp)) {
32498 		/* Very unlikely but possible: source buffer was resized by
32499 		 * a side effect when fixed buffer was pushed.  Output buffer
32500 		 * may not be large enough to hold output, so just fail if
32501 		 * length has changed.
32502 		 */
32503 		DUK_D(DUK_DPRINT("input buffer resized by side effect, fail"));
32504 		goto fail_type;
32505 	}
32506 
32507 	/* From this point onwards it's critical that no side effect occur
32508 	 * which may disturb 'input': finalizer execution, property accesses,
32509 	 * active coercions, etc.  Even an allocation related mark-and-sweep
32510 	 * may affect the pointer because it may trigger a pending finalizer.
32511 	 */
32512 
32513 	in = input;
32514 	out = output;
32515 	while (in < input + len) {
32516 		codepoint = duk__utf8_decode_next(dec_ctx, *in++);
32517 		if (codepoint < 0) {
32518 			if (codepoint == DUK__CP_CONTINUE) {
32519 				continue;
32520 			}
32521 
32522 			/* Decoding error with or without retry. */
32523 			DUK_ASSERT(codepoint == DUK__CP_ERROR || codepoint == DUK__CP_RETRY);
32524 			if (codepoint == DUK__CP_RETRY) {
32525 				--in;  /* retry last byte */
32526 			}
32527 			/* replacement mode: replace with U+FFFD */
32528 			codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
32529 			if (dec_ctx->fatal) {
32530 				/* fatal mode: throw a TypeError */
32531 				goto fail_type;
32532 			}
32533 			/* Continue with 'codepoint', Unicode replacement. */
32534 		}
32535 		DUK_ASSERT(codepoint >= 0x0000L && codepoint <= 0x10ffffL);
32536 
32537 		if (!dec_ctx->bom_handled) {
32538 			dec_ctx->bom_handled = 1;
32539 			if (codepoint == 0xfeffL && !dec_ctx->ignore_bom) {
32540 				continue;
32541 			}
32542 		}
32543 
32544 		out += duk_unicode_encode_cesu8((duk_ucodepoint_t) codepoint, out);
32545 		DUK_ASSERT(out <= output + (3 + (3 * len)));
32546 	}
32547 
32548 	if (!stream) {
32549 		if (dec_ctx->needed != 0) {
32550 			/* truncated sequence at end of buffer */
32551 			if (dec_ctx->fatal) {
32552 				goto fail_type;
32553 			} else {
32554 				out += duk_unicode_encode_cesu8(DUK_UNICODE_CP_REPLACEMENT_CHARACTER, out);
32555 				DUK_ASSERT(out <= output + (3 + (3 * len)));
32556 			}
32557 		}
32558 		duk__utf8_decode_init(dec_ctx);  /* Initialize decoding state for potential reuse. */
32559 	}
32560 
32561 	/* Output buffer is fixed and thus stable even if there had been
32562 	 * side effects (which there shouldn't be).
32563 	 */
32564 	duk_push_lstring(thr, (const char *) output, (duk_size_t) (out - output));
32565 	return 1;
32566 
32567  fail_type:
32568 	DUK_ERROR_TYPE(thr, DUK_STR_UTF8_DECODE_FAILED);
32569 	DUK_WO_NORETURN(return 0;);
32570 }
32571 
32572 /*
32573  *  Built-in bindings
32574  */
32575 
32576 #if defined(DUK_USE_ENCODING_BUILTINS)
duk_bi_textencoder_constructor(duk_hthread * thr)32577 DUK_INTERNAL duk_ret_t duk_bi_textencoder_constructor(duk_hthread *thr) {
32578 	/* TextEncoder currently requires no persistent state, so the constructor
32579 	 * does nothing on purpose.
32580 	 */
32581 
32582 	duk_require_constructor_call(thr);
32583 	return 0;
32584 }
32585 
duk_bi_textencoder_prototype_encoding_getter(duk_hthread * thr)32586 DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_hthread *thr) {
32587 	duk_push_literal(thr, "utf-8");
32588 	return 1;
32589 }
32590 
duk_bi_textencoder_prototype_encode(duk_hthread * thr)32591 DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encode(duk_hthread *thr) {
32592 	duk__encode_context enc_ctx;
32593 	duk_size_t len;
32594 	duk_size_t final_len;
32595 	duk_uint8_t *output;
32596 
32597 	DUK_ASSERT_TOP(thr, 1);
32598 	if (duk_is_undefined(thr, 0)) {
32599 		len = 0;
32600 	} else {
32601 		duk_hstring *h_input;
32602 
32603 		h_input = duk_to_hstring(thr, 0);
32604 		DUK_ASSERT(h_input != NULL);
32605 
32606 		len = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_input);
32607 		if (len >= DUK_HBUFFER_MAX_BYTELEN / 3) {
32608 			DUK_ERROR_TYPE(thr, DUK_STR_RESULT_TOO_LONG);
32609 			DUK_WO_NORETURN(return 0;);
32610 		}
32611 	}
32612 
32613 	/* Allowance is 3*len because all bytes can potentially be replaced with
32614 	 * U+FFFD -- which rather inconveniently encodes to 3 bytes in UTF-8.
32615 	 * Rely on dynamic buffer data pointer stability: no other code has
32616 	 * access to the data pointer.
32617 	 *
32618 	 * XXX: The buffer allocation strategy used here is rather inefficient.
32619 	 * Maybe switch to a chunk-based strategy, or preprocess the string to
32620 	 * figure out the space needed ahead of time?
32621 	 */
32622 	DUK_ASSERT(3 * len >= len);
32623 	output = (duk_uint8_t *) duk_push_dynamic_buffer(thr, 3 * len);
32624 
32625 	if (len > 0) {
32626 		DUK_ASSERT(duk_is_string(thr, 0));  /* True if len > 0. */
32627 
32628 		/* XXX: duk_decode_string() is used to process the input
32629 		 * string.  For standard ECMAScript strings, represented
32630 		 * internally as CESU-8, this is fine.  However, behavior
32631 		 * beyond CESU-8 is not very strict: codepoints using an
32632 		 * extended form of UTF-8 are also accepted, and invalid
32633 		 * codepoint sequences (which are allowed in Duktape strings)
32634 		 * are not handled as well as they could (e.g. invalid
32635 		 * continuation bytes may mask following codepoints).
32636 		 * This is how ECMAScript code would also see such strings.
32637 		 * Maybe replace duk_decode_string() with an explicit strict
32638 		 * CESU-8 decoder here?
32639 		 */
32640 		enc_ctx.lead = 0x0000L;
32641 		enc_ctx.out = output;
32642 		duk_decode_string(thr, 0, duk__utf8_encode_char, (void *) &enc_ctx);
32643 		if (enc_ctx.lead != 0x0000L) {
32644 			/* unpaired high surrogate at end of string */
32645 			enc_ctx.out = duk__utf8_emit_repl(enc_ctx.out);
32646 			DUK_ASSERT(enc_ctx.out <= output + (3 * len));
32647 		}
32648 
32649 		/* The output buffer is usually very much oversized, so shrink it to
32650 		 * actually needed size.  Pointer stability assumed up to this point.
32651 		 */
32652 		DUK_ASSERT_TOP(thr, 2);
32653 		DUK_ASSERT(output == (duk_uint8_t *) duk_get_buffer_data(thr, -1, NULL));
32654 
32655 		final_len = (duk_size_t) (enc_ctx.out - output);
32656 		duk_resize_buffer(thr, -1, final_len);
32657 		/* 'output' and 'enc_ctx.out' are potentially invalidated by the resize. */
32658 	} else {
32659 		final_len = 0;
32660 	}
32661 
32662 	/* Standard WHATWG output is a Uint8Array.  Here the Uint8Array will
32663 	 * be backed by a dynamic buffer which differs from e.g. Uint8Arrays
32664 	 * created as 'new Uint8Array(N)'.  ECMAScript code won't see the
32665 	 * difference but C code will.  When bufferobjects are not supported,
32666 	 * returns a plain dynamic buffer.
32667 	 */
32668 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
32669 	duk_push_buffer_object(thr, -1, 0, final_len, DUK_BUFOBJ_UINT8ARRAY);
32670 #endif
32671 	return 1;
32672 }
32673 
duk_bi_textdecoder_constructor(duk_hthread * thr)32674 DUK_INTERNAL duk_ret_t duk_bi_textdecoder_constructor(duk_hthread *thr) {
32675 	duk__decode_context *dec_ctx;
32676 	duk_bool_t fatal = 0;
32677 	duk_bool_t ignore_bom = 0;
32678 
32679 	DUK_ASSERT_TOP(thr, 2);
32680 	duk_require_constructor_call(thr);
32681 	if (!duk_is_undefined(thr, 0)) {
32682 		/* XXX: For now ignore 'label' (encoding identifier). */
32683 		duk_to_string(thr, 0);
32684 	}
32685 	if (!duk_is_null_or_undefined(thr, 1)) {
32686 		if (duk_get_prop_literal(thr, 1, "fatal")) {
32687 			fatal = duk_to_boolean(thr, -1);
32688 		}
32689 		if (duk_get_prop_literal(thr, 1, "ignoreBOM")) {
32690 			ignore_bom = duk_to_boolean(thr, -1);
32691 		}
32692 	}
32693 
32694 	duk_push_this(thr);
32695 
32696 	/* The decode context is not assumed to be zeroed; all fields are
32697 	 * initialized explicitly.
32698 	 */
32699 	dec_ctx = (duk__decode_context *) duk_push_fixed_buffer(thr, sizeof(duk__decode_context));
32700 	dec_ctx->fatal = (duk_uint8_t) fatal;
32701 	dec_ctx->ignore_bom = (duk_uint8_t) ignore_bom;
32702 	duk__utf8_decode_init(dec_ctx);  /* Initializes remaining fields. */
32703 
32704 	duk_put_prop_literal(thr, -2, DUK_INTERNAL_SYMBOL("Context"));
32705 	return 0;
32706 }
32707 
32708 /* Get TextDecoder context from 'this'; leaves garbage on stack. */
duk__get_textdecoder_context(duk_hthread * thr)32709 DUK_LOCAL duk__decode_context *duk__get_textdecoder_context(duk_hthread *thr) {
32710 	duk__decode_context *dec_ctx;
32711 	duk_push_this(thr);
32712 	duk_get_prop_literal(thr, -1, DUK_INTERNAL_SYMBOL("Context"));
32713 	dec_ctx = (duk__decode_context *) duk_require_buffer(thr, -1, NULL);
32714 	DUK_ASSERT(dec_ctx != NULL);
32715 	return dec_ctx;
32716 }
32717 
duk_bi_textdecoder_prototype_shared_getter(duk_hthread * thr)32718 DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_hthread *thr) {
32719 	duk__decode_context *dec_ctx;
32720 	duk_int_t magic;
32721 
32722 	dec_ctx = duk__get_textdecoder_context(thr);
32723 	magic = duk_get_current_magic(thr);
32724 	switch (magic) {
32725 	case 0:
32726 		/* Encoding is now fixed, so _Context lookup is only needed to
32727 		 * validate the 'this' binding (TypeError if not TextDecoder-like).
32728 		 */
32729 		duk_push_literal(thr, "utf-8");
32730 		break;
32731 	case 1:
32732 		duk_push_boolean(thr, dec_ctx->fatal);
32733 		break;
32734 	default:
32735 		duk_push_boolean(thr, dec_ctx->ignore_bom);
32736 		break;
32737 	}
32738 
32739 	return 1;
32740 }
32741 
duk_bi_textdecoder_prototype_decode(duk_hthread * thr)32742 DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_hthread *thr) {
32743 	duk__decode_context *dec_ctx;
32744 
32745 	dec_ctx = duk__get_textdecoder_context(thr);
32746 	return duk__decode_helper(thr, dec_ctx);
32747 }
32748 #endif  /* DUK_USE_ENCODING_BUILTINS */
32749 
32750 /*
32751  *  Internal helper for Node.js Buffer
32752  */
32753 
32754 /* Internal helper used for Node.js Buffer .toString().  Value stack convention
32755  * is currently odd: it mimics TextDecoder .decode() so that argument must be at
32756  * index 0, and decode options (not present for Buffer) at index 1.  Return value
32757  * is a Duktape/C function return value.
32758  */
duk_textdecoder_decode_utf8_nodejs(duk_hthread * thr)32759 DUK_INTERNAL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_hthread *thr) {
32760 	duk__decode_context dec_ctx;
32761 
32762 	dec_ctx.fatal = 0;  /* use replacement chars */
32763 	dec_ctx.ignore_bom = 1;  /* ignore BOMs (matches Node.js Buffer .toString()) */
32764 	duk__utf8_decode_init(&dec_ctx);
32765 
32766 	return duk__decode_helper(thr, &dec_ctx);
32767 }
32768 
32769 /* automatic undefs */
32770 #undef DUK__CP_CONTINUE
32771 #undef DUK__CP_ERROR
32772 #undef DUK__CP_RETRY
32773 /*
32774  *  Error built-ins
32775  */
32776 
32777 /* #include duk_internal.h -> already included */
32778 
duk_bi_error_constructor_shared(duk_hthread * thr)32779 DUK_INTERNAL duk_ret_t duk_bi_error_constructor_shared(duk_hthread *thr) {
32780 	/* Behavior for constructor and non-constructor call is
32781 	 * the same except for augmenting the created error.  When
32782 	 * called as a constructor, the caller (duk_new()) will handle
32783 	 * augmentation; when called as normal function, we need to do
32784 	 * it here.
32785 	 */
32786 
32787 	duk_small_int_t bidx_prototype = duk_get_current_magic(thr);
32788 
32789 	/* same for both error and each subclass like TypeError */
32790 	duk_uint_t flags_and_class = DUK_HOBJECT_FLAG_EXTENSIBLE |
32791 	                             DUK_HOBJECT_FLAG_FASTREFS |
32792 	                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR);
32793 
32794 	(void) duk_push_object_helper(thr, flags_and_class, bidx_prototype);
32795 
32796 	/* If message is undefined, the own property 'message' is not set at
32797 	 * all to save property space.  An empty message is inherited anyway.
32798 	 */
32799 	if (!duk_is_undefined(thr, 0)) {
32800 		duk_to_string(thr, 0);
32801 		duk_dup_0(thr);  /* [ message error message ] */
32802 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
32803 	}
32804 
32805 	/* Augment the error if called as a normal function.  __FILE__ and __LINE__
32806 	 * are not desirable in this case.
32807 	 */
32808 
32809 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
32810 	if (!duk_is_constructor_call(thr)) {
32811 		duk_err_augment_error_create(thr, thr, NULL, 0, DUK_AUGMENT_FLAG_NOBLAME_FILELINE);
32812 	}
32813 #endif
32814 
32815 	return 1;
32816 }
32817 
duk_bi_error_prototype_to_string(duk_hthread * thr)32818 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_hthread *thr) {
32819 	/* XXX: optimize with more direct internal access */
32820 
32821 	duk_push_this(thr);
32822 	(void) duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
32823 
32824 	/* [ ... this ] */
32825 
32826 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME);
32827 	if (duk_is_undefined(thr, -1)) {
32828 		duk_pop(thr);
32829 		duk_push_literal(thr, "Error");
32830 	} else {
32831 		duk_to_string(thr, -1);
32832 	}
32833 
32834 	/* [ ... this name ] */
32835 
32836 	/* XXX: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by
32837 	 * accident or are they actually needed?  The first ToString()
32838 	 * could conceivably return 'undefined'.
32839 	 */
32840 	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE);
32841 	if (duk_is_undefined(thr, -1)) {
32842 		duk_pop(thr);
32843 		duk_push_hstring_empty(thr);
32844 	} else {
32845 		duk_to_string(thr, -1);
32846 	}
32847 
32848 	/* [ ... this name message ] */
32849 
32850 	if (duk_get_length(thr, -2) == 0) {
32851 		/* name is empty -> return message */
32852 		return 1;
32853 	}
32854 	if (duk_get_length(thr, -1) == 0) {
32855 		/* message is empty -> return name */
32856 		duk_pop(thr);
32857 		return 1;
32858 	}
32859 	duk_push_literal(thr, ": ");
32860 	duk_insert(thr, -2);  /* ... name ': ' message */
32861 	duk_concat(thr, 3);
32862 
32863 	return 1;
32864 }
32865 
32866 #if defined(DUK_USE_TRACEBACKS)
32867 
32868 /*
32869  *  Traceback handling
32870  *
32871  *  The unified helper decodes the traceback and produces various requested
32872  *  outputs.  It should be optimized for size, and may leave garbage on stack,
32873  *  only the topmost return value matters.  For instance, traceback separator
32874  *  and decoded strings are pushed even when looking for filename only.
32875  *
32876  *  NOTE: although _Tracedata is an internal property, user code can currently
32877  *  write to the array (or replace it with something other than an array).
32878  *  The code below must tolerate arbitrary _Tracedata.  It can throw errors
32879  *  etc, but cannot cause a segfault or memory unsafe behavior.
32880  */
32881 
32882 /* constants arbitrary, chosen for small loads */
32883 #define DUK__OUTPUT_TYPE_TRACEBACK   (-1)
32884 #define DUK__OUTPUT_TYPE_FILENAME    0
32885 #define DUK__OUTPUT_TYPE_LINENUMBER  1
32886 
duk__error_getter_helper(duk_hthread * thr,duk_small_int_t output_type)32887 DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_hthread *thr, duk_small_int_t output_type) {
32888 	duk_idx_t idx_td;
32889 	duk_small_int_t i;  /* traceback depth fits into 16 bits */
32890 	duk_small_int_t t;  /* stack type fits into 16 bits */
32891 	duk_small_int_t count_func = 0;  /* traceback depth ensures fits into 16 bits */
32892 	const char *str_tailcall = " tailcall";
32893 	const char *str_strict = " strict";
32894 	const char *str_construct = " construct";
32895 	const char *str_prevyield = " preventsyield";
32896 	const char *str_directeval = " directeval";
32897 	const char *str_empty = "";
32898 
32899 	DUK_ASSERT_TOP(thr, 0);  /* fixed arg count */
32900 
32901 	duk_push_this(thr);
32902 	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_TRACEDATA);
32903 	idx_td = duk_get_top_index(thr);
32904 
32905 	duk_push_hstring_stridx(thr, DUK_STRIDX_NEWLINE_4SPACE);
32906 	duk_push_this(thr);
32907 
32908 	/* [ ... this tracedata sep this ] */
32909 
32910 	/* XXX: skip null filename? */
32911 
32912 	if (duk_check_type(thr, idx_td, DUK_TYPE_OBJECT)) {
32913 		/* Current tracedata contains 2 entries per callstack entry. */
32914 		for (i = 0; ; i += 2) {
32915 			duk_int_t pc;
32916 			duk_uint_t line;
32917 			duk_uint_t flags;
32918 			duk_double_t d;
32919 			const char *funcname;
32920 			const char *filename;
32921 			duk_hobject *h_func;
32922 			duk_hstring *h_name;
32923 
32924 			duk_require_stack(thr, 5);
32925 			duk_get_prop_index(thr, idx_td, (duk_uarridx_t) i);
32926 			duk_get_prop_index(thr, idx_td, (duk_uarridx_t) (i + 1));
32927 			d = duk_to_number_m1(thr);
32928 			pc = duk_double_to_int_t(DUK_FMOD(d, DUK_DOUBLE_2TO32));
32929 			flags = duk_double_to_uint_t(DUK_FLOOR(d / DUK_DOUBLE_2TO32));
32930 			t = (duk_small_int_t) duk_get_type(thr, -2);
32931 
32932 			if (t == DUK_TYPE_OBJECT || t == DUK_TYPE_LIGHTFUNC) {
32933 				/*
32934 				 *  ECMAScript/native function call or lightfunc call
32935 				 */
32936 
32937 				count_func++;
32938 
32939 				/* [ ... v1(func) v2(pc+flags) ] */
32940 
32941 				/* These may be systematically omitted by Duktape
32942 				 * with certain config options, but allow user to
32943 				 * set them on a case-by-case basis.
32944 				 */
32945 				duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
32946 				duk_get_prop_stridx_short(thr, -3, DUK_STRIDX_FILE_NAME);
32947 
32948 #if defined(DUK_USE_PC2LINE)
32949 				line = (duk_uint_t) duk_hobject_pc2line_query(thr, -4, (duk_uint_fast32_t) pc);
32950 #else
32951 				line = 0;
32952 #endif
32953 
32954 				/* [ ... v1 v2 name filename ] */
32955 
32956 				/* When looking for .fileName/.lineNumber, blame first
32957 				 * function which has a .fileName.
32958 				 */
32959 				if (duk_is_string_notsymbol(thr, -1)) {
32960 					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
32961 						return 1;
32962 					} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
32963 						duk_push_uint(thr, line);
32964 						return 1;
32965 					}
32966 				}
32967 
32968 				/* XXX: Change 'anon' handling here too, to use empty string for anonymous functions? */
32969 				/* XXX: Could be improved by coercing to a readable duk_tval (especially string escaping) */
32970 				h_name = duk_get_hstring_notsymbol(thr, -2);  /* may be NULL */
32971 				funcname = (h_name == NULL || h_name == DUK_HTHREAD_STRING_EMPTY_STRING(thr)) ?
32972 				           "[anon]" : (const char *) DUK_HSTRING_GET_DATA(h_name);
32973 				filename = duk_get_string_notsymbol(thr, -1);
32974 				filename = filename ? filename : "";
32975 				DUK_ASSERT(funcname != NULL);
32976 				DUK_ASSERT(filename != NULL);
32977 
32978 				h_func = duk_get_hobject(thr, -4);  /* NULL for lightfunc */
32979 
32980 				if (h_func == NULL) {
32981 					duk_push_sprintf(thr, "at %s light%s%s%s%s%s",
32982 					                 (const char *) funcname,
32983 					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
32984 					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
32985 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
32986 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
32987 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
32988 				} else if (DUK_HOBJECT_HAS_NATFUNC(h_func)) {
32989 					duk_push_sprintf(thr, "at %s (%s) native%s%s%s%s%s",
32990 					                 (const char *) funcname,
32991 					                 (const char *) filename,
32992 					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
32993 					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
32994 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
32995 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
32996 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
32997 				} else {
32998 					duk_push_sprintf(thr, "at %s (%s:%lu)%s%s%s%s%s",
32999 					                 (const char *) funcname,
33000 					                 (const char *) filename,
33001 					                 (unsigned long) line,
33002 					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
33003 					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
33004 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
33005 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
33006 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
33007 				}
33008 				duk_replace(thr, -5);   /* [ ... v1 v2 name filename str ] -> [ ... str v2 name filename ] */
33009 				duk_pop_3(thr);         /* -> [ ... str ] */
33010 			} else if (t == DUK_TYPE_STRING) {
33011 				const char *str_file;
33012 
33013 				/*
33014 				 *  __FILE__ / __LINE__ entry, here 'pc' is line number directly.
33015 				 *  Sometimes __FILE__ / __LINE__ is reported as the source for
33016 				 *  the error (fileName, lineNumber), sometimes not.
33017 				 */
33018 
33019 				/* [ ... v1(filename) v2(line+flags) ] */
33020 
33021 				/* When looking for .fileName/.lineNumber, blame compilation
33022 				 * or C call site unless flagged not to do so.
33023 				 */
33024 				if (!(flags & DUK_TB_FLAG_NOBLAME_FILELINE)) {
33025 					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
33026 						duk_pop(thr);
33027 						return 1;
33028 					} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
33029 						duk_push_int(thr, pc);
33030 						return 1;
33031 					}
33032 				}
33033 
33034 				/* Tracedata is trusted but avoid any risk of using a NULL
33035 				 * for %s format because it has undefined behavior.  Symbols
33036 				 * don't need to be explicitly rejected as they pose no memory
33037 				 * safety issues.
33038 				 */
33039 				str_file = (const char *) duk_get_string(thr, -2);
33040 				duk_push_sprintf(thr, "at [anon] (%s:%ld) internal",
33041 				                 (const char *) (str_file ? str_file : "null"), (long) pc);
33042 				duk_replace(thr, -3);  /* [ ... v1 v2 str ] -> [ ... str v2 ] */
33043 				duk_pop(thr);          /* -> [ ... str ] */
33044 			} else {
33045 				/* unknown, ignore */
33046 				duk_pop_2(thr);
33047 				break;
33048 			}
33049 		}
33050 
33051 		if (count_func >= DUK_USE_TRACEBACK_DEPTH) {
33052 			/* Possibly truncated; there is no explicit truncation
33053 			 * marker so this is the best we can do.
33054 			 */
33055 
33056 			duk_push_hstring_stridx(thr, DUK_STRIDX_BRACKETED_ELLIPSIS);
33057 		}
33058 	}
33059 
33060 	/* [ ... this tracedata sep this str1 ... strN ] */
33061 
33062 	if (output_type != DUK__OUTPUT_TYPE_TRACEBACK) {
33063 		return 0;
33064 	} else {
33065 		/* The 'this' after 'sep' will get ToString() coerced by
33066 		 * duk_join() automatically.  We don't want to do that
33067 		 * coercion when providing .fileName or .lineNumber (GH-254).
33068 		 */
33069 		duk_join(thr, duk_get_top(thr) - (idx_td + 2) /*count, not including sep*/);
33070 		return 1;
33071 	}
33072 }
33073 
33074 /* XXX: Output type could be encoded into native function 'magic' value to
33075  * save space.  For setters the stridx could be encoded into 'magic'.
33076  */
33077 
duk_bi_error_prototype_stack_getter(duk_hthread * thr)33078 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_hthread *thr) {
33079 	return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_TRACEBACK);
33080 }
33081 
duk_bi_error_prototype_filename_getter(duk_hthread * thr)33082 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_hthread *thr) {
33083 	return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_FILENAME);
33084 }
33085 
duk_bi_error_prototype_linenumber_getter(duk_hthread * thr)33086 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_hthread *thr) {
33087 	return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_LINENUMBER);
33088 }
33089 
33090 #else  /* DUK_USE_TRACEBACKS */
33091 
33092 /*
33093  *  Traceback handling when tracebacks disabled.
33094  *
33095  *  The fileName / lineNumber stubs are now necessary because built-in
33096  *  data will include the accessor properties in Error.prototype.  If those
33097  *  are removed for builds without tracebacks, these can also be removed.
33098  *  'stack' should still be present and produce a ToString() equivalent:
33099  *  this is useful for user code which prints a stacktrace and expects to
33100  *  see something useful.  A normal stacktrace also begins with a ToString()
33101  *  of the error so this makes sense.
33102  */
33103 
duk_bi_error_prototype_stack_getter(duk_hthread * thr)33104 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_hthread *thr) {
33105 	/* XXX: remove this native function and map 'stack' accessor
33106 	 * to the toString() implementation directly.
33107 	 */
33108 	return duk_bi_error_prototype_to_string(thr);
33109 }
33110 
duk_bi_error_prototype_filename_getter(duk_hthread * thr)33111 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_hthread *thr) {
33112 	DUK_UNREF(thr);
33113 	return 0;
33114 }
33115 
duk_bi_error_prototype_linenumber_getter(duk_hthread * thr)33116 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_hthread *thr) {
33117 	DUK_UNREF(thr);
33118 	return 0;
33119 }
33120 
33121 #endif  /* DUK_USE_TRACEBACKS */
33122 
duk__error_setter_helper(duk_hthread * thr,duk_small_uint_t stridx_key)33123 DUK_LOCAL duk_ret_t duk__error_setter_helper(duk_hthread *thr, duk_small_uint_t stridx_key) {
33124 	/* Attempt to write 'stack', 'fileName', 'lineNumber' works as if
33125 	 * user code called Object.defineProperty() to create an overriding
33126 	 * own property.  This allows user code to overwrite .fileName etc
33127 	 * intuitively as e.g. "err.fileName = 'dummy'" as one might expect.
33128 	 * See https://github.com/svaarala/duktape/issues/387.
33129 	 */
33130 
33131 	DUK_ASSERT_TOP(thr, 1);  /* fixed arg count: value */
33132 
33133 	duk_push_this(thr);
33134 	duk_push_hstring_stridx(thr, stridx_key);
33135 	duk_dup_0(thr);
33136 
33137 	/* [ ... obj key value ] */
33138 
33139 	DUK_DD(DUK_DDPRINT("error setter: %!T %!T %!T",
33140 	                   duk_get_tval(thr, -3), duk_get_tval(thr, -2), duk_get_tval(thr, -1)));
33141 
33142 	duk_def_prop(thr, -3, DUK_DEFPROP_HAVE_VALUE |
33143 	                      DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE |
33144 	                      DUK_DEFPROP_HAVE_ENUMERABLE | /*not enumerable*/
33145 	                      DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE);
33146 	return 0;
33147 }
33148 
duk_bi_error_prototype_stack_setter(duk_hthread * thr)33149 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_setter(duk_hthread *thr) {
33150 	return duk__error_setter_helper(thr, DUK_STRIDX_STACK);
33151 }
33152 
duk_bi_error_prototype_filename_setter(duk_hthread * thr)33153 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_setter(duk_hthread *thr) {
33154 	return duk__error_setter_helper(thr, DUK_STRIDX_FILE_NAME);
33155 }
33156 
duk_bi_error_prototype_linenumber_setter(duk_hthread * thr)33157 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_hthread *thr) {
33158 	return duk__error_setter_helper(thr, DUK_STRIDX_LINE_NUMBER);
33159 }
33160 
33161 /* automatic undefs */
33162 #undef DUK__OUTPUT_TYPE_FILENAME
33163 #undef DUK__OUTPUT_TYPE_LINENUMBER
33164 #undef DUK__OUTPUT_TYPE_TRACEBACK
33165 /*
33166  *  Function built-ins
33167  */
33168 
33169 /* #include duk_internal.h -> already included */
33170 
33171 /* Needed even when Function built-in is disabled. */
duk_bi_function_prototype(duk_hthread * thr)33172 DUK_INTERNAL duk_ret_t duk_bi_function_prototype(duk_hthread *thr) {
33173 	/* ignore arguments, return undefined (E5 Section 15.3.4) */
33174 	DUK_UNREF(thr);
33175 	return 0;
33176 }
33177 
33178 #if defined(DUK_USE_FUNCTION_BUILTIN)
duk_bi_function_constructor(duk_hthread * thr)33179 DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_hthread *thr) {
33180 	duk_hstring *h_sourcecode;
33181 	duk_idx_t nargs;
33182 	duk_idx_t i;
33183 	duk_small_uint_t comp_flags;
33184 	duk_hcompfunc *func;
33185 	duk_hobject *outer_lex_env;
33186 	duk_hobject *outer_var_env;
33187 
33188 	/* normal and constructor calls have identical semantics */
33189 
33190 	nargs = duk_get_top(thr);
33191 	for (i = 0; i < nargs; i++) {
33192 		duk_to_string(thr, i);  /* Rejects Symbols during coercion. */
33193 	}
33194 
33195 	if (nargs == 0) {
33196 		duk_push_hstring_empty(thr);
33197 		duk_push_hstring_empty(thr);
33198 	} else if (nargs == 1) {
33199 		/* XXX: cover this with the generic >1 case? */
33200 		duk_push_hstring_empty(thr);
33201 	} else {
33202 		duk_insert(thr, 0);   /* [ arg1 ... argN-1 body] -> [body arg1 ... argN-1] */
33203 		duk_push_literal(thr, ",");
33204 		duk_insert(thr, 1);
33205 		duk_join(thr, nargs - 1);
33206 	}
33207 
33208 	/* [ body formals ], formals is comma separated list that needs to be parsed */
33209 
33210 	DUK_ASSERT_TOP(thr, 2);
33211 
33212 	/* XXX: this placeholder is not always correct, but use for now.
33213 	 * It will fail in corner cases; see test-dev-func-cons-args.js.
33214 	 */
33215 	duk_push_literal(thr, "function(");
33216 	duk_dup_1(thr);
33217 	duk_push_literal(thr, "){");
33218 	duk_dup_0(thr);
33219 	duk_push_literal(thr, "\n}");  /* Newline is important to handle trailing // comment. */
33220 	duk_concat(thr, 5);
33221 
33222 	/* [ body formals source ] */
33223 
33224 	DUK_ASSERT_TOP(thr, 3);
33225 
33226 	/* strictness is not inherited, intentional */
33227 	comp_flags = DUK_COMPILE_FUNCEXPR;
33228 
33229 	duk_push_hstring_stridx(thr, DUK_STRIDX_COMPILE);  /* XXX: copy from caller? */  /* XXX: ignored now */
33230 	h_sourcecode = duk_require_hstring(thr, -2);  /* no symbol check needed; -2 is concat'd code */
33231 	duk_js_compile(thr,
33232 	               (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode),
33233 	               (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode),
33234 	               comp_flags);
33235 
33236 	/* Force .name to 'anonymous' (ES2015). */
33237 	duk_push_literal(thr, "anonymous");
33238 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
33239 
33240 	func = (duk_hcompfunc *) duk_known_hobject(thr, -1);
33241 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) func));
33242 	DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) func));
33243 
33244 	/* [ body formals source template ] */
33245 
33246 	/* only outer_lex_env matters, as functions always get a new
33247 	 * variable declaration environment.
33248 	 */
33249 
33250 	outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
33251 	outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
33252 
33253 	duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 1 /*add_auto_proto*/);
33254 
33255 	/* [ body formals source template closure ] */
33256 
33257 	return 1;
33258 }
33259 #endif  /* DUK_USE_FUNCTION_BUILTIN */
33260 
33261 #if defined(DUK_USE_FUNCTION_BUILTIN)
duk_bi_function_prototype_to_string(duk_hthread * thr)33262 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_to_string(duk_hthread *thr) {
33263 	duk_tval *tv;
33264 
33265 	/*
33266 	 *  E5 Section 15.3.4.2 places few requirements on the output of
33267 	 *  this function: the result is implementation dependent, must
33268 	 *  follow FunctionDeclaration syntax (in particular, must have a
33269 	 *  name even for anonymous functions or functions with empty name).
33270 	 *  The output does NOT need to compile into anything useful.
33271 	 *
33272 	 *  E6 Section 19.2.3.5 changes the requirements completely: the
33273 	 *  result must either eval() to a functionally equivalent object
33274 	 *  OR eval() to a SyntaxError.
33275 	 *
33276 	 *  We opt for the SyntaxError approach for now, with a syntax that
33277 	 *  mimics V8's native function syntax:
33278 	 *
33279 	 *      'function cos() { [native code] }'
33280 	 *
33281 	 *  but extended with [ecmascript code], [bound code], and
33282 	 *  [lightfunc code].
33283 	 */
33284 
33285 	duk_push_this(thr);
33286 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
33287 	DUK_ASSERT(tv != NULL);
33288 
33289 	if (DUK_TVAL_IS_OBJECT(tv)) {
33290 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv);
33291 		const char *func_name;
33292 
33293 		/* Function name: missing/undefined is mapped to empty string,
33294 		 * otherwise coerce to string.  No handling for invalid identifier
33295 		 * characters or e.g. '{' in the function name.  This doesn't
33296 		 * really matter as long as a SyntaxError results.  Technically
33297 		 * if the name contained a suitable prefix followed by '//' it
33298 		 * might cause the result to parse without error.
33299 		 */
33300 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME);
33301 		if (duk_is_undefined(thr, -1)) {
33302 			func_name = "";
33303 		} else {
33304 			func_name = duk_to_string(thr, -1);
33305 			DUK_ASSERT(func_name != NULL);
33306 		}
33307 
33308 		if (DUK_HOBJECT_IS_COMPFUNC(obj)) {
33309 			duk_push_sprintf(thr, "function %s() { [ecmascript code] }", (const char *) func_name);
33310 		} else if (DUK_HOBJECT_IS_NATFUNC(obj)) {
33311 			duk_push_sprintf(thr, "function %s() { [native code] }", (const char *) func_name);
33312 		} else if (DUK_HOBJECT_IS_BOUNDFUNC(obj)) {
33313 			duk_push_sprintf(thr, "function %s() { [bound code] }", (const char *) func_name);
33314 		} else {
33315 			goto type_error;
33316 		}
33317 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
33318 		duk_push_lightfunc_tostring(thr, tv);
33319 	} else {
33320 		goto type_error;
33321 	}
33322 
33323 	return 1;
33324 
33325  type_error:
33326 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
33327 }
33328 #endif
33329 
33330 /* Always present because the native function pointer is needed in call
33331  * handling.
33332  */
duk_bi_function_prototype_call(duk_hthread * thr)33333 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_call(duk_hthread *thr) {
33334 	/* .call() is dealt with in call handling by simulating its
33335 	 * effects so this function is actually never called.
33336 	 */
33337 	DUK_UNREF(thr);
33338 	return DUK_RET_TYPE_ERROR;
33339 }
33340 
duk_bi_function_prototype_apply(duk_hthread * thr)33341 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_apply(duk_hthread *thr) {
33342 	/* Like .call(), never actually called. */
33343 	DUK_UNREF(thr);
33344 	return DUK_RET_TYPE_ERROR;
33345 }
33346 
duk_bi_reflect_apply(duk_hthread * thr)33347 DUK_INTERNAL duk_ret_t duk_bi_reflect_apply(duk_hthread *thr) {
33348 	/* Like .call(), never actually called. */
33349 	DUK_UNREF(thr);
33350 	return DUK_RET_TYPE_ERROR;
33351 }
33352 
duk_bi_reflect_construct(duk_hthread * thr)33353 DUK_INTERNAL duk_ret_t duk_bi_reflect_construct(duk_hthread *thr) {
33354 	/* Like .call(), never actually called. */
33355 	DUK_UNREF(thr);
33356 	return DUK_RET_TYPE_ERROR;
33357 }
33358 
33359 #if defined(DUK_USE_FUNCTION_BUILTIN)
33360 /* Create a bound function which points to a target function which may
33361  * be bound or non-bound.  If the target is bound, the argument lists
33362  * and 'this' binding of the functions are merged and the resulting
33363  * function points directly to the non-bound target.
33364  */
duk_bi_function_prototype_bind(duk_hthread * thr)33365 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) {
33366 	duk_hboundfunc *h_bound;
33367 	duk_idx_t nargs;  /* bound args, not counting 'this' binding */
33368 	duk_idx_t bound_nargs;
33369 	duk_int_t bound_len;
33370 	duk_tval *tv_prevbound;
33371 	duk_idx_t n_prevbound;
33372 	duk_tval *tv_res;
33373 	duk_tval *tv_tmp;
33374 
33375 	/* XXX: C API call, e.g. duk_push_bound_function(thr, target_idx, nargs); */
33376 
33377 	/* Vararg function, careful arg handling, e.g. thisArg may not
33378 	 * be present.
33379 	 */
33380 	nargs = duk_get_top(thr) - 1;  /* actual args, not counting 'this' binding */
33381 	if (nargs < 0) {
33382 		nargs++;
33383 		duk_push_undefined(thr);
33384 	}
33385 	DUK_ASSERT(nargs >= 0);
33386 
33387 	/* Limit 'nargs' for bound functions to guarantee arithmetic
33388 	 * below will never wrap.
33389 	 */
33390 	if (nargs > (duk_idx_t) DUK_HBOUNDFUNC_MAX_ARGS) {
33391 		DUK_DCERROR_RANGE_INVALID_COUNT(thr);
33392 	}
33393 
33394 	duk_push_this(thr);
33395 	duk_require_callable(thr, -1);
33396 
33397 	/* [ thisArg arg1 ... argN func ]  (thisArg+args == nargs+1 total) */
33398 	DUK_ASSERT_TOP(thr, nargs + 2);
33399 
33400 	/* Create bound function object. */
33401 	h_bound = duk_push_hboundfunc(thr);
33402 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&h_bound->target));
33403 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&h_bound->this_binding));
33404 	DUK_ASSERT(h_bound->args == NULL);
33405 	DUK_ASSERT(h_bound->nargs == 0);
33406 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_bound) == NULL);
33407 
33408 	/* [ thisArg arg1 ... argN func boundFunc ] */
33409 
33410 	/* If the target is a bound function, argument lists must be
33411 	 * merged.  The 'this' binding closest to the target function
33412 	 * wins because in call handling the 'this' gets replaced over
33413 	 * and over again until we call the non-bound function.
33414 	 */
33415 	tv_prevbound = NULL;
33416 	n_prevbound = 0;
33417 	tv_tmp = DUK_GET_TVAL_POSIDX(thr, 0);
33418 	DUK_TVAL_SET_TVAL(&h_bound->this_binding, tv_tmp);
33419 	tv_tmp = DUK_GET_TVAL_NEGIDX(thr, -2);
33420 	DUK_TVAL_SET_TVAL(&h_bound->target, tv_tmp);
33421 
33422 	if (DUK_TVAL_IS_OBJECT(tv_tmp)) {
33423 		duk_hobject *h_target;
33424 		duk_hobject *bound_proto;
33425 
33426 		h_target = DUK_TVAL_GET_OBJECT(tv_tmp);
33427 		DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(h_target));
33428 
33429 		/* Internal prototype must be copied from the target.
33430 		 * For lightfuncs Function.prototype is used and is already
33431 		 * in place.
33432 		 */
33433 		bound_proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_target);
33434 		DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) h_bound, bound_proto);
33435 
33436 		/* The 'strict' flag is copied to get the special [[Get]] of E5.1
33437 		 * Section 15.3.5.4 to apply when a 'caller' value is a strict bound
33438 		 * function.  Not sure if this is correct, because the specification
33439 		 * is a bit ambiguous on this point but it would make sense.
33440 		 */
33441 		/* Strictness is inherited from target. */
33442 		if (DUK_HOBJECT_HAS_STRICT(h_target)) {
33443 			DUK_HOBJECT_SET_STRICT((duk_hobject *) h_bound);
33444 		}
33445 
33446 		if (DUK_HOBJECT_HAS_BOUNDFUNC(h_target)) {
33447 			duk_hboundfunc *h_boundtarget;
33448 
33449 			h_boundtarget = (duk_hboundfunc *) (void *) h_target;
33450 
33451 			/* The final function should always be non-bound, unless
33452 			 * there's a bug in the internals.  Assert for it.
33453 			 */
33454 			DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&h_boundtarget->target) ||
33455 			           (DUK_TVAL_IS_OBJECT(&h_boundtarget->target) &&
33456 			            DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(&h_boundtarget->target)) &&
33457 			            !DUK_HOBJECT_IS_BOUNDFUNC(DUK_TVAL_GET_OBJECT(&h_boundtarget->target))));
33458 
33459 			DUK_TVAL_SET_TVAL(&h_bound->target, &h_boundtarget->target);
33460 			DUK_TVAL_SET_TVAL(&h_bound->this_binding, &h_boundtarget->this_binding);
33461 
33462 			tv_prevbound = h_boundtarget->args;
33463 			n_prevbound = h_boundtarget->nargs;
33464 		}
33465 	} else {
33466 		/* Lightfuncs are always strict. */
33467 		duk_hobject *bound_proto;
33468 
33469 		DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_tmp));
33470 		DUK_HOBJECT_SET_STRICT((duk_hobject *) h_bound);
33471 		bound_proto = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
33472 		DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) h_bound, bound_proto);
33473 	}
33474 
33475 	DUK_TVAL_INCREF(thr, &h_bound->target);  /* old values undefined, no decref needed */
33476 	DUK_TVAL_INCREF(thr, &h_bound->this_binding);
33477 
33478 	bound_nargs = n_prevbound + nargs;
33479 	if (bound_nargs > (duk_idx_t) DUK_HBOUNDFUNC_MAX_ARGS) {
33480 		DUK_DCERROR_RANGE_INVALID_COUNT(thr);
33481 	}
33482 	tv_res = (duk_tval *) DUK_ALLOC_CHECKED(thr, ((duk_size_t) bound_nargs) * sizeof(duk_tval));
33483 	DUK_ASSERT(tv_res != NULL || bound_nargs == 0);
33484 	DUK_ASSERT(h_bound->args == NULL);
33485 	DUK_ASSERT(h_bound->nargs == 0);
33486 	h_bound->args = tv_res;
33487 	h_bound->nargs = bound_nargs;
33488 
33489 	DUK_ASSERT(n_prevbound >= 0);
33490 	duk_copy_tvals_incref(thr, tv_res, tv_prevbound, (duk_size_t) n_prevbound);
33491 	DUK_ASSERT(nargs >= 0);
33492 	duk_copy_tvals_incref(thr, tv_res + n_prevbound, DUK_GET_TVAL_POSIDX(thr, 1), (duk_size_t) nargs);
33493 
33494 	/* [ thisArg arg1 ... argN func boundFunc ] */
33495 
33496 	/* Bound function 'length' property is interesting.
33497 	 * For lightfuncs, simply read the virtual property.
33498 	 */
33499 	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH);
33500 	bound_len = duk_get_int(thr, -1);  /* ES2015: no coercion */
33501 	if (bound_len < nargs) {
33502 		bound_len = 0;
33503 	} else {
33504 		bound_len -= nargs;
33505 	}
33506 	if (sizeof(duk_int_t) > 4 && bound_len > (duk_int_t) DUK_UINT32_MAX) {
33507 		bound_len = (duk_int_t) DUK_UINT32_MAX;
33508 	}
33509 	duk_pop(thr);
33510 	DUK_ASSERT(bound_len >= 0);
33511 	tv_tmp = thr->valstack_top++;
33512 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_tmp));
33513 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv_tmp));
33514 	DUK_TVAL_SET_U32(tv_tmp, (duk_uint32_t) bound_len);  /* in-place update, fastint */
33515 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);  /* attrs in E6 Section 9.2.4 */
33516 
33517 	/* XXX: could these be virtual? */
33518 	/* Caller and arguments must use the same thrower, [[ThrowTypeError]]. */
33519 	duk_xdef_prop_stridx_thrower(thr, -1, DUK_STRIDX_CALLER);
33520 	duk_xdef_prop_stridx_thrower(thr, -1, DUK_STRIDX_LC_ARGUMENTS);
33521 
33522 	/* Function name and fileName (non-standard). */
33523 	duk_push_literal(thr, "bound ");  /* ES2015 19.2.3.2. */
33524 	duk_get_prop_stridx(thr, -3, DUK_STRIDX_NAME);
33525 	if (!duk_is_string_notsymbol(thr, -1)) {
33526 		/* ES2015 has requirement to check that .name of target is a string
33527 		 * (also must check for Symbol); if not, targetName should be the
33528 		 * empty string.  ES2015 19.2.3.2.
33529 		 */
33530 		duk_pop(thr);
33531 		duk_push_hstring_empty(thr);
33532 	}
33533 	duk_concat(thr, 2);
33534 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
33535 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
33536 	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME);
33537 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C);
33538 #endif
33539 
33540 	DUK_DDD(DUK_DDDPRINT("created bound function: %!iT", (duk_tval *) duk_get_tval(thr, -1)));
33541 
33542 	return 1;
33543 }
33544 #endif  /* DUK_USE_FUNCTION_BUILTIN */
33545 
33546 /* %NativeFunctionPrototype% .length getter. */
duk_bi_native_function_length(duk_hthread * thr)33547 DUK_INTERNAL duk_ret_t duk_bi_native_function_length(duk_hthread *thr) {
33548 	duk_tval *tv;
33549 	duk_hnatfunc *h;
33550 	duk_int16_t func_nargs;
33551 
33552 	tv = duk_get_borrowed_this_tval(thr);
33553 	DUK_ASSERT(tv != NULL);
33554 
33555 	if (DUK_TVAL_IS_OBJECT(tv)) {
33556 		h = (duk_hnatfunc *) DUK_TVAL_GET_OBJECT(tv);
33557 		DUK_ASSERT(h != NULL);
33558 		if (!DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h)) {
33559 			goto fail_type;
33560 		}
33561 		func_nargs = h->nargs;
33562 		duk_push_int(thr, func_nargs == DUK_HNATFUNC_NARGS_VARARGS ? 0 : func_nargs);
33563 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
33564 		duk_small_uint_t lf_flags;
33565 		duk_small_uint_t lf_len;
33566 
33567 		lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
33568 		lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
33569 		duk_push_uint(thr, lf_len);
33570 	} else {
33571 		goto fail_type;
33572 	}
33573 	return 1;
33574 
33575  fail_type:
33576 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
33577 }
33578 
33579 /* %NativeFunctionPrototype% .name getter. */
duk_bi_native_function_name(duk_hthread * thr)33580 DUK_INTERNAL duk_ret_t duk_bi_native_function_name(duk_hthread *thr) {
33581 	duk_tval *tv;
33582 	duk_hnatfunc *h;
33583 
33584 	tv = duk_get_borrowed_this_tval(thr);
33585 	DUK_ASSERT(tv != NULL);
33586 
33587 	if (DUK_TVAL_IS_OBJECT(tv)) {
33588 		h = (duk_hnatfunc *) DUK_TVAL_GET_OBJECT(tv);
33589 		DUK_ASSERT(h != NULL);
33590 		if (!DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h)) {
33591 			goto fail_type;
33592 		}
33593 #if 0
33594 		duk_push_hnatfunc_name(thr, h);
33595 #endif
33596 		duk_push_hstring_empty(thr);
33597 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
33598 		duk_push_lightfunc_name(thr, tv);
33599 	} else {
33600 		goto fail_type;
33601 	}
33602 	return 1;
33603 
33604  fail_type:
33605 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
33606 }
33607 
33608 #if defined(DUK_USE_SYMBOL_BUILTIN)
duk_bi_function_prototype_hasinstance(duk_hthread * thr)33609 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_hasinstance(duk_hthread *thr) {
33610 	/* This binding: RHS, stack index 0: LHS. */
33611 	duk_bool_t ret;
33612 
33613 	ret = duk_js_instanceof_ordinary(thr, DUK_GET_TVAL_POSIDX(thr, 0), DUK_GET_THIS_TVAL_PTR(thr));
33614 	duk_push_boolean(thr, ret);
33615 	return 1;
33616 }
33617 #endif  /* DUK_USE_SYMBOL_BUILTIN */
33618 /*
33619  *  Global object built-ins
33620  */
33621 
33622 /* #include duk_internal.h -> already included */
33623 
33624 /*
33625  *  Encoding/decoding helpers
33626  */
33627 
33628 /* XXX: Could add fast path (for each transform callback) with direct byte
33629  * lookups (no shifting) and no explicit check for x < 0x80 before table
33630  * lookup.
33631  */
33632 
33633 /* Macros for creating and checking bitmasks for character encoding.
33634  * Bit number is a bit counterintuitive, but minimizes code size.
33635  */
33636 #define DUK__MKBITS(a,b,c,d,e,f,g,h)  ((duk_uint8_t) ( \
33637 	((a) << 0) | ((b) << 1) | ((c) << 2) | ((d) << 3) | \
33638 	((e) << 4) | ((f) << 5) | ((g) << 6) | ((h) << 7) \
33639 	))
33640 #define DUK__CHECK_BITMASK(table,cp)  ((table)[(cp) >> 3] & (1 << ((cp) & 0x07)))
33641 
33642 /* E5.1 Section 15.1.3.3: uriReserved + uriUnescaped + '#' */
33643 DUK_LOCAL const duk_uint8_t duk__encode_uriunescaped_table[16] = {
33644 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
33645 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
33646 	DUK__MKBITS(0, 1, 0, 1, 1, 0, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x20-0x2f */
33647 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 0, 1, 0, 1),  /* 0x30-0x3f */
33648 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
33649 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
33650 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
33651 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0),  /* 0x70-0x7f */
33652 };
33653 
33654 /* E5.1 Section 15.1.3.4: uriUnescaped */
33655 DUK_LOCAL const duk_uint8_t duk__encode_uricomponent_unescaped_table[16] = {
33656 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
33657 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
33658 	DUK__MKBITS(0, 1, 0, 0, 0, 0, 0, 1), DUK__MKBITS(1, 1, 1, 0, 0, 1, 1, 0),  /* 0x20-0x2f */
33659 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
33660 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
33661 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
33662 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
33663 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0),  /* 0x70-0x7f */
33664 };
33665 
33666 /* E5.1 Section 15.1.3.1: uriReserved + '#' */
33667 DUK_LOCAL const duk_uint8_t duk__decode_uri_reserved_table[16] = {
33668 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
33669 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
33670 	DUK__MKBITS(0, 0, 0, 1, 1, 0, 1, 0), DUK__MKBITS(0, 0, 0, 1, 1, 0, 0, 1),  /* 0x20-0x2f */
33671 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 0, 1),  /* 0x30-0x3f */
33672 	DUK__MKBITS(1, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x40-0x4f */
33673 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x50-0x5f */
33674 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x60-0x6f */
33675 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x70-0x7f */
33676 };
33677 
33678 /* E5.1 Section 15.1.3.2: empty */
33679 DUK_LOCAL const duk_uint8_t duk__decode_uri_component_reserved_table[16] = {
33680 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
33681 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
33682 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x20-0x2f */
33683 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
33684 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x40-0x4f */
33685 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x50-0x5f */
33686 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x60-0x6f */
33687 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x70-0x7f */
33688 };
33689 
33690 #if defined(DUK_USE_SECTION_B)
33691 /* E5.1 Section B.2.2, step 7. */
33692 DUK_LOCAL const duk_uint8_t duk__escape_unescaped_table[16] = {
33693 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
33694 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
33695 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 1, 1),  /* 0x20-0x2f */
33696 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
33697 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
33698 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
33699 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
33700 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 0)   /* 0x70-0x7f */
33701 };
33702 #endif  /* DUK_USE_SECTION_B */
33703 
33704 typedef struct {
33705 	duk_hthread *thr;
33706 	duk_hstring *h_str;
33707 	duk_bufwriter_ctx bw;
33708 	const duk_uint8_t *p;
33709 	const duk_uint8_t *p_start;
33710 	const duk_uint8_t *p_end;
33711 } duk__transform_context;
33712 
33713 typedef void (*duk__transform_callback)(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp);
33714 
33715 /* XXX: refactor and share with other code */
duk__decode_hex_escape(const duk_uint8_t * p,duk_small_int_t n)33716 DUK_LOCAL duk_small_int_t duk__decode_hex_escape(const duk_uint8_t *p, duk_small_int_t n) {
33717 	duk_small_int_t ch;
33718 	duk_small_int_t t = 0;
33719 
33720 	while (n > 0) {
33721 		t = t * 16;
33722 		ch = (duk_small_int_t) duk_hex_dectab[*p++];
33723 		if (DUK_LIKELY(ch >= 0)) {
33724 			t += ch;
33725 		} else {
33726 			return -1;
33727 		}
33728 		n--;
33729 	}
33730 	return t;
33731 }
33732 
duk__transform_helper(duk_hthread * thr,duk__transform_callback callback,const void * udata)33733 DUK_LOCAL int duk__transform_helper(duk_hthread *thr, duk__transform_callback callback, const void *udata) {
33734 	duk__transform_context tfm_ctx_alloc;
33735 	duk__transform_context *tfm_ctx = &tfm_ctx_alloc;
33736 	duk_codepoint_t cp;
33737 
33738 	tfm_ctx->thr = thr;
33739 
33740 	tfm_ctx->h_str = duk_to_hstring(thr, 0);
33741 	DUK_ASSERT(tfm_ctx->h_str != NULL);
33742 
33743 	DUK_BW_INIT_PUSHBUF(thr, &tfm_ctx->bw, DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str));  /* initial size guess */
33744 
33745 	tfm_ctx->p_start = DUK_HSTRING_GET_DATA(tfm_ctx->h_str);
33746 	tfm_ctx->p_end = tfm_ctx->p_start + DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str);
33747 	tfm_ctx->p = tfm_ctx->p_start;
33748 
33749 	while (tfm_ctx->p < tfm_ctx->p_end) {
33750 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end);
33751 		callback(tfm_ctx, udata, cp);
33752 	}
33753 
33754 	DUK_BW_COMPACT(thr, &tfm_ctx->bw);
33755 
33756 	(void) duk_buffer_to_string(thr, -1);  /* Safe if transform is safe. */
33757 	return 1;
33758 }
33759 
duk__transform_callback_encode_uri(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)33760 DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
33761 	duk_uint8_t xutf8_buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
33762 	duk_small_int_t len;
33763 	duk_codepoint_t cp1, cp2;
33764 	duk_small_int_t i, t;
33765 	const duk_uint8_t *unescaped_table = (const duk_uint8_t *) udata;
33766 
33767 	/* UTF-8 encoded bytes escaped as %xx%xx%xx... -> 3 * nbytes.
33768 	 * Codepoint range is restricted so this is a slightly too large
33769 	 * but doesn't matter.
33770 	 */
33771 	DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 3 * DUK_UNICODE_MAX_XUTF8_LENGTH);
33772 
33773 	if (cp < 0) {
33774 		goto uri_error;
33775 	} else if ((cp < 0x80L) && DUK__CHECK_BITMASK(unescaped_table, cp)) {
33776 		DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
33777 		return;
33778 	} else if (cp >= 0xdc00L && cp <= 0xdfffL) {
33779 		goto uri_error;
33780 	} else if (cp >= 0xd800L && cp <= 0xdbffL) {
33781 		/* Needs lookahead */
33782 		if (duk_unicode_decode_xutf8(tfm_ctx->thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end, (duk_ucodepoint_t *) &cp2) == 0) {
33783 			goto uri_error;
33784 		}
33785 		if (!(cp2 >= 0xdc00L && cp2 <= 0xdfffL)) {
33786 			goto uri_error;
33787 		}
33788 		cp1 = cp;
33789 		cp = (duk_codepoint_t) (((cp1 - 0xd800L) << 10) + (cp2 - 0xdc00L) + 0x10000L);
33790 	} else if (cp > 0x10ffffL) {
33791 		/* Although we can allow non-BMP characters (they'll decode
33792 		 * back into surrogate pairs), we don't allow extended UTF-8
33793 		 * characters; they would encode to URIs which won't decode
33794 		 * back because of strict UTF-8 checks in URI decoding.
33795 		 * (However, we could just as well allow them here.)
33796 		 */
33797 		goto uri_error;
33798 	} else {
33799 		/* Non-BMP characters within valid UTF-8 range: encode as is.
33800 		 * They'll decode back into surrogate pairs if the escaped
33801 		 * output is decoded.
33802 		 */
33803 		;
33804 	}
33805 
33806 	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) cp, xutf8_buf);
33807 	for (i = 0; i < len; i++) {
33808 		t = (duk_small_int_t) xutf8_buf[i];
33809 		DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
33810 		                      &tfm_ctx->bw,
33811 		                      DUK_ASC_PERCENT,
33812 		                      (duk_uint8_t) duk_uc_nybbles[t >> 4],
33813                                       (duk_uint8_t) duk_uc_nybbles[t & 0x0f]);
33814 	}
33815 
33816 	return;
33817 
33818  uri_error:
33819 	DUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
33820 	DUK_WO_NORETURN(return;);
33821 }
33822 
duk__transform_callback_decode_uri(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)33823 DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
33824 	const duk_uint8_t *reserved_table = (const duk_uint8_t *) udata;
33825 	duk_small_uint_t utf8_blen;
33826 	duk_codepoint_t min_cp;
33827 	duk_small_int_t t;  /* must be signed */
33828 	duk_small_uint_t i;
33829 
33830 	/* Maximum write size: XUTF8 path writes max DUK_UNICODE_MAX_XUTF8_LENGTH,
33831 	 * percent escape path writes max two times CESU-8 encoded BMP length.
33832 	 */
33833 	DUK_BW_ENSURE(tfm_ctx->thr,
33834 	              &tfm_ctx->bw,
33835 	              (DUK_UNICODE_MAX_XUTF8_LENGTH >= 2 * DUK_UNICODE_MAX_CESU8_BMP_LENGTH ?
33836 	              DUK_UNICODE_MAX_XUTF8_LENGTH : DUK_UNICODE_MAX_CESU8_BMP_LENGTH));
33837 
33838 	if (cp == (duk_codepoint_t) '%') {
33839 		const duk_uint8_t *p = tfm_ctx->p;
33840 		duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p);  /* bytes left */
33841 
33842 		DUK_DDD(DUK_DDDPRINT("percent encoding, left=%ld", (long) left));
33843 
33844 		if (left < 2) {
33845 			goto uri_error;
33846 		}
33847 
33848 		t = duk__decode_hex_escape(p, 2);
33849 		DUK_DDD(DUK_DDDPRINT("first byte: %ld", (long) t));
33850 		if (t < 0) {
33851 			goto uri_error;
33852 		}
33853 
33854 		if (t < 0x80) {
33855 			if (DUK__CHECK_BITMASK(reserved_table, t)) {
33856 				/* decode '%xx' to '%xx' if decoded char in reserved set */
33857 				DUK_ASSERT(tfm_ctx->p - 1 >= tfm_ctx->p_start);
33858 				DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
33859 				                      &tfm_ctx->bw,
33860 				                      DUK_ASC_PERCENT,
33861 				                      p[0],
33862 				                      p[1]);
33863 			} else {
33864 				DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) t);
33865 			}
33866 			tfm_ctx->p += 2;
33867 			return;
33868 		}
33869 
33870 		/* Decode UTF-8 codepoint from a sequence of hex escapes.  The
33871 		 * first byte of the sequence has been decoded to 't'.
33872 		 *
33873 		 * Note that UTF-8 validation must be strict according to the
33874 		 * specification: E5.1 Section 15.1.3, decode algorithm step
33875 		 * 4.d.vii.8.  URIError from non-shortest encodings is also
33876 		 * specifically noted in the spec.
33877 		 */
33878 
33879 		DUK_ASSERT(t >= 0x80);
33880 		if (t < 0xc0) {
33881 			/* continuation byte */
33882 			goto uri_error;
33883 		} else if (t < 0xe0) {
33884 			/* 110x xxxx; 2 bytes */
33885 			utf8_blen = 2;
33886 			min_cp = 0x80L;
33887 			cp = t & 0x1f;
33888 		} else if (t < 0xf0) {
33889 			/* 1110 xxxx; 3 bytes */
33890 			utf8_blen = 3;
33891 			min_cp = 0x800L;
33892 			cp = t & 0x0f;
33893 		} else if (t < 0xf8) {
33894 			/* 1111 0xxx; 4 bytes */
33895 			utf8_blen = 4;
33896 			min_cp = 0x10000L;
33897 			cp = t & 0x07;
33898 		} else {
33899 			/* extended utf-8 not allowed for URIs */
33900 			goto uri_error;
33901 		}
33902 
33903 		if (left < utf8_blen * 3 - 1) {
33904 			/* '%xx%xx...%xx', p points to char after first '%' */
33905 			goto uri_error;
33906 		}
33907 
33908 		p += 3;
33909 		for (i = 1; i < utf8_blen; i++) {
33910 			/* p points to digit part ('%xy', p points to 'x') */
33911 			t = duk__decode_hex_escape(p, 2);
33912 			DUK_DDD(DUK_DDDPRINT("i=%ld utf8_blen=%ld cp=%ld t=0x%02lx",
33913 			                     (long) i, (long) utf8_blen, (long) cp, (unsigned long) t));
33914 			if (t < 0) {
33915 				goto uri_error;
33916 			}
33917 			if ((t & 0xc0) != 0x80) {
33918 				goto uri_error;
33919 			}
33920 			cp = (cp << 6) + (t & 0x3f);
33921 			p += 3;
33922 		}
33923 		p--;  /* p overshoots */
33924 		tfm_ctx->p = p;
33925 
33926 		DUK_DDD(DUK_DDDPRINT("final cp=%ld, min_cp=%ld", (long) cp, (long) min_cp));
33927 
33928 		if (cp < min_cp || cp > 0x10ffffL || (cp >= 0xd800L && cp <= 0xdfffL)) {
33929 			goto uri_error;
33930 		}
33931 
33932 		/* The E5.1 algorithm checks whether or not a decoded codepoint
33933 		 * is below 0x80 and perhaps may be in the "reserved" set.
33934 		 * This seems pointless because the single byte UTF-8 case is
33935 		 * handled separately, and non-shortest encodings are rejected.
33936 		 * So, 'cp' cannot be below 0x80 here, and thus cannot be in
33937 		 * the reserved set.
33938 		 */
33939 
33940 		/* utf-8 validation ensures these */
33941 		DUK_ASSERT(cp >= 0x80L && cp <= 0x10ffffL);
33942 
33943 		if (cp >= 0x10000L) {
33944 			cp -= 0x10000L;
33945 			DUK_ASSERT(cp < 0x100000L);
33946 
33947 			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp >> 10) + 0xd800L));
33948 			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp & 0x03ffL) + 0xdc00L));
33949 		} else {
33950 			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
33951 		}
33952 	} else {
33953 		DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
33954 	}
33955 	return;
33956 
33957  uri_error:
33958 	DUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
33959 	DUK_WO_NORETURN(return;);
33960 }
33961 
33962 #if defined(DUK_USE_SECTION_B)
duk__transform_callback_escape(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)33963 DUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
33964 	DUK_UNREF(udata);
33965 
33966 	DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 6);
33967 
33968 	if (cp < 0) {
33969 		goto esc_error;
33970 	} else if ((cp < 0x80L) && DUK__CHECK_BITMASK(duk__escape_unescaped_table, cp)) {
33971 		DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
33972 	} else if (cp < 0x100L) {
33973 		DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
33974 		                      &tfm_ctx->bw,
33975 		                      (duk_uint8_t) DUK_ASC_PERCENT,
33976 		                      (duk_uint8_t) duk_uc_nybbles[cp >> 4],
33977 		                      (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
33978 	} else if (cp < 0x10000L) {
33979 		DUK_BW_WRITE_RAW_U8_6(tfm_ctx->thr,
33980 		                      &tfm_ctx->bw,
33981 		                      (duk_uint8_t) DUK_ASC_PERCENT,
33982 		                      (duk_uint8_t) DUK_ASC_LC_U,
33983 		                      (duk_uint8_t) duk_uc_nybbles[cp >> 12],
33984 		                      (duk_uint8_t) duk_uc_nybbles[(cp >> 8) & 0x0f],
33985 		                      (duk_uint8_t) duk_uc_nybbles[(cp >> 4) & 0x0f],
33986 		                      (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
33987 	} else {
33988 		/* Characters outside BMP cannot be escape()'d.  We could
33989 		 * encode them as surrogate pairs (for codepoints inside
33990 		 * valid UTF-8 range, but not extended UTF-8).  Because
33991 		 * escape() and unescape() are legacy functions, we don't.
33992 		 */
33993 		goto esc_error;
33994 	}
33995 
33996 	return;
33997 
33998  esc_error:
33999 	DUK_ERROR_TYPE(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
34000 	DUK_WO_NORETURN(return;);
34001 }
34002 
duk__transform_callback_unescape(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)34003 DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
34004 	duk_small_int_t t;
34005 
34006 	DUK_UNREF(udata);
34007 
34008 	if (cp == (duk_codepoint_t) '%') {
34009 		const duk_uint8_t *p = tfm_ctx->p;
34010 		duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p);  /* bytes left */
34011 
34012 		if (left >= 5 && p[0] == 'u' &&
34013 		    ((t = duk__decode_hex_escape(p + 1, 4)) >= 0)) {
34014 			cp = (duk_codepoint_t) t;
34015 			tfm_ctx->p += 5;
34016 		} else if (left >= 2 &&
34017 		           ((t = duk__decode_hex_escape(p, 2)) >= 0)) {
34018 			cp = (duk_codepoint_t) t;
34019 			tfm_ctx->p += 2;
34020 		}
34021 	}
34022 
34023 	DUK_BW_WRITE_ENSURE_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
34024 }
34025 #endif  /* DUK_USE_SECTION_B */
34026 
34027 /*
34028  *  Eval
34029  *
34030  *  Eval needs to handle both a "direct eval" and an "indirect eval".
34031  *  Direct eval handling needs access to the caller's activation so that its
34032  *  lexical environment can be accessed.  A direct eval is only possible from
34033  *  ECMAScript code; an indirect eval call is possible also from C code.
34034  *  When an indirect eval call is made from C code, there may not be a
34035  *  calling activation at all which needs careful handling.
34036  */
34037 
duk_bi_global_object_eval(duk_hthread * thr)34038 DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_hthread *thr) {
34039 	duk_hstring *h;
34040 	duk_activation *act_caller;
34041 	duk_activation *act_eval;
34042 	duk_hcompfunc *func;
34043 	duk_hobject *outer_lex_env;
34044 	duk_hobject *outer_var_env;
34045 	duk_bool_t this_to_global = 1;
34046 	duk_small_uint_t comp_flags;
34047 	duk_int_t level = -2;
34048 	duk_small_uint_t call_flags;
34049 
34050 	DUK_ASSERT(duk_get_top(thr) == 1 || duk_get_top(thr) == 2);  /* 2 when called by debugger */
34051 	DUK_ASSERT(thr->callstack_top >= 1);  /* at least this function exists */
34052 	DUK_ASSERT(thr->callstack_curr != NULL);
34053 	DUK_ASSERT((thr->callstack_curr->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0 || /* indirect eval */
34054 	           (thr->callstack_top >= 2));  /* if direct eval, calling activation must exist */
34055 
34056 	/*
34057 	 *  callstack_top - 1 --> this function
34058 	 *  callstack_top - 2 --> caller (may not exist)
34059 	 *
34060 	 *  If called directly from C, callstack_top might be 1.  If calling
34061 	 *  activation doesn't exist, call must be indirect.
34062 	 */
34063 
34064 	h = duk_get_hstring_notsymbol(thr, 0);
34065 	if (!h) {
34066 		/* Symbol must be returned as is, like any non-string values. */
34067 		return 1;  /* return arg as-is */
34068 	}
34069 
34070 #if defined(DUK_USE_DEBUGGER_SUPPORT)
34071 	/* NOTE: level is used only by the debugger and should never be present
34072 	 * for an ECMAScript eval().
34073 	 */
34074 	DUK_ASSERT(level == -2);  /* by default, use caller's environment */
34075 	if (duk_get_top(thr) >= 2 && duk_is_number(thr, 1)) {
34076 		level = duk_get_int(thr, 1);
34077 	}
34078 	DUK_ASSERT(level <= -2);  /* This is guaranteed by debugger code. */
34079 #endif
34080 
34081 	/* [ source ] */
34082 
34083 	comp_flags = DUK_COMPILE_EVAL;
34084 	act_eval = thr->callstack_curr;  /* this function */
34085 	DUK_ASSERT(act_eval != NULL);
34086 	act_caller = duk_hthread_get_activation_for_level(thr, level);
34087 	if (act_caller != NULL) {
34088 		/* Have a calling activation, check for direct eval (otherwise
34089 		 * assume indirect eval.
34090 		 */
34091 		if ((act_caller->flags & DUK_ACT_FLAG_STRICT) &&
34092 		    (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL)) {
34093 			/* Only direct eval inherits strictness from calling code
34094 			 * (E5.1 Section 10.1.1).
34095 			 */
34096 			comp_flags |= DUK_COMPILE_STRICT;
34097 		}
34098 	} else {
34099 		DUK_ASSERT((act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0);
34100 	}
34101 
34102 	duk_push_hstring_stridx(thr, DUK_STRIDX_INPUT);  /* XXX: copy from caller? */
34103 	duk_js_compile(thr,
34104 	               (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h),
34105 	               (duk_size_t) DUK_HSTRING_GET_BYTELEN(h),
34106 	               comp_flags);
34107 	func = (duk_hcompfunc *) duk_known_hobject(thr, -1);
34108 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) func));
34109 
34110 	/* [ source template ] */
34111 
34112 	/* E5 Section 10.4.2 */
34113 
34114 	if (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
34115 		DUK_ASSERT(thr->callstack_top >= 2);
34116 		DUK_ASSERT(act_caller != NULL);
34117 		if (act_caller->lex_env == NULL) {
34118 			DUK_ASSERT(act_caller->var_env == NULL);
34119 			DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
34120 
34121 			/* this may have side effects, so re-lookup act */
34122 			duk_js_init_activation_environment_records_delayed(thr, act_caller);
34123 		}
34124 		DUK_ASSERT(act_caller->lex_env != NULL);
34125 		DUK_ASSERT(act_caller->var_env != NULL);
34126 
34127 		this_to_global = 0;
34128 
34129 		if (DUK_HOBJECT_HAS_STRICT((duk_hobject *) func)) {
34130 			duk_hdecenv *new_env;
34131 			duk_hobject *act_lex_env;
34132 
34133 			DUK_DDD(DUK_DDDPRINT("direct eval call to a strict function -> "
34134 			                     "var_env and lex_env to a fresh env, "
34135 			                     "this_binding to caller's this_binding"));
34136 
34137 			act_lex_env = act_caller->lex_env;
34138 
34139 			new_env = duk_hdecenv_alloc(thr,
34140 			                            DUK_HOBJECT_FLAG_EXTENSIBLE |
34141 			                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
34142 			DUK_ASSERT(new_env != NULL);
34143 			duk_push_hobject(thr, (duk_hobject *) new_env);
34144 
34145 			DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
34146 			DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, act_lex_env);
34147 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, act_lex_env);
34148 			DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
34149 
34150 			outer_lex_env = (duk_hobject *) new_env;
34151 			outer_var_env = (duk_hobject *) new_env;
34152 
34153 			duk_insert(thr, 0);  /* stash to bottom of value stack to keep new_env reachable for duration of eval */
34154 
34155 			/* compiler's responsibility */
34156 			DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));
34157 		} else {
34158 			DUK_DDD(DUK_DDDPRINT("direct eval call to a non-strict function -> "
34159 			                     "var_env and lex_env to caller's envs, "
34160 			                     "this_binding to caller's this_binding"));
34161 
34162 			outer_lex_env = act_caller->lex_env;
34163 			outer_var_env = act_caller->var_env;
34164 
34165 			/* compiler's responsibility */
34166 			DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));
34167 		}
34168 	} else {
34169 		DUK_DDD(DUK_DDDPRINT("indirect eval call -> var_env and lex_env to "
34170 		                     "global object, this_binding to global object"));
34171 
34172 		this_to_global = 1;
34173 		outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
34174 		outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
34175 	}
34176 
34177 	/* Eval code doesn't need an automatic .prototype object. */
34178 	duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 0 /*add_auto_proto*/);
34179 
34180 	/* [ env? source template closure ] */
34181 
34182 	if (this_to_global) {
34183 		DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
34184 		duk_push_hobject_bidx(thr, DUK_BIDX_GLOBAL);
34185 	} else {
34186 		duk_tval *tv;
34187 		DUK_ASSERT(thr->callstack_top >= 2);
34188 		DUK_ASSERT(act_caller != NULL);
34189 		tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act_caller->bottom_byteoff - sizeof(duk_tval));  /* this is just beneath bottom */
34190 		DUK_ASSERT(tv >= thr->valstack);
34191 		duk_push_tval(thr, tv);
34192 	}
34193 
34194 	DUK_DDD(DUK_DDDPRINT("eval -> lex_env=%!iO, var_env=%!iO, this_binding=%!T",
34195 	                     (duk_heaphdr *) outer_lex_env,
34196 	                     (duk_heaphdr *) outer_var_env,
34197 	                     duk_get_tval(thr, -1)));
34198 
34199 	/* [ env? source template closure this ] */
34200 
34201 	call_flags = 0;
34202 	if (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
34203 		/* Set DIRECT_EVAL flag for the call; it's not strictly
34204 		 * needed for the 'inner' eval call (the eval body) but
34205 		 * current new.target implementation expects to find it
34206 		 * so it can traverse direct eval chains up to the real
34207 		 * calling function.
34208 		 */
34209 		call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
34210 	}
34211 	duk_handle_call_unprotected_nargs(thr, 0, call_flags);
34212 
34213 	/* [ env? source template result ] */
34214 
34215 	return 1;
34216 }
34217 
34218 /*
34219  *  Parsing of ints and floats
34220  */
34221 
34222 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_parse_int(duk_hthread * thr)34223 DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_int(duk_hthread *thr) {
34224 	duk_int32_t radix;
34225 	duk_small_uint_t s2n_flags;
34226 
34227 	DUK_ASSERT_TOP(thr, 2);
34228 	duk_to_string(thr, 0);  /* Reject symbols. */
34229 
34230 	radix = duk_to_int32(thr, 1);
34231 
34232 	/* While parseInt() recognizes 0xdeadbeef, it doesn't recognize
34233 	 * ES2015 0o123 or 0b10001.
34234 	 */
34235 	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
34236 	            DUK_S2N_FLAG_ALLOW_GARBAGE |
34237 	            DUK_S2N_FLAG_ALLOW_PLUS |
34238 	            DUK_S2N_FLAG_ALLOW_MINUS |
34239 	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
34240 	            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
34241 
34242 	/* Specification stripPrefix maps to DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT.
34243 	 *
34244 	 * Don't autodetect octals (from leading zeroes), require user code to
34245 	 * provide an explicit radix 8 for parsing octal.  See write-up from Mozilla:
34246 	 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#ECMAScript_5_Removes_Octal_Interpretation
34247 	 */
34248 
34249 	if (radix != 0) {
34250 		if (radix < 2 || radix > 36) {
34251 			goto ret_nan;
34252 		}
34253 		if (radix != 16) {
34254 			s2n_flags &= ~DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
34255 		}
34256 	} else {
34257 		radix = 10;
34258 	}
34259 
34260 	duk_dup_0(thr);
34261 	duk_numconv_parse(thr, (duk_small_int_t) radix, s2n_flags);
34262 	return 1;
34263 
34264  ret_nan:
34265 	duk_push_nan(thr);
34266 	return 1;
34267 }
34268 #endif  /* DUK_USE_GLOBAL_BUILTIN */
34269 
34270 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_parse_float(duk_hthread * thr)34271 DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_float(duk_hthread *thr) {
34272 	duk_small_uint_t s2n_flags;
34273 
34274 	DUK_ASSERT_TOP(thr, 1);
34275 	duk_to_string(thr, 0);  /* Reject symbols. */
34276 
34277 	/* XXX: check flags */
34278 	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
34279 	            DUK_S2N_FLAG_ALLOW_EXP |
34280 	            DUK_S2N_FLAG_ALLOW_GARBAGE |
34281 	            DUK_S2N_FLAG_ALLOW_PLUS |
34282 	            DUK_S2N_FLAG_ALLOW_MINUS |
34283 	            DUK_S2N_FLAG_ALLOW_INF |
34284 	            DUK_S2N_FLAG_ALLOW_FRAC |
34285 	            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
34286 	            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
34287 	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
34288 
34289 	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
34290 	return 1;
34291 }
34292 #endif  /* DUK_USE_GLOBAL_BUILTIN */
34293 
34294 /*
34295  *  Number checkers
34296  */
34297 
34298 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_is_nan(duk_hthread * thr)34299 DUK_INTERNAL duk_ret_t duk_bi_global_object_is_nan(duk_hthread *thr) {
34300 	duk_double_t d = duk_to_number(thr, 0);
34301 	duk_push_boolean(thr, (duk_bool_t) DUK_ISNAN(d));
34302 	return 1;
34303 }
34304 #endif  /* DUK_USE_GLOBAL_BUILTIN */
34305 
34306 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_is_finite(duk_hthread * thr)34307 DUK_INTERNAL duk_ret_t duk_bi_global_object_is_finite(duk_hthread *thr) {
34308 	duk_double_t d = duk_to_number(thr, 0);
34309 	duk_push_boolean(thr, (duk_bool_t) DUK_ISFINITE(d));
34310 	return 1;
34311 }
34312 #endif  /* DUK_USE_GLOBAL_BUILTIN */
34313 
34314 /*
34315  *  URI handling
34316  */
34317 
34318 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_decode_uri(duk_hthread * thr)34319 DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri(duk_hthread *thr) {
34320 	return duk__transform_helper(thr, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_reserved_table);
34321 }
34322 
duk_bi_global_object_decode_uri_component(duk_hthread * thr)34323 DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri_component(duk_hthread *thr) {
34324 	return duk__transform_helper(thr, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_component_reserved_table);
34325 }
34326 
duk_bi_global_object_encode_uri(duk_hthread * thr)34327 DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri(duk_hthread *thr) {
34328 	return duk__transform_helper(thr, duk__transform_callback_encode_uri, (const void *) duk__encode_uriunescaped_table);
34329 }
34330 
duk_bi_global_object_encode_uri_component(duk_hthread * thr)34331 DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri_component(duk_hthread *thr) {
34332 	return duk__transform_helper(thr, duk__transform_callback_encode_uri, (const void *) duk__encode_uricomponent_unescaped_table);
34333 }
34334 
34335 #if defined(DUK_USE_SECTION_B)
duk_bi_global_object_escape(duk_hthread * thr)34336 DUK_INTERNAL duk_ret_t duk_bi_global_object_escape(duk_hthread *thr) {
34337 	return duk__transform_helper(thr, duk__transform_callback_escape, (const void *) NULL);
34338 }
34339 
duk_bi_global_object_unescape(duk_hthread * thr)34340 DUK_INTERNAL duk_ret_t duk_bi_global_object_unescape(duk_hthread *thr) {
34341 	return duk__transform_helper(thr, duk__transform_callback_unescape, (const void *) NULL);
34342 }
34343 #endif  /* DUK_USE_SECTION_B */
34344 #endif  /* DUK_USE_GLOBAL_BUILTIN */
34345 
34346 /* automatic undefs */
34347 #undef DUK__CHECK_BITMASK
34348 #undef DUK__MKBITS
34349 /*
34350  *  JSON built-ins.
34351  *
34352  *  See doc/json.rst.
34353  *
34354  *  Codepoints are handled as duk_uint_fast32_t to ensure that the full
34355  *  unsigned 32-bit range is supported.  This matters to e.g. JX.
34356  *
34357  *  Input parsing doesn't do an explicit end-of-input check at all.  This is
34358  *  safe: input string data is always NUL-terminated (0x00) and valid JSON
34359  *  inputs never contain plain NUL characters, so that as long as syntax checks
34360  *  are correct, we'll never read past the NUL.  This approach reduces code size
34361  *  and improves parsing performance, but it's critical that syntax checks are
34362  *  indeed correct!
34363  */
34364 
34365 /* #include duk_internal.h -> already included */
34366 
34367 #if defined(DUK_USE_JSON_SUPPORT)
34368 
34369 /*
34370  *  Local defines and forward declarations.
34371  */
34372 
34373 #define DUK__JSON_DECSTR_BUFSIZE 128
34374 #define DUK__JSON_DECSTR_CHUNKSIZE 64
34375 #define DUK__JSON_ENCSTR_CHUNKSIZE 64
34376 #define DUK__JSON_STRINGIFY_BUFSIZE 128
34377 #define DUK__JSON_MAX_ESC_LEN 10  /* '\Udeadbeef' */
34378 
34379 DUK_LOCAL_DECL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx);
34380 DUK_LOCAL_DECL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx);
34381 #if defined(DUK_USE_JX)
34382 DUK_LOCAL_DECL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx);
34383 #endif
34384 DUK_LOCAL_DECL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx);
34385 DUK_LOCAL_DECL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx);
34386 DUK_LOCAL_DECL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n);
34387 DUK_LOCAL_DECL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx);
34388 DUK_LOCAL_DECL void duk__dec_string(duk_json_dec_ctx *js_ctx);
34389 #if defined(DUK_USE_JX)
34390 DUK_LOCAL_DECL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx);
34391 DUK_LOCAL_DECL void duk__dec_pointer(duk_json_dec_ctx *js_ctx);
34392 DUK_LOCAL_DECL void duk__dec_buffer(duk_json_dec_ctx *js_ctx);
34393 #endif
34394 DUK_LOCAL_DECL void duk__dec_number(duk_json_dec_ctx *js_ctx);
34395 DUK_LOCAL_DECL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx);
34396 DUK_LOCAL_DECL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx);
34397 DUK_LOCAL_DECL void duk__dec_object(duk_json_dec_ctx *js_ctx);
34398 DUK_LOCAL_DECL void duk__dec_array(duk_json_dec_ctx *js_ctx);
34399 DUK_LOCAL_DECL void duk__dec_value(duk_json_dec_ctx *js_ctx);
34400 DUK_LOCAL_DECL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx);
34401 
34402 DUK_LOCAL_DECL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch);
34403 DUK_LOCAL_DECL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2);
34404 DUK_LOCAL_DECL void duk__unemit_1(duk_json_enc_ctx *js_ctx);
34405 DUK_LOCAL_DECL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h);
34406 #if defined(DUK_USE_FASTINT)
34407 DUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p);
34408 #endif
34409 DUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx);
34410 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);
34411 DUK_LOCAL_DECL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k);
34412 DUK_LOCAL_DECL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str);
34413 DUK_LOCAL_DECL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
34414 DUK_LOCAL_DECL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
34415 DUK_LOCAL_DECL void duk__enc_object(duk_json_enc_ctx *js_ctx);
34416 DUK_LOCAL_DECL void duk__enc_array(duk_json_enc_ctx *js_ctx);
34417 DUK_LOCAL_DECL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder);
34418 DUK_LOCAL_DECL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv);
34419 DUK_LOCAL_DECL void duk__enc_double(duk_json_enc_ctx *js_ctx);
34420 #if defined(DUK_USE_FASTINT)
34421 DUK_LOCAL_DECL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv);
34422 #endif
34423 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
34424 DUK_LOCAL_DECL void duk__enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
34425 DUK_LOCAL_DECL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr);
34426 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
34427 DUK_LOCAL_DECL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj);
34428 #endif
34429 #endif
34430 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
34431 DUK_LOCAL_DECL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
34432 #endif
34433 DUK_LOCAL_DECL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth);
34434 
34435 /*
34436  *  Helper tables
34437  */
34438 
34439 #if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
34440 DUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256] = {
34441 	/* 0x00 ... 0x7f: as is
34442 	 * 0x80: escape generically
34443 	 * 0x81: slow path
34444 	 * 0xa0 ... 0xff: backslash + one char
34445 	 */
34446 
34447 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe2, 0xf4, 0xee, 0x80, 0xe6, 0xf2, 0x80, 0x80,
34448 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
34449 	0x20, 0x21, 0xa2, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
34450 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
34451 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
34452 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0xdc, 0x5d, 0x5e, 0x5f,
34453 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
34454 	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x81,
34455 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34456 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34457 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34458 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34459 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34460 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34461 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34462 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81
34463 };
34464 #else  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
34465 DUK_LOCAL const duk_uint8_t duk__json_quotestr_esc[14] = {
34466 	DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
34467 	DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
34468 	DUK_ASC_LC_B, DUK_ASC_LC_T, DUK_ASC_LC_N, DUK_ASC_NUL,
34469 	DUK_ASC_LC_F, DUK_ASC_LC_R
34470 };
34471 #endif  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
34472 
34473 #if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
34474 DUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256] = {
34475 	/* 0x00: slow path
34476 	 * other: as is
34477 	 */
34478 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34479 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34480 	0x20, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
34481 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
34482 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
34483 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x5d, 0x5e, 0x5f,
34484 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
34485 	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
34486 	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
34487 	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
34488 	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
34489 	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
34490 	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
34491 	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
34492 	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
34493 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
34494 };
34495 #endif  /* DUK_USE_JSON_DECSTRING_FASTPATH */
34496 
34497 #if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
34498 DUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256] = {
34499 	/* 0x00: finish (non-white)
34500 	 * 0x01: continue
34501 	 */
34502 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
34503 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34504 	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34505 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34506 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34507 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34508 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34509 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34510 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34511 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34512 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34513 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34514 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34515 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34516 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34517 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
34518 };
34519 #endif  /* DUK_USE_JSON_EATWHITE_FASTPATH */
34520 
34521 #if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
34522 DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256] = {
34523 	/* 0x00: finish (not part of number)
34524 	 * 0x01: continue
34525 	 */
34526 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34527 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34528 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00,
34529 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34530 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34531 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34532 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34533 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34534 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34535 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34536 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34537 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34538 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34539 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34540 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34541 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
34542 };
34543 #endif  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
34544 
34545 /*
34546  *  Parsing implementation.
34547  *
34548  *  JSON lexer is now separate from duk_lexer.c because there are numerous
34549  *  small differences making it difficult to share the lexer.
34550  *
34551  *  The parser here works with raw bytes directly; this works because all
34552  *  JSON delimiters are ASCII characters.  Invalid xUTF-8 encoded values
34553  *  inside strings will be passed on without normalization; this is not a
34554  *  compliance concern because compliant inputs will always be valid
34555  *  CESU-8 encodings.
34556  */
34557 
duk__dec_syntax_error(duk_json_dec_ctx * js_ctx)34558 DUK_LOCAL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx) {
34559 	/* Shared handler to minimize parser size.  Cause will be
34560 	 * hidden, unfortunately, but we'll have an offset which
34561 	 * is often quite enough.
34562 	 */
34563 	DUK_ERROR_FMT1(js_ctx->thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_FMT_INVALID_JSON,
34564 	               (long) (js_ctx->p - js_ctx->p_start));
34565 	DUK_WO_NORETURN(return;);
34566 }
34567 
duk__dec_eat_white(duk_json_dec_ctx * js_ctx)34568 DUK_LOCAL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx) {
34569 	const duk_uint8_t *p;
34570 	duk_uint8_t t;
34571 
34572 	p = js_ctx->p;
34573 	for (;;) {
34574 		DUK_ASSERT(p <= js_ctx->p_end);
34575 		t = *p;
34576 
34577 #if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
34578 		/* This fast path is pretty marginal in practice.
34579 		 * XXX: candidate for removal.
34580 		 */
34581 		DUK_ASSERT(duk__json_eatwhite_lookup[0x00] == 0x00);  /* end-of-input breaks */
34582 		if (duk__json_eatwhite_lookup[t] == 0) {
34583 			break;
34584 		}
34585 #else  /* DUK_USE_JSON_EATWHITE_FASTPATH */
34586 		if (!(t == 0x20 || t == 0x0a || t == 0x0d || t == 0x09)) {
34587 			/* NUL also comes here.  Comparison order matters, 0x20
34588 			 * is most common whitespace.
34589 			 */
34590 			break;
34591 		}
34592 #endif  /* DUK_USE_JSON_EATWHITE_FASTPATH */
34593 		p++;
34594 	}
34595 	js_ctx->p = p;
34596 }
34597 
34598 #if defined(DUK_USE_JX)
duk__dec_peek(duk_json_dec_ctx * js_ctx)34599 DUK_LOCAL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx) {
34600 	DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
34601 	return *js_ctx->p;
34602 }
34603 #endif
34604 
duk__dec_get(duk_json_dec_ctx * js_ctx)34605 DUK_LOCAL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx) {
34606 	DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
34607 	return *js_ctx->p++;
34608 }
34609 
duk__dec_get_nonwhite(duk_json_dec_ctx * js_ctx)34610 DUK_LOCAL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx) {
34611 	duk__dec_eat_white(js_ctx);
34612 	return duk__dec_get(js_ctx);
34613 }
34614 
34615 /* For JX, expressing the whole unsigned 32-bit range matters. */
duk__dec_decode_hex_escape(duk_json_dec_ctx * js_ctx,duk_small_uint_t n)34616 DUK_LOCAL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) {
34617 	duk_small_uint_t i;
34618 	duk_uint_fast32_t res = 0;
34619 	duk_uint8_t x;
34620 	duk_small_int_t t;
34621 
34622 	for (i = 0; i < n; i++) {
34623 		/* XXX: share helper from lexer; duk_lexer.c / hexval(). */
34624 
34625 		x = duk__dec_get(js_ctx);
34626 		DUK_DDD(DUK_DDDPRINT("decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld",
34627 		                     (long) i, (long) n, (long) res, (long) x));
34628 
34629 		/* x == 0x00 (EOF) causes syntax_error */
34630 		DUK_ASSERT(duk_hex_dectab[0] == -1);
34631 		t = duk_hex_dectab[x & 0xff];
34632 		if (DUK_LIKELY(t >= 0)) {
34633 			res = (res * 16) + (duk_uint_fast32_t) t;
34634 		} else {
34635 			/* catches EOF and invalid digits */
34636 			goto syntax_error;
34637 		}
34638 	}
34639 
34640 	DUK_DDD(DUK_DDDPRINT("final hex decoded value: %ld", (long) res));
34641 	return res;
34642 
34643  syntax_error:
34644 	duk__dec_syntax_error(js_ctx);
34645 	DUK_UNREACHABLE();
34646 	return 0;
34647 }
34648 
duk__dec_req_stridx(duk_json_dec_ctx * js_ctx,duk_small_uint_t stridx)34649 DUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) {
34650 	duk_hstring *h;
34651 	const duk_uint8_t *p;
34652 	duk_uint8_t x, y;
34653 
34654 	/* First character has already been eaten and checked by the caller.
34655 	 * We can scan until a NUL in stridx string because no built-in strings
34656 	 * have internal NULs.
34657 	 */
34658 
34659 	DUK_ASSERT_STRIDX_VALID(stridx);
34660 	h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
34661 	DUK_ASSERT(h != NULL);
34662 
34663 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h) + 1;
34664 	DUK_ASSERT(*(js_ctx->p - 1) == *(p - 1));  /* first character has been matched */
34665 
34666 	for (;;) {
34667 		x = *p;
34668 		if (x == 0) {
34669 			break;
34670 		}
34671 		y = duk__dec_get(js_ctx);
34672 		if (x != y) {
34673 			/* Catches EOF of JSON input. */
34674 			goto syntax_error;
34675 		}
34676 		p++;
34677 	}
34678 
34679 	return;
34680 
34681  syntax_error:
34682 	duk__dec_syntax_error(js_ctx);
34683 	DUK_UNREACHABLE();
34684 }
34685 
duk__dec_string_escape(duk_json_dec_ctx * js_ctx,duk_uint8_t ** ext_p)34686 DUK_LOCAL duk_small_int_t duk__dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p) {
34687 	duk_uint_fast32_t cp;
34688 
34689 	/* EOF (-1) will be cast to an unsigned value first
34690 	 * and then re-cast for the switch.  In any case, it
34691 	 * will match the default case (syntax error).
34692 	 */
34693 	cp = (duk_uint_fast32_t) duk__dec_get(js_ctx);
34694 	switch (cp) {
34695 	case DUK_ASC_BACKSLASH: break;
34696 	case DUK_ASC_DOUBLEQUOTE: break;
34697 	case DUK_ASC_SLASH: break;
34698 	case DUK_ASC_LC_T: cp = 0x09; break;
34699 	case DUK_ASC_LC_N: cp = 0x0a; break;
34700 	case DUK_ASC_LC_R: cp = 0x0d; break;
34701 	case DUK_ASC_LC_F: cp = 0x0c; break;
34702 	case DUK_ASC_LC_B: cp = 0x08; break;
34703 	case DUK_ASC_LC_U: {
34704 		cp = duk__dec_decode_hex_escape(js_ctx, 4);
34705 		break;
34706 	}
34707 #if defined(DUK_USE_JX)
34708 	case DUK_ASC_UC_U: {
34709 		if (js_ctx->flag_ext_custom) {
34710 			cp = duk__dec_decode_hex_escape(js_ctx, 8);
34711 		} else {
34712 			return 1;  /* syntax error */
34713 		}
34714 		break;
34715 	}
34716 	case DUK_ASC_LC_X: {
34717 		if (js_ctx->flag_ext_custom) {
34718 			cp = duk__dec_decode_hex_escape(js_ctx, 2);
34719 		} else {
34720 			return 1;  /* syntax error */
34721 		}
34722 		break;
34723 	}
34724 #endif  /* DUK_USE_JX */
34725 	default:
34726 		/* catches EOF (0x00) */
34727 		return 1;  /* syntax error */
34728 	}
34729 
34730 	DUK_RAW_WRITE_XUTF8(*ext_p, cp);
34731 
34732 	return 0;
34733 }
34734 
duk__dec_string(duk_json_dec_ctx * js_ctx)34735 DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) {
34736 	duk_hthread *thr = js_ctx->thr;
34737 	duk_bufwriter_ctx bw_alloc;
34738 	duk_bufwriter_ctx *bw;
34739 	duk_uint8_t *q;
34740 
34741 	/* '"' was eaten by caller */
34742 
34743 	/* Note that we currently parse -bytes-, not codepoints.
34744 	 * All non-ASCII extended UTF-8 will encode to bytes >= 0x80,
34745 	 * so they'll simply pass through (valid UTF-8 or not).
34746 	 */
34747 
34748 	bw = &bw_alloc;
34749 	DUK_BW_INIT_PUSHBUF(js_ctx->thr, bw, DUK__JSON_DECSTR_BUFSIZE);
34750 	q = DUK_BW_GET_PTR(js_ctx->thr, bw);
34751 
34752 #if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
34753 	for (;;) {
34754 		duk_small_uint_t safe;
34755 		duk_uint8_t b, x;
34756 		const duk_uint8_t *p;
34757 
34758 		/* Select a safe loop count where no output checks are
34759 		 * needed assuming we won't encounter escapes.  Input
34760 		 * bound checks are not necessary as a NUL (guaranteed)
34761 		 * will cause a SyntaxError before we read out of bounds.
34762 		 */
34763 
34764 		safe = DUK__JSON_DECSTR_CHUNKSIZE;
34765 
34766 		/* Ensure space for 1:1 output plus one escape. */
34767 		q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, safe + DUK_UNICODE_MAX_XUTF8_LENGTH, q);
34768 
34769 		p = js_ctx->p;  /* temp copy, write back for next loop */
34770 		for (;;) {
34771 			if (safe == 0) {
34772 				js_ctx->p = p;
34773 				break;
34774 			}
34775 			safe--;
34776 
34777 			/* End of input (NUL) goes through slow path and causes SyntaxError. */
34778 			DUK_ASSERT(duk__json_decstr_lookup[0] == 0x00);
34779 
34780 			b = *p++;
34781 			x = (duk_small_int_t) duk__json_decstr_lookup[b];
34782 			if (DUK_LIKELY(x != 0)) {
34783 				/* Fast path, decode as is. */
34784 				*q++ = b;
34785 			} else if (b == DUK_ASC_DOUBLEQUOTE) {
34786 				js_ctx->p = p;
34787 				goto found_quote;
34788 			} else if (b == DUK_ASC_BACKSLASH) {
34789 				/* We've ensured space for one escaped input; then
34790 				 * bail out and recheck (this makes escape handling
34791 				 * quite slow but it's uncommon).
34792 				 */
34793 				js_ctx->p = p;
34794 				if (duk__dec_string_escape(js_ctx, &q) != 0) {
34795 					goto syntax_error;
34796 				}
34797 				break;
34798 			} else {
34799 				js_ctx->p = p;
34800 				goto syntax_error;
34801 			}
34802 		}
34803 	}
34804  found_quote:
34805 #else  /* DUK_USE_JSON_DECSTRING_FASTPATH */
34806 	for (;;) {
34807 		duk_uint8_t x;
34808 
34809 		q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, DUK_UNICODE_MAX_XUTF8_LENGTH, q);
34810 
34811 		x = duk__dec_get(js_ctx);
34812 
34813 		if (x == DUK_ASC_DOUBLEQUOTE) {
34814 			break;
34815 		} else if (x == DUK_ASC_BACKSLASH) {
34816 			if (duk__dec_string_escape(js_ctx, &q) != 0) {
34817 				goto syntax_error;
34818 			}
34819 		} else if (x < 0x20) {
34820 			/* catches EOF (NUL) */
34821 			goto syntax_error;
34822 		} else {
34823 			*q++ = (duk_uint8_t) x;
34824 		}
34825 	}
34826 #endif  /* DUK_USE_JSON_DECSTRING_FASTPATH */
34827 
34828 	DUK_BW_SETPTR_AND_COMPACT(js_ctx->thr, bw, q);
34829 	(void) duk_buffer_to_string(thr, -1);  /* Safe if input string is safe. */
34830 
34831 	/* [ ... str ] */
34832 
34833 	return;
34834 
34835  syntax_error:
34836 	duk__dec_syntax_error(js_ctx);
34837 	DUK_UNREACHABLE();
34838 }
34839 
34840 #if defined(DUK_USE_JX)
34841 /* Decode a plain string consisting entirely of identifier characters.
34842  * Used to parse plain keys (e.g. "foo: 123").
34843  */
duk__dec_plain_string(duk_json_dec_ctx * js_ctx)34844 DUK_LOCAL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx) {
34845 	duk_hthread *thr = js_ctx->thr;
34846 	const duk_uint8_t *p;
34847 	duk_small_int_t x;
34848 
34849 	/* Caller has already eaten the first char so backtrack one byte. */
34850 
34851 	js_ctx->p--;  /* safe */
34852 	p = js_ctx->p;
34853 
34854 	/* Here again we parse bytes, and non-ASCII UTF-8 will cause end of
34855 	 * parsing (which is correct except if there are non-shortest encodings).
34856 	 * There is also no need to check explicitly for end of input buffer as
34857 	 * the input is NUL padded and NUL will exit the parsing loop.
34858 	 *
34859 	 * Because no unescaping takes place, we can just scan to the end of the
34860 	 * plain string and intern from the input buffer.
34861 	 */
34862 
34863 	for (;;) {
34864 		x = *p;
34865 
34866 		/* There is no need to check the first character specially here
34867 		 * (i.e. reject digits): the caller only accepts valid initial
34868 		 * characters and won't call us if the first character is a digit.
34869 		 * This also ensures that the plain string won't be empty.
34870 		 */
34871 
34872 		if (!duk_unicode_is_identifier_part((duk_codepoint_t) x)) {
34873 			break;
34874 		}
34875 		p++;
34876 	}
34877 
34878 	duk_push_lstring(thr, (const char *) js_ctx->p, (duk_size_t) (p - js_ctx->p));
34879 	js_ctx->p = p;
34880 
34881 	/* [ ... str ] */
34882 }
34883 #endif  /* DUK_USE_JX */
34884 
34885 #if defined(DUK_USE_JX)
duk__dec_pointer(duk_json_dec_ctx * js_ctx)34886 DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) {
34887 	duk_hthread *thr = js_ctx->thr;
34888 	const duk_uint8_t *p;
34889 	duk_small_int_t x;
34890 	void *voidptr;
34891 
34892 	/* Caller has already eaten the first character ('(') which we don't need. */
34893 
34894 	p = js_ctx->p;
34895 
34896 	for (;;) {
34897 		x = *p;
34898 
34899 		/* Assume that the native representation never contains a closing
34900 		 * parenthesis.
34901 		 */
34902 
34903 		if (x == DUK_ASC_RPAREN) {
34904 			break;
34905 		} else if (x <= 0) {
34906 			/* NUL term or -1 (EOF), NUL check would suffice */
34907 			goto syntax_error;
34908 		}
34909 		p++;
34910 	}
34911 
34912 	/* There is no need to NUL delimit the sscanf() call: trailing garbage is
34913 	 * ignored and there is always a NUL terminator which will force an error
34914 	 * if no error is encountered before it.  It's possible that the scan
34915 	 * would scan further than between [js_ctx->p,p[ though and we'd advance
34916 	 * by less than the scanned value.
34917 	 *
34918 	 * Because pointers are platform specific, a failure to scan a pointer
34919 	 * results in a null pointer which is a better placeholder than a missing
34920 	 * value or an error.
34921 	 */
34922 
34923 	voidptr = NULL;
34924 	(void) DUK_SSCANF((const char *) js_ctx->p, DUK_STR_FMT_PTR, &voidptr);
34925 	duk_push_pointer(thr, voidptr);
34926 	js_ctx->p = p + 1;  /* skip ')' */
34927 
34928 	/* [ ... ptr ] */
34929 
34930 	return;
34931 
34932  syntax_error:
34933 	duk__dec_syntax_error(js_ctx);
34934 	DUK_UNREACHABLE();
34935 }
34936 #endif  /* DUK_USE_JX */
34937 
34938 #if defined(DUK_USE_JX)
duk__dec_buffer(duk_json_dec_ctx * js_ctx)34939 DUK_LOCAL void duk__dec_buffer(duk_json_dec_ctx *js_ctx) {
34940 	duk_hthread *thr = js_ctx->thr;
34941 	const duk_uint8_t *p;
34942 	duk_uint8_t *buf;
34943 	duk_size_t src_len;
34944 	duk_small_int_t x;
34945 
34946 	/* Caller has already eaten the first character ('|') which we don't need. */
34947 
34948 	p = js_ctx->p;
34949 
34950 	/* XXX: Would be nice to share the fast path loop from duk_hex_decode()
34951 	 * and avoid creating a temporary buffer.  However, there are some
34952 	 * differences which prevent trivial sharing:
34953 	 *
34954 	 *   - Pipe char detection
34955 	 *   - EOF detection
34956 	 *   - Unknown length of input and output
34957 	 *
34958 	 * The best approach here would be a bufwriter and a reasonaly sized
34959 	 * safe inner loop (e.g. 64 output bytes at a time).
34960 	 */
34961 
34962 	for (;;) {
34963 		x = *p;
34964 
34965 		/* This loop intentionally does not ensure characters are valid
34966 		 * ([0-9a-fA-F]) because the hex decode call below will do that.
34967 		 */
34968 		if (x == DUK_ASC_PIPE) {
34969 			break;
34970 		} else if (x <= 0) {
34971 			/* NUL term or -1 (EOF), NUL check would suffice */
34972 			goto syntax_error;
34973 		}
34974 		p++;
34975 	}
34976 
34977 	/* XXX: this is not very nice; unnecessary copy is made. */
34978 	src_len = (duk_size_t) (p - js_ctx->p);
34979 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_len);
34980 	DUK_ASSERT(buf != NULL);
34981 	duk_memcpy((void *) buf, (const void *) js_ctx->p, src_len);
34982 	duk_hex_decode(thr, -1);
34983 
34984 	js_ctx->p = p + 1;  /* skip '|' */
34985 
34986 	/* [ ... buf ] */
34987 
34988 	return;
34989 
34990  syntax_error:
34991 	duk__dec_syntax_error(js_ctx);
34992 	DUK_UNREACHABLE();
34993 }
34994 #endif  /* DUK_USE_JX */
34995 
34996 /* Parse a number, other than NaN or +/- Infinity */
duk__dec_number(duk_json_dec_ctx * js_ctx)34997 DUK_LOCAL void duk__dec_number(duk_json_dec_ctx *js_ctx) {
34998 	duk_hthread *thr = js_ctx->thr;
34999 	const duk_uint8_t *p_start;
35000 	const duk_uint8_t *p;
35001 	duk_uint8_t x;
35002 	duk_small_uint_t s2n_flags;
35003 
35004 	DUK_DDD(DUK_DDDPRINT("parse_number"));
35005 
35006 	p_start = js_ctx->p;
35007 
35008 	/* First pass parse is very lenient (e.g. allows '1.2.3') and extracts a
35009 	 * string for strict number parsing.
35010 	 */
35011 
35012 	p = js_ctx->p;
35013 	for (;;) {
35014 		x = *p;
35015 
35016 		DUK_DDD(DUK_DDDPRINT("parse_number: p_start=%p, p=%p, p_end=%p, x=%ld",
35017 		                     (const void *) p_start, (const void *) p,
35018 		                     (const void *) js_ctx->p_end, (long) x));
35019 
35020 #if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
35021 		/* This fast path is pretty marginal in practice.
35022 		 * XXX: candidate for removal.
35023 		 */
35024 		DUK_ASSERT(duk__json_decnumber_lookup[0x00] == 0x00);  /* end-of-input breaks */
35025 		if (duk__json_decnumber_lookup[x] == 0) {
35026 			break;
35027 		}
35028 #else  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
35029 		if (!((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
35030 		      (x == DUK_ASC_PERIOD || x == DUK_ASC_LC_E ||
35031 		       x == DUK_ASC_UC_E || x == DUK_ASC_MINUS || x == DUK_ASC_PLUS))) {
35032 			/* Plus sign must be accepted for positive exponents
35033 			 * (e.g. '1.5e+2').  This clause catches NULs.
35034 			 */
35035 			break;
35036 		}
35037 #endif  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
35038 		p++;  /* safe, because matched (NUL causes a break) */
35039 	}
35040 	js_ctx->p = p;
35041 
35042 	DUK_ASSERT(js_ctx->p > p_start);
35043 	duk_push_lstring(thr, (const char *) p_start, (duk_size_t) (p - p_start));
35044 
35045 	s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
35046 	            DUK_S2N_FLAG_ALLOW_MINUS |  /* but don't allow leading plus */
35047 	            DUK_S2N_FLAG_ALLOW_FRAC;
35048 
35049 	DUK_DDD(DUK_DDDPRINT("parse_number: string before parsing: %!T",
35050 	                     (duk_tval *) duk_get_tval(thr, -1)));
35051 	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
35052 	if (duk_is_nan(thr, -1)) {
35053 		duk__dec_syntax_error(js_ctx);
35054 	}
35055 	DUK_ASSERT(duk_is_number(thr, -1));
35056 	DUK_DDD(DUK_DDDPRINT("parse_number: final number: %!T",
35057 	                     (duk_tval *) duk_get_tval(thr, -1)));
35058 
35059 	/* [ ... num ] */
35060 }
35061 
duk__dec_objarr_entry(duk_json_dec_ctx * js_ctx)35062 DUK_LOCAL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx) {
35063 	duk_hthread *thr = js_ctx->thr;
35064 	duk_require_stack(thr, DUK_JSON_DEC_REQSTACK);
35065 
35066 	/* c recursion check */
35067 
35068 	DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
35069 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
35070 	if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
35071 		DUK_ERROR_RANGE(thr, DUK_STR_JSONDEC_RECLIMIT);
35072 		DUK_WO_NORETURN(return;);
35073 	}
35074 	js_ctx->recursion_depth++;
35075 }
35076 
duk__dec_objarr_exit(duk_json_dec_ctx * js_ctx)35077 DUK_LOCAL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx) {
35078 	/* c recursion check */
35079 
35080 	DUK_ASSERT(js_ctx->recursion_depth > 0);
35081 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
35082 	js_ctx->recursion_depth--;
35083 }
35084 
duk__dec_object(duk_json_dec_ctx * js_ctx)35085 DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) {
35086 	duk_hthread *thr = js_ctx->thr;
35087 	duk_int_t key_count;  /* XXX: a "first" flag would suffice */
35088 	duk_uint8_t x;
35089 
35090 	DUK_DDD(DUK_DDDPRINT("parse_object"));
35091 
35092 	duk__dec_objarr_entry(js_ctx);
35093 
35094 	duk_push_object(thr);
35095 
35096 	/* Initial '{' has been checked and eaten by caller. */
35097 
35098 	key_count = 0;
35099 	for (;;) {
35100 		x = duk__dec_get_nonwhite(js_ctx);
35101 
35102 		DUK_DDD(DUK_DDDPRINT("parse_object: obj=%!T, x=%ld, key_count=%ld",
35103 		                     (duk_tval *) duk_get_tval(thr, -1),
35104 		                     (long) x, (long) key_count));
35105 
35106 		/* handle comma and closing brace */
35107 
35108 		if (x == DUK_ASC_COMMA && key_count > 0) {
35109 			/* accept comma, expect new value */
35110 			x = duk__dec_get_nonwhite(js_ctx);
35111 		} else if (x == DUK_ASC_RCURLY) {
35112 			/* eat closing brace */
35113 			break;
35114 		} else if (key_count == 0) {
35115 			/* accept anything, expect first value (EOF will be
35116 			 * caught by key parsing below.
35117 			 */
35118 			;
35119 		} else {
35120 			/* catches EOF (NUL) and initial comma */
35121 			goto syntax_error;
35122 		}
35123 
35124 		/* parse key and value */
35125 
35126 		if (x == DUK_ASC_DOUBLEQUOTE) {
35127 			duk__dec_string(js_ctx);
35128 #if defined(DUK_USE_JX)
35129 		} else if (js_ctx->flag_ext_custom &&
35130 		           duk_unicode_is_identifier_start((duk_codepoint_t) x)) {
35131 			duk__dec_plain_string(js_ctx);
35132 #endif
35133 		} else {
35134 			goto syntax_error;
35135 		}
35136 
35137 		/* [ ... obj key ] */
35138 
35139 		x = duk__dec_get_nonwhite(js_ctx);
35140 		if (x != DUK_ASC_COLON) {
35141 			goto syntax_error;
35142 		}
35143 
35144 		duk__dec_value(js_ctx);
35145 
35146 		/* [ ... obj key val ] */
35147 
35148 		duk_xdef_prop_wec(thr, -3);
35149 
35150 		/* [ ... obj ] */
35151 
35152 		key_count++;
35153 	}
35154 
35155 	/* [ ... obj ] */
35156 
35157 	DUK_DDD(DUK_DDDPRINT("parse_object: final object is %!T",
35158 	                     (duk_tval *) duk_get_tval(thr, -1)));
35159 
35160 	duk__dec_objarr_exit(js_ctx);
35161 	return;
35162 
35163  syntax_error:
35164 	duk__dec_syntax_error(js_ctx);
35165 	DUK_UNREACHABLE();
35166 }
35167 
duk__dec_array(duk_json_dec_ctx * js_ctx)35168 DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) {
35169 	duk_hthread *thr = js_ctx->thr;
35170 	duk_uarridx_t arr_idx;
35171 	duk_uint8_t x;
35172 
35173 	DUK_DDD(DUK_DDDPRINT("parse_array"));
35174 
35175 	duk__dec_objarr_entry(js_ctx);
35176 
35177 	duk_push_array(thr);
35178 
35179 	/* Initial '[' has been checked and eaten by caller. */
35180 
35181 	arr_idx = 0;
35182 	for (;;) {
35183 		x = duk__dec_get_nonwhite(js_ctx);
35184 
35185 		DUK_DDD(DUK_DDDPRINT("parse_array: arr=%!T, x=%ld, arr_idx=%ld",
35186 		                     (duk_tval *) duk_get_tval(thr, -1),
35187 		                     (long) x, (long) arr_idx));
35188 
35189 		/* handle comma and closing bracket */
35190 
35191 		if ((x == DUK_ASC_COMMA) && (arr_idx != 0)) {
35192 			/* accept comma, expect new value */
35193 			;
35194 		} else if (x == DUK_ASC_RBRACKET) {
35195 			/* eat closing bracket */
35196 			break;
35197 		} else if (arr_idx == 0) {
35198 			/* accept anything, expect first value (EOF will be
35199 			 * caught by duk__dec_value() below.
35200 			 */
35201 			js_ctx->p--;  /* backtrack (safe) */
35202 		} else {
35203 			/* catches EOF (NUL) and initial comma */
35204 			goto syntax_error;
35205 		}
35206 
35207 		/* parse value */
35208 
35209 		duk__dec_value(js_ctx);
35210 
35211 		/* [ ... arr val ] */
35212 
35213 		duk_xdef_prop_index_wec(thr, -2, arr_idx);
35214 		arr_idx++;
35215 	}
35216 
35217 	/* Must set 'length' explicitly when using duk_xdef_prop_xxx() to
35218 	 * set the values.
35219 	 */
35220 
35221 	duk_set_length(thr, -1, arr_idx);
35222 
35223 	/* [ ... arr ] */
35224 
35225 	DUK_DDD(DUK_DDDPRINT("parse_array: final array is %!T",
35226 	                     (duk_tval *) duk_get_tval(thr, -1)));
35227 
35228 	duk__dec_objarr_exit(js_ctx);
35229 	return;
35230 
35231  syntax_error:
35232 	duk__dec_syntax_error(js_ctx);
35233 	DUK_UNREACHABLE();
35234 }
35235 
duk__dec_value(duk_json_dec_ctx * js_ctx)35236 DUK_LOCAL void duk__dec_value(duk_json_dec_ctx *js_ctx) {
35237 	duk_hthread *thr = js_ctx->thr;
35238 	duk_uint8_t x;
35239 
35240 	x = duk__dec_get_nonwhite(js_ctx);
35241 
35242 	DUK_DDD(DUK_DDDPRINT("parse_value: initial x=%ld", (long) x));
35243 
35244 	/* Note: duk__dec_req_stridx() backtracks one char */
35245 
35246 	if (x == DUK_ASC_DOUBLEQUOTE) {
35247 		duk__dec_string(js_ctx);
35248 	} else if ((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x == DUK_ASC_MINUS)) {
35249 #if defined(DUK_USE_JX)
35250 		if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__dec_peek(js_ctx) == DUK_ASC_UC_I) {
35251 			duk__dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY);  /* "-Infinity", '-' has been eaten */
35252 			duk_push_number(thr, -DUK_DOUBLE_INFINITY);
35253 		} else {
35254 #else
35255 		{  /* unconditional block */
35256 #endif
35257 			/* We already ate 'x', so backup one byte. */
35258 			js_ctx->p--;  /* safe */
35259 			duk__dec_number(js_ctx);
35260 		}
35261 	} else if (x == DUK_ASC_LC_T) {
35262 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_TRUE);
35263 		duk_push_true(thr);
35264 	} else if (x == DUK_ASC_LC_F) {
35265 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_FALSE);
35266 		duk_push_false(thr);
35267 	} else if (x == DUK_ASC_LC_N) {
35268 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_NULL);
35269 		duk_push_null(thr);
35270 #if defined(DUK_USE_JX)
35271 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LC_U) {
35272 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_UNDEFINED);
35273 		duk_push_undefined(thr);
35274 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_N) {
35275 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_NAN);
35276 		duk_push_nan(thr);
35277 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_I) {
35278 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_INFINITY);
35279 		duk_push_number(thr, DUK_DOUBLE_INFINITY);
35280 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LPAREN) {
35281 		duk__dec_pointer(js_ctx);
35282 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_PIPE) {
35283 		duk__dec_buffer(js_ctx);
35284 #endif
35285 	} else if (x == DUK_ASC_LCURLY) {
35286 		duk__dec_object(js_ctx);
35287 	} else if (x == DUK_ASC_LBRACKET) {
35288 		duk__dec_array(js_ctx);
35289 	} else {
35290 		/* catches EOF (NUL) */
35291 		goto syntax_error;
35292 	}
35293 
35294 	duk__dec_eat_white(js_ctx);
35295 
35296 	/* [ ... val ] */
35297 	return;
35298 
35299  syntax_error:
35300 	duk__dec_syntax_error(js_ctx);
35301 	DUK_UNREACHABLE();
35302 }
35303 
35304 /* Recursive value reviver, implements the Walk() algorithm.  No C recursion
35305  * check is done here because the initial parsing step will already ensure
35306  * there is a reasonable limit on C recursion depth and hence object depth.
35307  */
35308 DUK_LOCAL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
35309 	duk_hthread *thr = js_ctx->thr;
35310 	duk_hobject *h;
35311 	duk_uarridx_t i, arr_len;
35312 
35313 	DUK_DDD(DUK_DDDPRINT("walk: top=%ld, holder=%!T, name=%!T",
35314 	                     (long) duk_get_top(thr),
35315 	                     (duk_tval *) duk_get_tval(thr, -2),
35316 	                     (duk_tval *) duk_get_tval(thr, -1)));
35317 
35318 	duk_dup_top(thr);
35319 	duk_get_prop(thr, -3);  /* -> [ ... holder name val ] */
35320 
35321 	h = duk_get_hobject(thr, -1);
35322 	if (h != NULL) {
35323 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
35324 			arr_len = (duk_uarridx_t) duk_get_length(thr, -1);
35325 			for (i = 0; i < arr_len; i++) {
35326 				/* [ ... holder name val ] */
35327 
35328 				DUK_DDD(DUK_DDDPRINT("walk: array, top=%ld, i=%ld, arr_len=%ld, holder=%!T, name=%!T, val=%!T",
35329 				                     (long) duk_get_top(thr), (long) i, (long) arr_len,
35330 				                     (duk_tval *) duk_get_tval(thr, -3), (duk_tval *) duk_get_tval(thr, -2),
35331 				                     (duk_tval *) duk_get_tval(thr, -1)));
35332 
35333 				duk_dup_top(thr);
35334 				(void) duk_push_uint_to_hstring(thr, (duk_uint_t) i);  /* -> [ ... holder name val val ToString(i) ] */
35335 				duk__dec_reviver_walk(js_ctx);  /* -> [ ... holder name val new_elem ] */
35336 
35337 				if (duk_is_undefined(thr, -1)) {
35338 					duk_pop(thr);
35339 					duk_del_prop_index(thr, -1, i);
35340 				} else {
35341 					/* XXX: duk_xdef_prop_index_wec() would be more appropriate
35342 					 * here but it currently makes some assumptions that might
35343 					 * not hold (e.g. that previous property is not an accessor).
35344 					 */
35345 					duk_put_prop_index(thr, -2, i);
35346 				}
35347 			}
35348 		} else {
35349 			/* [ ... holder name val ] */
35350 			duk_enum(thr, -1, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);
35351 			while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
35352 				DUK_DDD(DUK_DDDPRINT("walk: object, top=%ld, holder=%!T, name=%!T, val=%!T, enum=%!iT, obj_key=%!T",
35353 				                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -5),
35354 				                     (duk_tval *) duk_get_tval(thr, -4), (duk_tval *) duk_get_tval(thr, -3),
35355 				                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
35356 
35357 				/* [ ... holder name val enum obj_key ] */
35358 				duk_dup_m3(thr);
35359 				duk_dup_m2(thr);
35360 
35361 				/* [ ... holder name val enum obj_key val obj_key ] */
35362 				duk__dec_reviver_walk(js_ctx);
35363 
35364 				/* [ ... holder name val enum obj_key new_elem ] */
35365 				if (duk_is_undefined(thr, -1)) {
35366 					duk_pop(thr);
35367 					duk_del_prop(thr, -3);
35368 				} else {
35369 					/* XXX: duk_xdef_prop_index_wec() would be more appropriate
35370 					 * here but it currently makes some assumptions that might
35371 					 * not hold (e.g. that previous property is not an accessor).
35372 					 *
35373 					 * Using duk_put_prop() works incorrectly with '__proto__'
35374 					 * if the own property with that name has been deleted.  This
35375 					 * does not happen normally, but a clever reviver can trigger
35376 					 * that, see complex reviver case in: test-bug-json-parse-__proto__.js.
35377 					 */
35378 					duk_put_prop(thr, -4);
35379 				}
35380 			}
35381 			duk_pop(thr);  /* pop enum */
35382 		}
35383 	}
35384 
35385 	/* [ ... holder name val ] */
35386 
35387 	duk_dup(thr, js_ctx->idx_reviver);
35388 	duk_insert(thr, -4);  /* -> [ ... reviver holder name val ] */
35389 	duk_call_method(thr, 2);  /* -> [ ... res ] */
35390 
35391 	DUK_DDD(DUK_DDDPRINT("walk: top=%ld, result=%!T",
35392 	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -1)));
35393 }
35394 
35395 /*
35396  *  Stringify implementation.
35397  */
35398 
35399 #define DUK__EMIT_1(js_ctx,ch)          duk__emit_1((js_ctx), (duk_uint_fast8_t) (ch))
35400 #define DUK__EMIT_2(js_ctx,ch1,ch2)     duk__emit_2((js_ctx), (duk_uint_fast8_t) (ch1), (duk_uint_fast8_t) (ch2))
35401 #define DUK__EMIT_HSTR(js_ctx,h)        duk__emit_hstring((js_ctx), (h))
35402 #if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
35403 #define DUK__EMIT_CSTR(js_ctx,p)        duk__emit_cstring((js_ctx), (p))
35404 #endif
35405 #define DUK__EMIT_STRIDX(js_ctx,i)      duk__emit_stridx((js_ctx), (i))
35406 #define DUK__UNEMIT_1(js_ctx)           duk__unemit_1((js_ctx))
35407 
35408 DUK_LOCAL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch) {
35409 	DUK_BW_WRITE_ENSURE_U8(js_ctx->thr, &js_ctx->bw, ch);
35410 }
35411 
35412 DUK_LOCAL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2) {
35413 	DUK_BW_WRITE_ENSURE_U8_2(js_ctx->thr, &js_ctx->bw, ch1, ch2);
35414 }
35415 
35416 DUK_LOCAL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h) {
35417 	DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
35418 }
35419 
35420 #if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
35421 DUK_LOCAL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *str) {
35422 	DUK_BW_WRITE_ENSURE_CSTRING(js_ctx->thr, &js_ctx->bw, str);
35423 }
35424 #endif
35425 
35426 DUK_LOCAL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx) {
35427 	duk_hstring *h;
35428 
35429 	DUK_ASSERT_STRIDX_VALID(stridx);
35430 	h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
35431 	DUK_ASSERT(h != NULL);
35432 
35433 	DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
35434 }
35435 
35436 DUK_LOCAL void duk__unemit_1(duk_json_enc_ctx *js_ctx) {
35437 	DUK_ASSERT(DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw) >= 1);
35438 	DUK_BW_ADD_PTR(js_ctx->thr, &js_ctx->bw, -1);
35439 }
35440 
35441 #define DUK__MKESC(nybbles,esc1,esc2)  \
35442 	(((duk_uint_fast32_t) (nybbles)) << 16) | \
35443 	(((duk_uint_fast32_t) (esc1)) << 8) | \
35444 	((duk_uint_fast32_t) (esc2))
35445 
35446 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) {
35447 	duk_uint_fast32_t tmp;
35448 	duk_small_uint_t dig;
35449 
35450 	DUK_UNREF(js_ctx);
35451 
35452 	/* Caller ensures space for at least DUK__JSON_MAX_ESC_LEN. */
35453 
35454 	/* Select appropriate escape format automatically, and set 'tmp' to a
35455 	 * value encoding both the escape format character and the nybble count:
35456 	 *
35457 	 *   (nybble_count << 16) | (escape_char1) | (escape_char2)
35458 	 */
35459 
35460 #if defined(DUK_USE_JX)
35461 	if (DUK_LIKELY(cp < 0x100UL)) {
35462 		if (DUK_UNLIKELY(js_ctx->flag_ext_custom != 0U)) {
35463 			tmp = DUK__MKESC(2, DUK_ASC_BACKSLASH, DUK_ASC_LC_X);
35464 		} else {
35465 			tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);
35466 		}
35467 	} else
35468 #endif
35469 	if (DUK_LIKELY(cp < 0x10000UL)) {
35470 		tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);
35471 	} else {
35472 #if defined(DUK_USE_JX)
35473 		if (DUK_LIKELY(js_ctx->flag_ext_custom != 0U)) {
35474 			tmp = DUK__MKESC(8, DUK_ASC_BACKSLASH, DUK_ASC_UC_U);
35475 		} else
35476 #endif
35477 		{
35478 			/* In compatible mode and standard JSON mode, output
35479 			 * something useful for non-BMP characters.  This won't
35480 			 * roundtrip but will still be more or less readable and
35481 			 * more useful than an error.
35482 			 */
35483 			tmp = DUK__MKESC(8, DUK_ASC_UC_U, DUK_ASC_PLUS);
35484 		}
35485 	}
35486 
35487 	*q++ = (duk_uint8_t) ((tmp >> 8) & 0xff);
35488 	*q++ = (duk_uint8_t) (tmp & 0xff);
35489 
35490 	tmp = tmp >> 16;
35491 	while (tmp > 0) {
35492 		tmp--;
35493 		dig = (duk_small_uint_t) ((cp >> (4 * tmp)) & 0x0f);
35494 		*q++ = duk_lc_digits[dig];
35495 	}
35496 
35497 	return q;
35498 }
35499 
35500 DUK_LOCAL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) {
35501 	const duk_int8_t *p, *p_start, *p_end;  /* Note: intentionally signed. */
35502 	duk_size_t k_len;
35503 	duk_codepoint_t cp;
35504 
35505 	DUK_ASSERT(k != NULL);
35506 
35507 	/* Accept ASCII strings which conform to identifier requirements
35508 	 * as being emitted without key quotes.  Since we only accept ASCII
35509 	 * there's no need for actual decoding: 'p' is intentionally signed
35510 	 * so that bytes >= 0x80 extend to negative values and are rejected
35511 	 * as invalid identifier codepoints.
35512 	 */
35513 
35514 	if (js_ctx->flag_avoid_key_quotes) {
35515 		k_len = DUK_HSTRING_GET_BYTELEN(k);
35516 		p_start = (const duk_int8_t *) DUK_HSTRING_GET_DATA(k);
35517 		p_end = p_start + k_len;
35518 		p = p_start;
35519 
35520 		if (p == p_end) {
35521 			/* Zero length string is not accepted without quotes */
35522 			goto quote_normally;
35523 		}
35524 		cp = (duk_codepoint_t) (*p++);
35525 		if (DUK_UNLIKELY(!duk_unicode_is_identifier_start(cp))) {
35526 			goto quote_normally;
35527 		}
35528 		while (p < p_end) {
35529 			cp = (duk_codepoint_t) (*p++);
35530 			if (DUK_UNLIKELY(!duk_unicode_is_identifier_part(cp))) {
35531 				goto quote_normally;
35532 			}
35533 		}
35534 
35535 		/* This seems faster than emitting bytes one at a time and
35536 		 * then potentially rewinding.
35537 		 */
35538 		DUK__EMIT_HSTR(js_ctx, k);
35539 		return;
35540 	}
35541 
35542  quote_normally:
35543 	duk__enc_quote_string(js_ctx, k);
35544 }
35545 
35546 /* The Quote(value) operation: quote a string.
35547  *
35548  * Stack policy: [ ] -> [ ].
35549  */
35550 
35551 DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) {
35552 	duk_hthread *thr = js_ctx->thr;
35553 	const duk_uint8_t *p, *p_start, *p_end, *p_now, *p_tmp;
35554 	duk_uint8_t *q;
35555 	duk_ucodepoint_t cp;  /* typed for duk_unicode_decode_xutf8() */
35556 
35557 	DUK_DDD(DUK_DDDPRINT("duk__enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str));
35558 
35559 	DUK_ASSERT(h_str != NULL);
35560 	p_start = DUK_HSTRING_GET_DATA(h_str);
35561 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_str);
35562 	p = p_start;
35563 
35564 	DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);
35565 
35566 	/* Encode string in small chunks, estimating the maximum expansion so that
35567 	 * there's no need to ensure space while processing the chunk.
35568 	 */
35569 
35570 	while (p < p_end) {
35571 		duk_size_t left, now, space;
35572 
35573 		left = (duk_size_t) (p_end - p);
35574 		now = (left > DUK__JSON_ENCSTR_CHUNKSIZE ?
35575 		       DUK__JSON_ENCSTR_CHUNKSIZE : left);
35576 
35577 		/* Maximum expansion per input byte is 6:
35578 		 *   - invalid UTF-8 byte causes "\uXXXX" to be emitted (6/1 = 6).
35579 		 *   - 2-byte UTF-8 encodes as "\uXXXX" (6/2 = 3).
35580 		 *   - 4-byte UTF-8 encodes as "\Uxxxxxxxx" (10/4 = 2.5).
35581 		 */
35582 		space = now * 6;
35583 		q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
35584 
35585 		p_now = p + now;
35586 
35587 		while (p < p_now) {
35588 #if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
35589 			duk_uint8_t b;
35590 
35591 			b = duk__json_quotestr_lookup[*p++];
35592 			if (DUK_LIKELY(b < 0x80)) {
35593 				/* Most input bytes go through here. */
35594 				*q++ = b;
35595 			} else if (b >= 0xa0) {
35596 				*q++ = DUK_ASC_BACKSLASH;
35597 				*q++ = (duk_uint8_t) (b - 0x80);
35598 			} else if (b == 0x80) {
35599 				cp = (duk_ucodepoint_t) (*(p - 1));
35600 				q = duk__emit_esc_auto_fast(js_ctx, cp, q);
35601 			} else if (b == 0x7f && js_ctx->flag_ascii_only) {
35602 				/* 0x7F is special */
35603 				DUK_ASSERT(b == 0x81);
35604 				cp = (duk_ucodepoint_t) 0x7f;
35605 				q = duk__emit_esc_auto_fast(js_ctx, cp, q);
35606 			} else {
35607 				DUK_ASSERT(b == 0x81);
35608 				p--;
35609 
35610 				/* slow path is shared */
35611 #else  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
35612 			cp = *p;
35613 
35614 			if (DUK_LIKELY(cp <= 0x7f)) {
35615 				/* ascii fast path: avoid decoding utf-8 */
35616 				p++;
35617 				if (cp == 0x22 || cp == 0x5c) {
35618 					/* double quote or backslash */
35619 					*q++ = DUK_ASC_BACKSLASH;
35620 					*q++ = (duk_uint8_t) cp;
35621 				} else if (cp < 0x20) {
35622 					duk_uint_fast8_t esc_char;
35623 
35624 					/* This approach is a bit shorter than a straight
35625 					 * if-else-ladder and also a bit faster.
35626 					 */
35627 					if (cp < (sizeof(duk__json_quotestr_esc) / sizeof(duk_uint8_t)) &&
35628 					    (esc_char = duk__json_quotestr_esc[cp]) != 0) {
35629 						*q++ = DUK_ASC_BACKSLASH;
35630 						*q++ = (duk_uint8_t) esc_char;
35631 					} else {
35632 						q = duk__emit_esc_auto_fast(js_ctx, cp, q);
35633 					}
35634 				} else if (cp == 0x7f && js_ctx->flag_ascii_only) {
35635 					q = duk__emit_esc_auto_fast(js_ctx, cp, q);
35636 				} else {
35637 					/* any other printable -> as is */
35638 					*q++ = (duk_uint8_t) cp;
35639 				}
35640 			} else {
35641 				/* slow path is shared */
35642 #endif  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
35643 
35644 				/* slow path decode */
35645 
35646 				/* If XUTF-8 decoding fails, treat the offending byte as a codepoint directly
35647 				 * and go forward one byte.  This is of course very lossy, but allows some kind
35648 				 * of output to be produced even for internal strings which don't conform to
35649 				 * XUTF-8.  All standard ECMAScript strings are always CESU-8, so this behavior
35650 				 * does not violate the ECMAScript specification.  The behavior is applied to
35651 				 * all modes, including ECMAScript standard JSON.  Because the current XUTF-8
35652 				 * decoding is not very strict, this behavior only really affects initial bytes
35653 				 * and truncated codepoints.
35654 				 *
35655 				 * Another alternative would be to scan forwards to start of next codepoint
35656 				 * (or end of input) and emit just one replacement codepoint.
35657 				 */
35658 
35659 				p_tmp = p;
35660 				if (!duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
35661 					/* Decode failed. */
35662 					cp = *p_tmp;
35663 					p = p_tmp + 1;
35664 				}
35665 
35666 #if defined(DUK_USE_NONSTD_JSON_ESC_U2028_U2029)
35667 				if (js_ctx->flag_ascii_only || cp == 0x2028 || cp == 0x2029) {
35668 #else
35669 				if (js_ctx->flag_ascii_only) {
35670 #endif
35671 					q = duk__emit_esc_auto_fast(js_ctx, cp, q);
35672 				} else {
35673 					/* as is */
35674 					DUK_RAW_WRITE_XUTF8(q, cp);
35675 				}
35676 			}
35677 		}
35678 
35679 		DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
35680 	}
35681 
35682 	DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);
35683 }
35684 
35685 /* Encode a double (checked by caller) from stack top.  Stack top may be
35686  * replaced by serialized string but is not popped (caller does that).
35687  */
35688 DUK_LOCAL void duk__enc_double(duk_json_enc_ctx *js_ctx) {
35689 	duk_hthread *thr;
35690 	duk_tval *tv;
35691 	duk_double_t d;
35692 	duk_small_int_t c;
35693 	duk_small_int_t s;
35694 	duk_small_uint_t stridx;
35695 	duk_small_uint_t n2s_flags;
35696 	duk_hstring *h_str;
35697 
35698 	DUK_ASSERT(js_ctx != NULL);
35699 	thr = js_ctx->thr;
35700 	DUK_ASSERT(thr != NULL);
35701 
35702 	/* Caller must ensure 'tv' is indeed a double and not a fastint! */
35703 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
35704 	DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
35705 	d = DUK_TVAL_GET_DOUBLE(tv);
35706 
35707 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
35708 	s = (duk_small_int_t) DUK_SIGNBIT(d);
35709 	DUK_UNREF(s);
35710 
35711 	if (DUK_LIKELY(!(c == DUK_FP_INFINITE || c == DUK_FP_NAN))) {
35712 		DUK_ASSERT(DUK_ISFINITE(d));
35713 
35714 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
35715 		/* Negative zero needs special handling in JX/JC because
35716 		 * it would otherwise serialize to '0', not '-0'.
35717 		 */
35718 		if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 &&
35719 		                 (js_ctx->flag_ext_custom_or_compatible))) {
35720 			duk_push_hstring_stridx(thr, DUK_STRIDX_MINUS_ZERO);  /* '-0' */
35721 		} else
35722 #endif  /* DUK_USE_JX || DUK_USE_JC */
35723 		{
35724 			n2s_flags = 0;
35725 			/* [ ... number ] -> [ ... string ] */
35726 			duk_numconv_stringify(thr, 10 /*radix*/, 0 /*digits*/, n2s_flags);
35727 		}
35728 		h_str = duk_known_hstring(thr, -1);
35729 		DUK__EMIT_HSTR(js_ctx, h_str);
35730 		return;
35731 	}
35732 
35733 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
35734 	if (!(js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
35735 	                       DUK_JSON_FLAG_EXT_COMPATIBLE))) {
35736 		stridx = DUK_STRIDX_LC_NULL;
35737 	} else if (c == DUK_FP_NAN) {
35738 		stridx = js_ctx->stridx_custom_nan;
35739 	} else if (s == 0) {
35740 		stridx = js_ctx->stridx_custom_posinf;
35741 	} else {
35742 		stridx = js_ctx->stridx_custom_neginf;
35743 	}
35744 #else
35745 	stridx = DUK_STRIDX_LC_NULL;
35746 #endif
35747 	DUK__EMIT_STRIDX(js_ctx, stridx);
35748 }
35749 
35750 #if defined(DUK_USE_FASTINT)
35751 /* Encode a fastint from duk_tval ptr, no value stack effects. */
35752 DUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
35753 	duk_int64_t v;
35754 
35755 	/* Fastint range is signed 48-bit so longest value is -2^47 = -140737488355328
35756 	 * (16 chars long), longest signed 64-bit value is -2^63 = -9223372036854775808
35757 	 * (20 chars long).  Alloc space for 64-bit range to be safe.
35758 	 */
35759 	duk_uint8_t buf[20 + 1];
35760 
35761 	/* Caller must ensure 'tv' is indeed a fastint! */
35762 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
35763 	v = DUK_TVAL_GET_FASTINT(tv);
35764 
35765 	/* XXX: There are no format strings in duk_config.h yet, could add
35766 	 * one for formatting duk_int64_t.  For now, assumes "%lld" and that
35767 	 * "long long" type exists.  Could also rely on C99 directly but that
35768 	 * won't work for older MSVC.
35769 	 */
35770 	/*DUK_SPRINTF((char *) buf, "%lld", (long long) v);*/
35771 	DUK_SPRINTF((char *) buf, "%"PRIsizet, (size_t) v);
35772 	DUK__EMIT_CSTR(js_ctx, (const char *) buf);
35773 }
35774 #endif
35775 
35776 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
35777 #if defined(DUK_USE_HEX_FASTPATH)
35778 DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
35779 	duk_uint8_t *q;
35780 	duk_uint16_t *q16;
35781 	duk_small_uint_t x;
35782 	duk_size_t i, len_safe;
35783 #if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
35784 	duk_bool_t shift_dst;
35785 #endif
35786 
35787 	/* Unlike in duk_hex_encode() 'dst' is not necessarily aligned by 2.
35788 	 * For platforms where unaligned accesses are not allowed, shift 'dst'
35789 	 * ahead by 1 byte to get alignment and then duk_memmove() the result
35790 	 * in place.  The faster encoding loop makes up the difference.
35791 	 * There's always space for one extra byte because a terminator always
35792 	 * follows the hex data and that's been accounted for by the caller.
35793 	 */
35794 
35795 #if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
35796 	q16 = (duk_uint16_t *) (void *) dst;
35797 #else
35798 	shift_dst = (duk_bool_t) (((duk_size_t) dst) & 0x01U);
35799 	if (shift_dst) {
35800 		DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst not aligned -> step to dst + 1"));
35801 		q16 = (duk_uint16_t *) (void *) (dst + 1);
35802 	} else {
35803 		DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst is aligned"));
35804 		q16 = (duk_uint16_t *) (void *) dst;
35805 	}
35806 	DUK_ASSERT((((duk_size_t) q16) & 0x01U) == 0);
35807 #endif
35808 
35809 	len_safe = src_len & ~0x03U;
35810 	for (i = 0; i < len_safe; i += 4) {
35811 		q16[0] = duk_hex_enctab[src[i]];
35812 		q16[1] = duk_hex_enctab[src[i + 1]];
35813 		q16[2] = duk_hex_enctab[src[i + 2]];
35814 		q16[3] = duk_hex_enctab[src[i + 3]];
35815 		q16 += 4;
35816 	}
35817 	q = (duk_uint8_t *) q16;
35818 
35819 #if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
35820 	if (shift_dst) {
35821 		q--;
35822 		duk_memmove((void *) dst, (const void *) (dst + 1), 2 * len_safe);
35823 		DUK_ASSERT(dst + 2 * len_safe == q);
35824 	}
35825 #endif
35826 
35827 	for (; i < src_len; i++) {
35828 		x = src[i];
35829 		*q++ = duk_lc_digits[x >> 4];
35830 		*q++ = duk_lc_digits[x & 0x0f];
35831 	}
35832 
35833 	return q;
35834 }
35835 #else  /* DUK_USE_HEX_FASTPATH */
35836 DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
35837 	const duk_uint8_t *p;
35838 	const duk_uint8_t *p_end;
35839 	duk_uint8_t *q;
35840 	duk_small_uint_t x;
35841 
35842 	p = src;
35843 	p_end = src + src_len;
35844 	q = dst;
35845 	while (p != p_end) {
35846 		x = *p++;
35847 		*q++ = duk_lc_digits[x >> 4];
35848 		*q++ = duk_lc_digits[x & 0x0f];
35849 	}
35850 
35851 	return q;
35852 }
35853 #endif  /* DUK_USE_HEX_FASTPATH */
35854 
35855 DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) {
35856 	duk_hthread *thr;
35857 	duk_uint8_t *q;
35858 	duk_size_t space;
35859 
35860 	thr = js_ctx->thr;
35861 
35862 	DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);  /* caller checks */
35863 	DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
35864 
35865 	/* Buffer values are encoded in (lowercase) hex to make the
35866 	 * binary data readable.  Base64 or similar would be more
35867 	 * compact but less readable, and the point of JX/JC
35868 	 * variants is to be as useful to a programmer as possible.
35869 	 */
35870 
35871 	/* The #if defined() clutter here needs to handle the three
35872 	 * cases: (1) JX+JC, (2) JX only, (3) JC only.
35873 	 */
35874 
35875 	/* Note: space must cater for both JX and JC. */
35876 	space = 9 + buf_len * 2 + 2;
35877 	DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7ffffffeUL);
35878 	DUK_ASSERT((space - 2) / 2 >= buf_len);  /* overflow not possible, buffer limits */
35879 	q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
35880 
35881 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
35882 	if (js_ctx->flag_ext_custom)
35883 #endif
35884 #if defined(DUK_USE_JX)
35885 	{
35886 		*q++ = DUK_ASC_PIPE;
35887 		q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
35888 		*q++ = DUK_ASC_PIPE;
35889 
35890 	}
35891 #endif
35892 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
35893 	else
35894 #endif
35895 #if defined(DUK_USE_JC)
35896 	{
35897 		DUK_ASSERT(js_ctx->flag_ext_compatible);
35898 		duk_memcpy((void *) q, (const void *) "{\"_buf\":\"", 9);  /* len: 9 */
35899 		q += 9;
35900 		q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
35901 		*q++ = DUK_ASC_DOUBLEQUOTE;
35902 		*q++ = DUK_ASC_RCURLY;
35903 	}
35904 #endif
35905 
35906 	DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
35907 }
35908 
35909 DUK_LOCAL void duk__enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
35910 	duk__enc_buffer_data(js_ctx,
35911 	                     (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h),
35912 	                     (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
35913 }
35914 #endif  /* DUK_USE_JX || DUK_USE_JC */
35915 
35916 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
35917 DUK_LOCAL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
35918 	duk_size_t i, n;
35919 	const duk_uint8_t *buf;
35920 	duk_uint8_t *q;
35921 
35922 	n = DUK_HBUFFER_GET_SIZE(h);
35923 	if (n == 0) {
35924 		DUK__EMIT_2(js_ctx, DUK_ASC_LCURLY, DUK_ASC_RCURLY);
35925 		return;
35926 	}
35927 
35928 	DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
35929 
35930 	/* Maximum encoded length with 32-bit index: 1 + 10 + 2 + 3 + 1 + 1 = 18,
35931 	 * with 64-bit index: 1 + 20 + 2 + 3 + 1 + 1 = 28.  32 has some slack.
35932 	 *
35933 	 * Note that because the output buffer is reallocated from time to time,
35934 	 * side effects (such as finalizers) affecting the buffer 'h' must be
35935 	 * disabled.  This is the case in the JSON.stringify() fast path.
35936 	 */
35937 
35938 	buf = (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h);
35939 	if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
35940 		for (i = 0; i < n; i++) {
35941 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth + 1);
35942 			q = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, 32);
35943 			q += DUK_SPRINTF((char *) q, "\"%lu\": %u,", (unsigned long) i, (unsigned int) buf[i]);
35944 			DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);
35945 		}
35946 	} else {
35947 		q = DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw);
35948 		for (i = 0; i < n; i++) {
35949 			q = DUK_BW_ENSURE_RAW(js_ctx->thr, &js_ctx->bw, 32, q);
35950 			q += DUK_SPRINTF((char *) q, "\"%lu\":%u,", (unsigned long) i, (unsigned int) buf[i]);
35951 		}
35952 		DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);
35953 	}
35954 	DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
35955 
35956 	if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
35957 		duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
35958 	}
35959 	DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
35960 }
35961 #endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */
35962 
35963 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
35964 DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {
35965 	char buf[64];  /* XXX: how to figure correct size? */
35966 	const char *fmt;
35967 
35968 	DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);  /* caller checks */
35969 	DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
35970 
35971 	duk_memzero(buf, sizeof(buf));
35972 
35973 	/* The #if defined() clutter here needs to handle the three
35974 	 * cases: (1) JX+JC, (2) JX only, (3) JC only.
35975 	 */
35976 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
35977 	if (js_ctx->flag_ext_custom)
35978 #endif
35979 #if defined(DUK_USE_JX)
35980 	{
35981 		fmt = ptr ? "(%p)" : "(null)";
35982 	}
35983 #endif
35984 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
35985 	else
35986 #endif
35987 #if defined(DUK_USE_JC)
35988 	{
35989 		DUK_ASSERT(js_ctx->flag_ext_compatible);
35990 		fmt = ptr ? "{\"_ptr\":\"%p\"}" : "{\"_ptr\":\"null\"}";
35991 	}
35992 #endif
35993 
35994 	/* When ptr == NULL, the format argument is unused. */
35995 	DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr);  /* must not truncate */
35996 	DUK__EMIT_CSTR(js_ctx, buf);
35997 }
35998 #endif  /* DUK_USE_JX || DUK_USE_JC */
35999 
36000 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
36001 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36002 DUK_LOCAL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj) {
36003 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
36004 
36005 	if (h_bufobj->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
36006 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
36007 	} else {
36008 		/* Handle both full and partial slice (as long as covered). */
36009 		duk__enc_buffer_data(js_ctx,
36010 		                     (duk_uint8_t *) DUK_HBUFOBJ_GET_SLICE_BASE(js_ctx->thr->heap, h_bufobj),
36011 		                     (duk_size_t) h_bufobj->length);
36012 	}
36013 }
36014 #endif  /* DUK_USE_JX || DUK_USE_JC */
36015 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
36016 
36017 /* Indent helper.  Calling code relies on js_ctx->recursion_depth also being
36018  * directly related to indent depth.
36019  */
36020 #if defined(DUK_USE_PREFER_SIZE)
36021 DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
36022 	DUK_ASSERT(js_ctx->h_gap != NULL);
36023 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */
36024 
36025 	DUK__EMIT_1(js_ctx, 0x0a);
36026 	while (depth-- > 0) {
36027 		DUK__EMIT_HSTR(js_ctx, js_ctx->h_gap);
36028 	}
36029 }
36030 #else  /* DUK_USE_PREFER_SIZE */
36031 DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
36032 	const duk_uint8_t *gap_data;
36033 	duk_size_t gap_len;
36034 	duk_size_t avail_bytes;   /* bytes of indent available for copying */
36035 	duk_size_t need_bytes;    /* bytes of indent still needed */
36036 	duk_uint8_t *p_start;
36037 	duk_uint8_t *p;
36038 
36039 	DUK_ASSERT(js_ctx->h_gap != NULL);
36040 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */
36041 
36042 	DUK__EMIT_1(js_ctx, 0x0a);
36043 	if (DUK_UNLIKELY(depth == 0)) {
36044 		return;
36045 	}
36046 
36047 	/* To handle deeper indents efficiently, make use of copies we've
36048 	 * already emitted.  In effect we can emit a sequence of 1, 2, 4,
36049 	 * 8, etc copies, and then finish the last run.  Byte counters
36050 	 * avoid multiply with gap_len on every loop.
36051 	 */
36052 
36053 	gap_data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(js_ctx->h_gap);
36054 	gap_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap);
36055 	DUK_ASSERT(gap_len > 0);
36056 
36057 	need_bytes = gap_len * depth;
36058 	p = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, need_bytes);
36059 	p_start = p;
36060 
36061 	duk_memcpy((void *) p, (const void *) gap_data, (size_t) gap_len);
36062 	p += gap_len;
36063 	avail_bytes = gap_len;
36064 	DUK_ASSERT(need_bytes >= gap_len);
36065 	need_bytes -= gap_len;
36066 
36067 	while (need_bytes >= avail_bytes) {
36068 		duk_memcpy((void *) p, (const void *) p_start, (size_t) avail_bytes);
36069 		p += avail_bytes;
36070 		need_bytes -= avail_bytes;
36071 		avail_bytes <<= 1;
36072 	}
36073 
36074 	DUK_ASSERT(need_bytes < avail_bytes);  /* need_bytes may be zero */
36075 	duk_memcpy((void *) p, (const void *) p_start, (size_t) need_bytes);
36076 	p += need_bytes;
36077 	/*avail_bytes += need_bytes*/
36078 
36079 	DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, p);
36080 }
36081 #endif  /* DUK_USE_PREFER_SIZE */
36082 
36083 /* Shared entry handling for object/array serialization. */
36084 DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
36085 	duk_hthread *thr = js_ctx->thr;
36086 	duk_hobject *h_target;
36087 	duk_uint_fast32_t i, n;
36088 
36089 	*entry_top = duk_get_top(thr);
36090 
36091 	duk_require_stack(thr, DUK_JSON_ENC_REQSTACK);
36092 
36093 	/* Loop check using a hybrid approach: a fixed-size visited[] array
36094 	 * with overflow in a loop check object.
36095 	 */
36096 
36097 	h_target = duk_known_hobject(thr, -1);  /* object or array */
36098 
36099 	n = js_ctx->recursion_depth;
36100 	if (DUK_UNLIKELY(n > DUK_JSON_ENC_LOOPARRAY)) {
36101 		n = DUK_JSON_ENC_LOOPARRAY;
36102 	}
36103 	for (i = 0; i < n; i++) {
36104 		if (DUK_UNLIKELY(js_ctx->visiting[i] == h_target)) {
36105 			DUK_DD(DUK_DDPRINT("slow path loop detect"));
36106 			DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT);
36107 			DUK_WO_NORETURN(return;);
36108 		}
36109 	}
36110 	if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
36111 		js_ctx->visiting[js_ctx->recursion_depth] = h_target;
36112 	} else {
36113 		duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target);
36114 		duk_dup_top(thr);  /* -> [ ... voidp voidp ] */
36115 		if (duk_has_prop(thr, js_ctx->idx_loop)) {
36116 			DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT);
36117 			DUK_WO_NORETURN(return;);
36118 		}
36119 		duk_push_true(thr);  /* -> [ ... voidp true ] */
36120 		duk_put_prop(thr, js_ctx->idx_loop);  /* -> [ ... ] */
36121 	}
36122 
36123 	/* C recursion check. */
36124 
36125 	DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
36126 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
36127 	if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
36128 		DUK_ERROR_RANGE(thr, DUK_STR_JSONENC_RECLIMIT);
36129 		DUK_WO_NORETURN(return;);
36130 	}
36131 	js_ctx->recursion_depth++;
36132 
36133 	DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
36134 	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));
36135 }
36136 
36137 /* Shared exit handling for object/array serialization. */
36138 DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
36139 	duk_hthread *thr = js_ctx->thr;
36140 	duk_hobject *h_target;
36141 
36142 	/* C recursion check. */
36143 
36144 	DUK_ASSERT(js_ctx->recursion_depth > 0);
36145 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
36146 	js_ctx->recursion_depth--;
36147 
36148 	/* Loop check. */
36149 
36150 	h_target = duk_known_hobject(thr, *entry_top - 1);  /* original target at entry_top - 1 */
36151 
36152 	if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
36153 		/* Previous entry was inside visited[], nothing to do. */
36154 	} else {
36155 		duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target);
36156 		duk_del_prop(thr, js_ctx->idx_loop);  /* -> [ ... ] */
36157 	}
36158 
36159 	/* Restore stack top after unbalanced code paths. */
36160 	duk_set_top(thr, *entry_top);
36161 
36162 	DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
36163 	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));
36164 }
36165 
36166 /* The JO(value) operation: encode object.
36167  *
36168  * Stack policy: [ object ] -> [ object ].
36169  */
36170 DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
36171 	duk_hthread *thr = js_ctx->thr;
36172 	duk_hstring *h_key;
36173 	duk_idx_t entry_top;
36174 	duk_idx_t idx_obj;
36175 	duk_idx_t idx_keys;
36176 	duk_bool_t emitted;
36177 	duk_uarridx_t arr_len, i;
36178 	duk_size_t prev_size;
36179 
36180 	DUK_DDD(DUK_DDDPRINT("duk__enc_object: obj=%!T", (duk_tval *) duk_get_tval(thr, -1)));
36181 
36182 	duk__enc_objarr_entry(js_ctx, &entry_top);
36183 
36184 	idx_obj = entry_top - 1;
36185 
36186 	if (js_ctx->idx_proplist >= 0) {
36187 		idx_keys = js_ctx->idx_proplist;
36188 	} else {
36189 		/* XXX: would be nice to enumerate an object at specified index */
36190 		duk_dup(thr, idx_obj);
36191 		(void) duk_hobject_get_enumerated_keys(thr, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);  /* [ ... target ] -> [ ... target keys ] */
36192 		idx_keys = duk_require_normalize_index(thr, -1);
36193 		/* leave stack unbalanced on purpose */
36194 	}
36195 
36196 	DUK_DDD(DUK_DDDPRINT("idx_keys=%ld, h_keys=%!T",
36197 	                     (long) idx_keys, (duk_tval *) duk_get_tval(thr, idx_keys)));
36198 
36199 	/* Steps 8-10 have been merged to avoid a "partial" variable. */
36200 
36201 	DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
36202 
36203 	/* XXX: keys is an internal object with all keys to be processed
36204 	 * in its (gapless) array part.  Because nobody can touch the keys
36205 	 * object, we could iterate its array part directly (keeping in mind
36206 	 * that it can be reallocated).
36207 	 */
36208 
36209 	arr_len = (duk_uarridx_t) duk_get_length(thr, idx_keys);
36210 	emitted = 0;
36211 	for (i = 0; i < arr_len; i++) {
36212 		duk_get_prop_index(thr, idx_keys, i);  /* -> [ ... key ] */
36213 
36214 		DUK_DDD(DUK_DDDPRINT("object property loop: holder=%!T, key=%!T",
36215 		                     (duk_tval *) duk_get_tval(thr, idx_obj),
36216 		                     (duk_tval *) duk_get_tval(thr, -1)));
36217 
36218 		h_key = duk_known_hstring(thr, -1);
36219 		DUK_ASSERT(h_key != NULL);
36220 		DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(h_key));  /* proplist filtering; enum options */
36221 
36222 		prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
36223 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36224 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
36225 			duk__enc_key_autoquote(js_ctx, h_key);
36226 			DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
36227 		} else {
36228 			duk__enc_key_autoquote(js_ctx, h_key);
36229 			DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
36230 		}
36231 
36232 		/* [ ... key ] */
36233 
36234 		if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_obj) == 0)) {
36235 			/* Value would yield 'undefined', so skip key altogether.
36236 			 * Side effects have already happened.
36237 			 */
36238 			DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
36239 		} else {
36240 			DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
36241 			emitted = 1;
36242 		}
36243 
36244 		/* [ ... ] */
36245 	}
36246 
36247 	if (emitted) {
36248 		DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
36249 		DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
36250 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36251 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
36252 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
36253 		}
36254 	}
36255 	DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
36256 
36257 	duk__enc_objarr_exit(js_ctx, &entry_top);
36258 
36259 	DUK_ASSERT_TOP(thr, entry_top);
36260 }
36261 
36262 /* The JA(value) operation: encode array.
36263  *
36264  * Stack policy: [ array ] -> [ array ].
36265  */
36266 DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) {
36267 	duk_hthread *thr = js_ctx->thr;
36268 	duk_idx_t entry_top;
36269 	duk_idx_t idx_arr;
36270 	duk_bool_t emitted;
36271 	duk_uarridx_t i, arr_len;
36272 
36273 	DUK_DDD(DUK_DDDPRINT("duk__enc_array: array=%!T",
36274 	                     (duk_tval *) duk_get_tval(thr, -1)));
36275 
36276 	duk__enc_objarr_entry(js_ctx, &entry_top);
36277 
36278 	idx_arr = entry_top - 1;
36279 
36280 	/* Steps 8-10 have been merged to avoid a "partial" variable. */
36281 
36282 	DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);
36283 
36284 	arr_len = (duk_uarridx_t) duk_get_length(thr, idx_arr);
36285 	emitted = 0;
36286 	for (i = 0; i < arr_len; i++) {
36287 		DUK_DDD(DUK_DDDPRINT("array entry loop: array=%!T, index=%ld, arr_len=%ld",
36288 		                     (duk_tval *) duk_get_tval(thr, idx_arr),
36289 		                     (long) i, (long) arr_len));
36290 
36291 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36292 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
36293 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
36294 		}
36295 
36296 		(void) duk_push_uint_to_hstring(thr, (duk_uint_t) i);  /* -> [ ... key ] */
36297 
36298 		/* [ ... key ] */
36299 
36300 		if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_arr) == 0)) {
36301 			/* Value would normally be omitted, replace with 'null'. */
36302 			DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
36303 		} else {
36304 			;
36305 		}
36306 
36307 		/* [ ... ] */
36308 
36309 		DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
36310 		emitted = 1;
36311 	}
36312 
36313 	if (emitted) {
36314 		DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
36315 		DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
36316 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36317 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
36318 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
36319 		}
36320 	}
36321 	DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
36322 
36323 	duk__enc_objarr_exit(js_ctx, &entry_top);
36324 
36325 	DUK_ASSERT_TOP(thr, entry_top);
36326 }
36327 
36328 /* The Str(key, holder) operation.
36329  *
36330  * Stack policy: [ ... key ] -> [ ... ]
36331  */
36332 DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) {
36333 	duk_hthread *thr = js_ctx->thr;
36334 	duk_tval *tv;
36335 	duk_tval *tv_holder;
36336 	duk_tval *tv_key;
36337 	duk_small_int_t c;
36338 
36339 	DUK_DDD(DUK_DDDPRINT("duk__enc_value: idx_holder=%ld, holder=%!T, key=%!T",
36340 	                     (long) idx_holder, (duk_tval *) duk_get_tval(thr, idx_holder),
36341 	                     (duk_tval *) duk_get_tval(thr, -1)));
36342 
36343 	tv_holder = DUK_GET_TVAL_POSIDX(thr, idx_holder);
36344 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_holder));
36345 	tv_key = DUK_GET_TVAL_NEGIDX(thr, -1);
36346 	DUK_ASSERT(DUK_TVAL_IS_STRING(tv_key));
36347 	DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING(tv_key)));  /* Caller responsible. */
36348 	(void) duk_hobject_getprop(thr, tv_holder, tv_key);
36349 
36350 	/* -> [ ... key val ] */
36351 
36352 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
36353 
36354 	/* Standard JSON checks for .toJSON() only for actual objects; for
36355 	 * example, setting Number.prototype.toJSON and then serializing a
36356 	 * number won't invoke the .toJSON() method.  However, lightfuncs and
36357 	 * plain buffers mimic objects so we check for their .toJSON() method.
36358 	 */
36359 	if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
36360 	                                 DUK_TYPE_MASK_LIGHTFUNC |
36361 	                                 DUK_TYPE_MASK_BUFFER)) {
36362 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_JSON);
36363 		if (duk_is_callable(thr, -1)) {  /* toJSON() can also be a lightfunc */
36364 			DUK_DDD(DUK_DDDPRINT("value is object, has callable toJSON() -> call it"));
36365 			/* XXX: duk_dup_unvalidated(thr, -2) etc. */
36366 			duk_dup_m2(thr);          /* -> [ ... key val toJSON val ] */
36367 			duk_dup_m4(thr);          /* -> [ ... key val toJSON val key ] */
36368 			duk_call_method(thr, 1);  /* -> [ ... key val val' ] */
36369 			duk_remove_m2(thr);       /* -> [ ... key val' ] */
36370 		} else {
36371 			duk_pop(thr);             /* -> [ ... key val ] */
36372 		}
36373 	}
36374 
36375 	/* [ ... key val ] */
36376 
36377 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
36378 
36379 	if (js_ctx->h_replacer) {
36380 		/* XXX: Here a "slice copy" would be useful. */
36381 		DUK_DDD(DUK_DDDPRINT("replacer is set, call replacer"));
36382 		duk_push_hobject(thr, js_ctx->h_replacer);  /* -> [ ... key val replacer ] */
36383 		duk_dup(thr, idx_holder);                   /* -> [ ... key val replacer holder ] */
36384 		duk_dup_m4(thr);                            /* -> [ ... key val replacer holder key ] */
36385 		duk_dup_m4(thr);                            /* -> [ ... key val replacer holder key val ] */
36386 		duk_call_method(thr, 2);                    /* -> [ ... key val val' ] */
36387 		duk_remove_m2(thr);                         /* -> [ ... key val' ] */
36388 	}
36389 
36390 	/* [ ... key val ] */
36391 
36392 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
36393 
36394 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
36395 	if (DUK_TVAL_IS_OBJECT(tv)) {
36396 		duk_hobject *h;
36397 
36398 		h = DUK_TVAL_GET_OBJECT(tv);
36399 		DUK_ASSERT(h != NULL);
36400 
36401 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
36402 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36403 		if (DUK_HOBJECT_IS_BUFOBJ(h) &&
36404 		    js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE)) {
36405 			/* With JX/JC a bufferobject gets serialized specially. */
36406 			duk_hbufobj *h_bufobj;
36407 			h_bufobj = (duk_hbufobj *) h;
36408 			DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
36409 			duk__enc_bufobj(js_ctx, h_bufobj);
36410 			goto pop2_emitted;
36411 		}
36412 		/* Otherwise bufferobjects get serialized as normal objects. */
36413 #endif  /* JX || JC */
36414 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
36415 		c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
36416 		switch (c) {
36417 		case DUK_HOBJECT_CLASS_NUMBER: {
36418 			DUK_DDD(DUK_DDDPRINT("value is a Number object -> coerce with ToNumber()"));
36419 			duk_to_number_m1(thr);
36420 			/* The coercion potentially invokes user .valueOf() and .toString()
36421 			 * but can't result in a function value because ToPrimitive() would
36422 			 * reject such a result: test-dev-json-stringify-coercion-1.js.
36423 			 */
36424 			DUK_ASSERT(!duk_is_callable(thr, -1));
36425 			break;
36426 		}
36427 		case DUK_HOBJECT_CLASS_STRING: {
36428 			DUK_DDD(DUK_DDDPRINT("value is a String object -> coerce with ToString()"));
36429 			duk_to_string(thr, -1);
36430 			/* Same coercion behavior as for Number. */
36431 			DUK_ASSERT(!duk_is_callable(thr, -1));
36432 			break;
36433 		}
36434 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36435 		case DUK_HOBJECT_CLASS_POINTER:
36436 #endif
36437 		case DUK_HOBJECT_CLASS_BOOLEAN: {
36438 			DUK_DDD(DUK_DDDPRINT("value is a Boolean/Buffer/Pointer object -> get internal value"));
36439 			duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
36440 			duk_remove_m2(thr);
36441 			break;
36442 		}
36443 		default: {
36444 			/* Normal object which doesn't get automatically coerced to a
36445 			 * primitive value.  Functions are checked for specially.  The
36446 			 * primitive value coercions for Number, String, Pointer, and
36447 			 * Boolean can't result in functions so suffices to check here.
36448 			 * Symbol objects are handled like plain objects (their primitive
36449 			 * value is NOT looked up like for e.g. String objects).
36450 			 */
36451 			DUK_ASSERT(h != NULL);
36452 			if (DUK_HOBJECT_IS_CALLABLE(h)) {
36453 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36454 				if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
36455 				                     DUK_JSON_FLAG_EXT_COMPATIBLE)) {
36456 					/* We only get here when doing non-standard JSON encoding */
36457 					DUK_DDD(DUK_DDDPRINT("-> function allowed, serialize to custom format"));
36458 					DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);
36459 					DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
36460 					goto pop2_emitted;
36461 				} else {
36462 					DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
36463 					goto pop2_undef;
36464 				}
36465 #else  /* DUK_USE_JX || DUK_USE_JC */
36466 				DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
36467 				goto pop2_undef;
36468 #endif  /* DUK_USE_JX || DUK_USE_JC */
36469 			}
36470 		}
36471 		}  /* end switch */
36472 	}
36473 
36474 	/* [ ... key val ] */
36475 
36476 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
36477 
36478 	if (duk_check_type_mask(thr, -1, js_ctx->mask_for_undefined)) {
36479 		/* will result in undefined */
36480 		DUK_DDD(DUK_DDDPRINT("-> will result in undefined (type mask check)"));
36481 		goto pop2_undef;
36482 	}
36483 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
36484 
36485 	switch (DUK_TVAL_GET_TAG(tv)) {
36486 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36487 	/* When JX/JC not in use, the type mask above will avoid this case if needed. */
36488 	case DUK_TAG_UNDEFINED: {
36489 		DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
36490 		break;
36491 	}
36492 #endif
36493 	case DUK_TAG_NULL: {
36494 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
36495 		break;
36496 	}
36497 	case DUK_TAG_BOOLEAN: {
36498 		DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
36499 		                 DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
36500 		break;
36501 	}
36502 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36503 	/* When JX/JC not in use, the type mask above will avoid this case if needed. */
36504 	case DUK_TAG_POINTER: {
36505 		duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
36506 		break;
36507 	}
36508 #endif  /* DUK_USE_JX || DUK_USE_JC */
36509 	case DUK_TAG_STRING: {
36510 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
36511 		DUK_ASSERT(h != NULL);
36512 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
36513 			goto pop2_undef;
36514 		}
36515 		duk__enc_quote_string(js_ctx, h);
36516 		break;
36517 	}
36518 	case DUK_TAG_OBJECT: {
36519 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
36520 		DUK_ASSERT(h != NULL);
36521 
36522 		/* Function values are handled completely above (including
36523 		 * coercion results):
36524 		 */
36525 		DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE(h));
36526 
36527 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
36528 			duk__enc_array(js_ctx);
36529 		} else {
36530 			duk__enc_object(js_ctx);
36531 		}
36532 		break;
36533 	}
36534 	/* Because plain buffers mimics Uint8Array, they have enumerable
36535 	 * index properties [0,byteLength[.  Because JSON only serializes
36536 	 * enumerable own properties, no properties can be serialized for
36537 	 * plain buffers (all virtual properties are non-enumerable).  However,
36538 	 * there may be a .toJSON() method which was already handled above.
36539 	 */
36540 	case DUK_TAG_BUFFER: {
36541 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36542 		if (js_ctx->flag_ext_custom_or_compatible) {
36543 			duk__enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
36544 			break;
36545 		}
36546 #endif
36547 
36548 		/* Could implement a fastpath, but the fast path would need
36549 		 * to handle realloc side effects correctly.
36550 		 */
36551 		duk_to_object(thr, -1);
36552 		duk__enc_object(js_ctx);
36553 		break;
36554 	}
36555 	case DUK_TAG_LIGHTFUNC: {
36556 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36557 		/* We only get here when doing non-standard JSON encoding */
36558 		DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);
36559 		DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
36560 #else
36561 		/* Standard JSON omits functions */
36562 		DUK_UNREACHABLE();
36563 #endif
36564 		break;
36565 	}
36566 #if defined(DUK_USE_FASTINT)
36567 	case DUK_TAG_FASTINT:
36568 		/* Number serialization has a significant impact relative to
36569 		 * other fast path code, so careful fast path for fastints.
36570 		 */
36571 		duk__enc_fastint_tval(js_ctx, tv);
36572 		break;
36573 #endif
36574 	default: {
36575 		/* number */
36576 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
36577 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
36578 		/* XXX: A fast path for usual integers would be useful when
36579 		 * fastint support is not enabled.
36580 		 */
36581 		duk__enc_double(js_ctx);
36582 		break;
36583 	}
36584 	}
36585 
36586 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36587  pop2_emitted:
36588 #endif
36589 	duk_pop_2(thr); /* [ ... key val ] -> [ ... ] */
36590 	return 1;  /* emitted */
36591 
36592  pop2_undef:
36593 	duk_pop_2(thr);  /* [ ... key val ] -> [ ... ] */
36594 	return 0;  /* not emitted */
36595 }
36596 
36597 /* E5 Section 15.12.3, main algorithm, step 4.b.ii steps 1-4. */
36598 DUK_LOCAL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv) {
36599 	duk_small_int_t c;
36600 
36601 	/* XXX: some kind of external internal type checker?
36602 	 * - type mask; symbol flag; class mask
36603 	 */
36604 	DUK_ASSERT(tv != NULL);
36605 	if (DUK_TVAL_IS_STRING(tv)) {
36606 		duk_hstring *h;
36607 		h = DUK_TVAL_GET_STRING(tv);
36608 		DUK_ASSERT(h != NULL);
36609 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
36610 			return 0;
36611 		}
36612 		return 1;
36613 	} else if (DUK_TVAL_IS_NUMBER(tv)) {
36614 		return 1;
36615 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
36616 		duk_hobject *h;
36617 		h = DUK_TVAL_GET_OBJECT(tv);
36618 		DUK_ASSERT(h != NULL);
36619 		c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
36620 		if (c == DUK_HOBJECT_CLASS_STRING || c == DUK_HOBJECT_CLASS_NUMBER) {
36621 			return 1;
36622 		}
36623 	}
36624 
36625 	return 0;
36626 }
36627 
36628 /*
36629  *  JSON.stringify() fast path
36630  *
36631  *  Otherwise supports full JSON, JX, and JC features, but bails out on any
36632  *  possible side effect which might change the value being serialized.  The
36633  *  fast path can take advantage of the fact that the value being serialized
36634  *  is unchanged so that we can walk directly through property tables etc.
36635  */
36636 
36637 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
36638 DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
36639 	duk_uint_fast32_t i, n;
36640 
36641 	DUK_DDD(DUK_DDDPRINT("stringify fast: %!T", tv));
36642 
36643 	DUK_ASSERT(js_ctx != NULL);
36644 	DUK_ASSERT(js_ctx->thr != NULL);
36645 
36646 #if 0 /* disabled for now */
36647  restart_match:
36648 #endif
36649 
36650 	DUK_ASSERT(tv != NULL);
36651 
36652 	switch (DUK_TVAL_GET_TAG(tv)) {
36653 	case DUK_TAG_UNDEFINED: {
36654 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36655 		if (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible) {
36656 			DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
36657 			break;
36658 		} else {
36659 			goto emit_undefined;
36660 		}
36661 #else
36662 		goto emit_undefined;
36663 #endif
36664 	}
36665 	case DUK_TAG_NULL: {
36666 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
36667 		break;
36668 	}
36669 	case DUK_TAG_BOOLEAN: {
36670 		DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
36671 		                 DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
36672 		break;
36673 	}
36674 	case DUK_TAG_STRING: {
36675 		duk_hstring *h;
36676 		h = DUK_TVAL_GET_STRING(tv);
36677 		DUK_ASSERT(h != NULL);
36678 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
36679 			goto emit_undefined;
36680 		}
36681 		duk__enc_quote_string(js_ctx, h);
36682 		break;
36683 	}
36684 	case DUK_TAG_OBJECT: {
36685 		duk_hobject *obj;
36686 		duk_tval *tv_val;
36687 		duk_bool_t emitted = 0;
36688 		duk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef,
36689 		             c_func, c_bufobj, c_object, c_abort;
36690 
36691 		/* For objects JSON.stringify() only looks for own, enumerable
36692 		 * properties which is nice for the fast path here.
36693 		 *
36694 		 * For arrays JSON.stringify() uses [[Get]] so it will actually
36695 		 * inherit properties during serialization!  This fast path
36696 		 * supports gappy arrays as long as there's no actual inherited
36697 		 * property (which might be a getter etc).
36698 		 *
36699 		 * Since recursion only happens for objects, we can have both
36700 		 * recursion and loop checks here.  We use a simple, depth-limited
36701 		 * loop check in the fast path because the object-based tracking
36702 		 * is very slow (when tested, it accounted for 50% of fast path
36703 		 * execution time for input data with a lot of small objects!).
36704 		 */
36705 
36706 		/* XXX: for real world code, could just ignore array inheritance
36707 		 * and only look at array own properties.
36708 		 */
36709 
36710 		/* We rely on a few object flag / class number relationships here,
36711 		 * assert for them.
36712 		 */
36713 
36714 		obj = DUK_TVAL_GET_OBJECT(tv);
36715 		DUK_ASSERT(obj != NULL);
36716 		DUK_HOBJECT_ASSERT_VALID(obj);
36717 
36718 		/* Once recursion depth is increased, exit path must decrease
36719 		 * it (though it's OK to abort the fast path).
36720 		 */
36721 
36722 		DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
36723 		DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
36724 		if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
36725 			DUK_DD(DUK_DDPRINT("fast path recursion limit"));
36726 			DUK_ERROR_RANGE(js_ctx->thr, DUK_STR_JSONDEC_RECLIMIT);
36727 			DUK_WO_NORETURN(return 0;);
36728 		}
36729 
36730 		for (i = 0, n = (duk_uint_fast32_t) js_ctx->recursion_depth; i < n; i++) {
36731 			if (DUK_UNLIKELY(js_ctx->visiting[i] == obj)) {
36732 				DUK_DD(DUK_DDPRINT("fast path loop detect"));
36733 				DUK_ERROR_TYPE(js_ctx->thr, DUK_STR_CYCLIC_INPUT);
36734 				DUK_WO_NORETURN(return 0;);
36735 			}
36736 		}
36737 
36738 		/* Guaranteed by recursion_limit setup so we don't have to
36739 		 * check twice.
36740 		 */
36741 		DUK_ASSERT(js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY);
36742 		js_ctx->visiting[js_ctx->recursion_depth] = obj;
36743 		js_ctx->recursion_depth++;
36744 
36745 		/* If object has a .toJSON() property, we can't be certain
36746 		 * that it wouldn't mutate any value arbitrarily, so bail
36747 		 * out of the fast path.
36748 		 *
36749 		 * If an object is a Proxy we also can't avoid side effects
36750 		 * so abandon.
36751 		 */
36752 		/* XXX: non-callable .toJSON() doesn't need to cause an abort
36753 		 * but does at the moment, probably not worth fixing.
36754 		 */
36755 		if (duk_hobject_hasprop_raw(js_ctx->thr, obj, DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr)) ||
36756 		    DUK_HOBJECT_IS_PROXY(obj)) {
36757 			DUK_DD(DUK_DDPRINT("object has a .toJSON property or object is a Proxy, abort fast path"));
36758 			goto abort_fastpath;
36759 		}
36760 
36761 		/* We could use a switch-case for the class number but it turns out
36762 		 * a small if-else ladder on class masks is better.  The if-ladder
36763 		 * should be in order of relevancy.
36764 		 */
36765 
36766 		/* XXX: move masks to js_ctx? they don't change during one
36767 		 * fast path invocation.
36768 		 */
36769 		DUK_ASSERT(DUK_HOBJECT_CLASS_MAX <= 31);
36770 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36771 		if (js_ctx->flag_ext_custom_or_compatible) {
36772 			c_all = DUK_HOBJECT_CMASK_ALL;
36773 			c_array = DUK_HOBJECT_CMASK_ARRAY;
36774 			c_unbox = DUK_HOBJECT_CMASK_NUMBER |
36775 			          DUK_HOBJECT_CMASK_STRING |
36776 			          DUK_HOBJECT_CMASK_BOOLEAN |
36777 			          DUK_HOBJECT_CMASK_POINTER;  /* Symbols are not unboxed. */
36778 			c_func = DUK_HOBJECT_CMASK_FUNCTION;
36779 			c_bufobj = DUK_HOBJECT_CMASK_ALL_BUFOBJS;
36780 			c_undef = 0;
36781 			c_abort = 0;
36782 			c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);
36783 		}
36784 		else
36785 #endif
36786 		{
36787 			c_all = DUK_HOBJECT_CMASK_ALL;
36788 			c_array = DUK_HOBJECT_CMASK_ARRAY;
36789 			c_unbox = DUK_HOBJECT_CMASK_NUMBER |
36790 			          DUK_HOBJECT_CMASK_STRING |
36791 			          DUK_HOBJECT_CMASK_BOOLEAN;  /* Symbols are not unboxed. */
36792 			c_func = 0;
36793 			c_bufobj = 0;
36794 			c_undef = DUK_HOBJECT_CMASK_FUNCTION |
36795 			          DUK_HOBJECT_CMASK_POINTER;
36796 			/* As the fast path doesn't currently properly support
36797 			 * duk_hbufobj virtual properties, abort fast path if
36798 			 * we encounter them in plain JSON mode.
36799 			 */
36800 			c_abort = DUK_HOBJECT_CMASK_ALL_BUFOBJS;
36801 			c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);
36802 		}
36803 
36804 		c_bit = (duk_uint32_t) DUK_HOBJECT_GET_CLASS_MASK(obj);
36805 		if (c_bit & c_object) {
36806 			/* All other object types. */
36807 			DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
36808 
36809 			/* A non-Array object should not have an array part in practice.
36810 			 * But since it is supported internally (and perhaps used at some
36811 			 * point), check and abandon if that's the case.
36812 			 */
36813 			if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
36814 				DUK_DD(DUK_DDPRINT("non-Array object has array part, abort fast path"));
36815 				goto abort_fastpath;
36816 			}
36817 
36818 			for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(obj); i++) {
36819 				duk_hstring *k;
36820 				duk_size_t prev_size;
36821 
36822 				k = DUK_HOBJECT_E_GET_KEY(js_ctx->thr->heap, obj, i);
36823 				if (!k) {
36824 					continue;
36825 				}
36826 				if (DUK_HSTRING_HAS_ARRIDX(k)) {
36827 					/* If an object has array index keys we would need
36828 					 * to sort them into the ES2015 enumeration order to
36829 					 * be consistent with the slow path.  Abort the fast
36830 					 * path and handle in the slow path for now.
36831 					 */
36832 					DUK_DD(DUK_DDPRINT("property key is an array index, abort fast path"));
36833 					goto abort_fastpath;
36834 				}
36835 				if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(js_ctx->thr->heap, obj, i)) {
36836 					continue;
36837 				}
36838 				if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(js_ctx->thr->heap, obj, i)) {
36839 					/* Getter might have arbitrary side effects,
36840 					 * so bail out.
36841 					 */
36842 					DUK_DD(DUK_DDPRINT("property is an accessor, abort fast path"));
36843 					goto abort_fastpath;
36844 				}
36845 				if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(k))) {
36846 					continue;
36847 				}
36848 
36849 				tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(js_ctx->thr->heap, obj, i);
36850 
36851 				prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
36852 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36853 					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
36854 					duk__enc_key_autoquote(js_ctx, k);
36855 					DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
36856 				} else {
36857 					duk__enc_key_autoquote(js_ctx, k);
36858 					DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
36859 				}
36860 
36861 				if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) {
36862 					DUK_DD(DUK_DDPRINT("prop value not supported, rewind key and colon"));
36863 					DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
36864 				} else {
36865 					DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
36866 					emitted = 1;
36867 				}
36868 			}
36869 
36870 			/* If any non-Array value had enumerable virtual own
36871 			 * properties, they should be serialized here (actually,
36872 			 * before the explicit properties).  Standard types don't.
36873 			 */
36874 
36875 			if (emitted) {
36876 				DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
36877 				DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
36878 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36879 					DUK_ASSERT(js_ctx->recursion_depth >= 1);
36880 					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
36881 				}
36882 			}
36883 			DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
36884 		} else if (c_bit & c_array) {
36885 			duk_uint_fast32_t arr_len;
36886 			duk_uint_fast32_t asize;
36887 
36888 			DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);
36889 
36890 			/* Assume arrays are dense in the fast path. */
36891 			if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
36892 				DUK_DD(DUK_DDPRINT("Array object is sparse, abort fast path"));
36893 				goto abort_fastpath;
36894 			}
36895 
36896 			arr_len = (duk_uint_fast32_t) ((duk_harray *) obj)->length;
36897 			asize = (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(obj);
36898 			/* Array part may be larger than 'length'; if so, iterate
36899 			 * only up to array 'length'.  Array part may also be smaller
36900 			 * than 'length' in some cases.
36901 			 */
36902 			for (i = 0; i < arr_len; i++) {
36903 				duk_tval *tv_arrval;
36904 				duk_hstring *h_tmp;
36905 				duk_bool_t has_inherited;
36906 
36907 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36908 					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
36909 				}
36910 
36911 				if (DUK_LIKELY(i < asize)) {
36912 					tv_arrval = DUK_HOBJECT_A_GET_VALUE_PTR(js_ctx->thr->heap, obj, i);
36913 					if (DUK_LIKELY(!DUK_TVAL_IS_UNUSED(tv_arrval))) {
36914 						/* Expected case: element is present. */
36915 						if (duk__json_stringify_fast_value(js_ctx, tv_arrval) == 0) {
36916 							DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
36917 						}
36918 						goto elem_done;
36919 					}
36920 				}
36921 
36922 				/* Gap in array; check for inherited property,
36923 				 * bail out if one exists.  This should be enough
36924 				 * to support gappy arrays for all practical code.
36925 				 */
36926 
36927 				h_tmp = duk_push_uint_to_hstring(js_ctx->thr, (duk_uint_t) i);
36928 				has_inherited = duk_hobject_hasprop_raw(js_ctx->thr, obj, h_tmp);
36929 				duk_pop(js_ctx->thr);
36930 				if (has_inherited) {
36931 					DUK_D(DUK_DPRINT("gap in array, conflicting inherited property, abort fast path"));
36932 					goto abort_fastpath;
36933 				}
36934 
36935 				/* Ordinary gap, undefined encodes to 'null' in
36936 				 * standard JSON, but JX/JC use their form for
36937 				 * undefined to better preserve the typing.
36938 				 */
36939 				DUK_D(DUK_DPRINT("gap in array, no conflicting inherited property, remain on fast path"));
36940 #if defined(DUK_USE_JX)
36941 				DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
36942 #else
36943 				DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
36944 #endif
36945 				/* fall through */
36946 
36947 			 elem_done:
36948 				DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
36949 				emitted = 1;
36950 			}
36951 
36952 			if (emitted) {
36953 				DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
36954 				DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
36955 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36956 					DUK_ASSERT(js_ctx->recursion_depth >= 1);
36957 					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
36958 				}
36959 			}
36960 			DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
36961 		} else if (c_bit & c_unbox) {
36962 			/* Certain boxed types are required to go through
36963 			 * automatic unboxing.  Rely on internal value being
36964 			 * sane (to avoid infinite recursion).
36965 			 */
36966 			DUK_ASSERT((c_bit & DUK_HOBJECT_CMASK_SYMBOL) == 0);  /* Symbols are not unboxed. */
36967 
36968 #if 1
36969 			/* The code below is incorrect if .toString() or .valueOf() have
36970 			 * have been overridden.  The correct approach would be to look up
36971 			 * the method(s) and if they resolve to the built-in function we
36972 			 * can safely bypass it and look up the internal value directly.
36973 			 * Unimplemented for now, abort fast path for boxed values.
36974 			 */
36975 			goto abort_fastpath;
36976 #else  /* disabled */
36977 			/* Disabled until fixed, see above. */
36978 			duk_tval *tv_internal;
36979 
36980 			DUK_DD(DUK_DDPRINT("auto unboxing in fast path"));
36981 
36982 			tv_internal = duk_hobject_get_internal_value_tval_ptr(js_ctx->thr->heap, obj);
36983 			DUK_ASSERT(tv_internal != NULL);
36984 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv_internal) ||
36985 			           DUK_TVAL_IS_NUMBER(tv_internal) ||
36986 			           DUK_TVAL_IS_BOOLEAN(tv_internal) ||
36987 			           DUK_TVAL_IS_POINTER(tv_internal));
36988 
36989 			tv = tv_internal;
36990 			DUK_ASSERT(js_ctx->recursion_depth > 0);
36991 			js_ctx->recursion_depth--;  /* required to keep recursion depth correct */
36992 			goto restart_match;
36993 #endif  /* disabled */
36994 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36995 		} else if (c_bit & c_func) {
36996 			DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
36997 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
36998 		} else if (c_bit & c_bufobj) {
36999 			duk__enc_bufobj(js_ctx, (duk_hbufobj *) obj);
37000 #endif
37001 #endif
37002 		} else if (c_bit & c_abort) {
37003 			DUK_DD(DUK_DDPRINT("abort fast path for unsupported type"));
37004 			goto abort_fastpath;
37005 		} else {
37006 			DUK_ASSERT((c_bit & c_undef) != 0);
37007 
37008 			/* Must decrease recursion depth before returning. */
37009 			DUK_ASSERT(js_ctx->recursion_depth > 0);
37010 			DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
37011 			js_ctx->recursion_depth--;
37012 			goto emit_undefined;
37013 		}
37014 
37015 		DUK_ASSERT(js_ctx->recursion_depth > 0);
37016 		DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
37017 		js_ctx->recursion_depth--;
37018 		break;
37019 	}
37020 	case DUK_TAG_BUFFER: {
37021 		/* Plain buffers are treated like Uint8Arrays: they have
37022 		 * enumerable indices.  Other virtual properties are not
37023 		 * enumerable, and inherited properties are not serialized.
37024 		 * However, there can be a replacer (not relevant here) or
37025 		 * a .toJSON() method (which we need to check for explicitly).
37026 		 */
37027 
37028 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
37029 		if (duk_hobject_hasprop_raw(js_ctx->thr,
37030 		                            js_ctx->thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE],
37031 		                            DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr))) {
37032 			DUK_DD(DUK_DDPRINT("value is a plain buffer and there's an inherited .toJSON, abort fast path"));
37033 			goto abort_fastpath;
37034 		}
37035 #endif
37036 
37037 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37038 		if (js_ctx->flag_ext_custom_or_compatible) {
37039 			duk__enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
37040 			break;
37041 		}
37042 #endif
37043 
37044 		/* Plain buffers mimic Uint8Arrays, and have enumerable index
37045 		 * properties.
37046 		 */
37047 		duk__enc_buffer_json_fastpath(js_ctx, DUK_TVAL_GET_BUFFER(tv));
37048 		break;
37049 	}
37050 	case DUK_TAG_POINTER: {
37051 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37052 		if (js_ctx->flag_ext_custom_or_compatible) {
37053 			duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
37054 			break;
37055 		} else {
37056 			goto emit_undefined;
37057 		}
37058 #else
37059 		goto emit_undefined;
37060 #endif
37061 	}
37062 	case DUK_TAG_LIGHTFUNC: {
37063 		/* A lightfunc might also inherit a .toJSON() so just bail out. */
37064 		/* XXX: Could just lookup .toJSON() and continue in fast path,
37065 		 * as it would almost never be defined.
37066 		 */
37067 		DUK_DD(DUK_DDPRINT("value is a lightfunc, abort fast path"));
37068 		goto abort_fastpath;
37069 	}
37070 #if defined(DUK_USE_FASTINT)
37071 	case DUK_TAG_FASTINT: {
37072 		/* Number serialization has a significant impact relative to
37073 		 * other fast path code, so careful fast path for fastints.
37074 		 */
37075 		duk__enc_fastint_tval(js_ctx, tv);
37076 		break;
37077 	}
37078 #endif
37079 	default: {
37080 		/* XXX: A fast path for usual integers would be useful when
37081 		 * fastint support is not enabled.
37082 		 */
37083 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
37084 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
37085 
37086 		/* XXX: Stack discipline is annoying, could be changed in numconv. */
37087 		duk_push_tval(js_ctx->thr, tv);
37088 		duk__enc_double(js_ctx);
37089 		duk_pop(js_ctx->thr);
37090 
37091 #if 0
37092 		/* Could also rely on native sprintf(), but it will handle
37093 		 * values like NaN, Infinity, -0, exponent notation etc in
37094 		 * a JSON-incompatible way.
37095 		 */
37096 		duk_double_t d;
37097 		char buf[64];
37098 
37099 		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
37100 		d = DUK_TVAL_GET_DOUBLE(tv);
37101 		DUK_SPRINTF(buf, "%lg", d);
37102 		DUK__EMIT_CSTR(js_ctx, buf);
37103 #endif
37104 	}
37105 	}
37106 	return 1;  /* not undefined */
37107 
37108  emit_undefined:
37109 	return 0;  /* value was undefined/unsupported */
37110 
37111  abort_fastpath:
37112 	/* Error message doesn't matter: the error is ignored anyway. */
37113 	DUK_DD(DUK_DDPRINT("aborting fast path"));
37114 	DUK_ERROR_INTERNAL(js_ctx->thr);
37115 	DUK_WO_NORETURN(return 0;);
37116 }
37117 
37118 DUK_LOCAL duk_ret_t duk__json_stringify_fast(duk_hthread *thr, void *udata) {
37119 	duk_json_enc_ctx *js_ctx;
37120 	duk_tval *tv;
37121 
37122 	DUK_ASSERT(thr != NULL);
37123 	DUK_ASSERT(udata != NULL);
37124 
37125 	js_ctx = (duk_json_enc_ctx *) udata;
37126 	DUK_ASSERT(js_ctx != NULL);
37127 
37128 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
37129 	if (duk__json_stringify_fast_value(js_ctx, tv) == 0) {
37130 		DUK_DD(DUK_DDPRINT("top level value not supported, fail fast path"));
37131 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);  /* Error message is ignored, so doesn't matter. */
37132 	}
37133 
37134 	return 0;
37135 }
37136 #endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */
37137 
37138 /*
37139  *  Top level wrappers
37140  */
37141 
37142 DUK_INTERNAL
37143 void duk_bi_json_parse_helper(duk_hthread *thr,
37144                               duk_idx_t idx_value,
37145                               duk_idx_t idx_reviver,
37146                               duk_small_uint_t flags) {
37147 	duk_json_dec_ctx js_ctx_alloc;
37148 	duk_json_dec_ctx *js_ctx = &js_ctx_alloc;
37149 	duk_hstring *h_text;
37150 #if defined(DUK_USE_ASSERTIONS)
37151 	duk_idx_t entry_top = duk_get_top(thr);
37152 #endif
37153 
37154 	/* negative top-relative indices not allowed now */
37155 	DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
37156 	DUK_ASSERT(idx_reviver == DUK_INVALID_INDEX || idx_reviver >= 0);
37157 
37158 	DUK_DDD(DUK_DDDPRINT("JSON parse start: text=%!T, reviver=%!T, flags=0x%08lx, stack_top=%ld",
37159 	                     (duk_tval *) duk_get_tval(thr, idx_value),
37160 	                     (duk_tval *) duk_get_tval(thr, idx_reviver),
37161 	                     (unsigned long) flags,
37162 	                     (long) duk_get_top(thr)));
37163 
37164 	duk_memzero(&js_ctx_alloc, sizeof(js_ctx_alloc));
37165 	js_ctx->thr = thr;
37166 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
37167 	/* nothing now */
37168 #endif
37169 	js_ctx->recursion_limit = DUK_USE_JSON_DEC_RECLIMIT;
37170 	DUK_ASSERT(js_ctx->recursion_depth == 0);
37171 
37172 	/* Flag handling currently assumes that flags are consistent.  This is OK
37173 	 * because the call sites are now strictly controlled.
37174 	 */
37175 
37176 	js_ctx->flags = flags;
37177 #if defined(DUK_USE_JX)
37178 	js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
37179 #endif
37180 #if defined(DUK_USE_JC)
37181 	js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
37182 #endif
37183 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37184 	js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
37185 #endif
37186 
37187 	h_text = duk_to_hstring(thr, idx_value);  /* coerce in-place; rejects Symbols */
37188 	DUK_ASSERT(h_text != NULL);
37189 
37190 	/* JSON parsing code is allowed to read [p_start,p_end]: p_end is
37191 	 * valid and points to the string NUL terminator (which is always
37192 	 * guaranteed for duk_hstrings.
37193 	 */
37194 	js_ctx->p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text);
37195 	js_ctx->p = js_ctx->p_start;
37196 	js_ctx->p_end = ((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) +
37197 	                DUK_HSTRING_GET_BYTELEN(h_text);
37198 	DUK_ASSERT(*(js_ctx->p_end) == 0x00);
37199 
37200 	duk__dec_value(js_ctx);  /* -> [ ... value ] */
37201 
37202 	/* Trailing whitespace has been eaten by duk__dec_value(), so if
37203 	 * we're not at end of input here, it's a SyntaxError.
37204 	 */
37205 
37206 	if (js_ctx->p != js_ctx->p_end) {
37207 		duk__dec_syntax_error(js_ctx);
37208 	}
37209 
37210 	if (duk_is_callable(thr, idx_reviver)) {
37211 		DUK_DDD(DUK_DDDPRINT("applying reviver: %!T",
37212 		                     (duk_tval *) duk_get_tval(thr, idx_reviver)));
37213 
37214 		js_ctx->idx_reviver = idx_reviver;
37215 
37216 		duk_push_object(thr);
37217 		duk_dup_m2(thr);  /* -> [ ... val root val ] */
37218 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_EMPTY_STRING);  /* default attrs ok */
37219 		duk_push_hstring_stridx(thr, DUK_STRIDX_EMPTY_STRING);  /* -> [ ... val root "" ] */
37220 
37221 		DUK_DDD(DUK_DDDPRINT("start reviver walk, root=%!T, name=%!T",
37222 		                     (duk_tval *) duk_get_tval(thr, -2),
37223 		                     (duk_tval *) duk_get_tval(thr, -1)));
37224 
37225 		duk__dec_reviver_walk(js_ctx);  /* [ ... val root "" ] -> [ ... val val' ] */
37226 		duk_remove_m2(thr);             /* -> [ ... val' ] */
37227 	} else {
37228 		DUK_DDD(DUK_DDDPRINT("reviver does not exist or is not callable: %!T",
37229 		                     (duk_tval *) duk_get_tval(thr, idx_reviver)));
37230 	}
37231 
37232 	/* Final result is at stack top. */
37233 
37234 	DUK_DDD(DUK_DDDPRINT("JSON parse end: text=%!T, reviver=%!T, flags=0x%08lx, result=%!T, stack_top=%ld",
37235 	                     (duk_tval *) duk_get_tval(thr, idx_value),
37236 	                     (duk_tval *) duk_get_tval(thr, idx_reviver),
37237 	                     (unsigned long) flags,
37238 	                     (duk_tval *) duk_get_tval(thr, -1),
37239 	                     (long) duk_get_top(thr)));
37240 
37241 	DUK_ASSERT(duk_get_top(thr) == entry_top + 1);
37242 }
37243 
37244 DUK_INTERNAL
37245 void duk_bi_json_stringify_helper(duk_hthread *thr,
37246                                   duk_idx_t idx_value,
37247                                   duk_idx_t idx_replacer,
37248                                   duk_idx_t idx_space,
37249                                   duk_small_uint_t flags) {
37250 	duk_json_enc_ctx js_ctx_alloc;
37251 	duk_json_enc_ctx *js_ctx = &js_ctx_alloc;
37252 	duk_hobject *h;
37253 	duk_idx_t idx_holder;
37254 	duk_idx_t entry_top;
37255 
37256 	/* negative top-relative indices not allowed now */
37257 	DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
37258 	DUK_ASSERT(idx_replacer == DUK_INVALID_INDEX || idx_replacer >= 0);
37259 	DUK_ASSERT(idx_space == DUK_INVALID_INDEX || idx_space >= 0);
37260 
37261 	DUK_DDD(DUK_DDDPRINT("JSON stringify start: value=%!T, replacer=%!T, space=%!T, flags=0x%08lx, stack_top=%ld",
37262 	                     (duk_tval *) duk_get_tval(thr, idx_value),
37263 	                     (duk_tval *) duk_get_tval(thr, idx_replacer),
37264 	                     (duk_tval *) duk_get_tval(thr, idx_space),
37265 	                     (unsigned long) flags,
37266 	                     (long) duk_get_top(thr)));
37267 
37268 	entry_top = duk_get_top(thr);
37269 
37270 	/*
37271 	 *  Context init
37272 	 */
37273 
37274 	duk_memzero(&js_ctx_alloc, sizeof(js_ctx_alloc));
37275 	js_ctx->thr = thr;
37276 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
37277 	js_ctx->h_replacer = NULL;
37278 	js_ctx->h_gap = NULL;
37279 #endif
37280 	js_ctx->idx_proplist = -1;
37281 
37282 	/* Flag handling currently assumes that flags are consistent.  This is OK
37283 	 * because the call sites are now strictly controlled.
37284 	 */
37285 
37286 	js_ctx->flags = flags;
37287 	js_ctx->flag_ascii_only = flags & DUK_JSON_FLAG_ASCII_ONLY;
37288 	js_ctx->flag_avoid_key_quotes = flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES;
37289 #if defined(DUK_USE_JX)
37290 	js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
37291 #endif
37292 #if defined(DUK_USE_JC)
37293 	js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
37294 #endif
37295 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37296 	js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
37297 #endif
37298 
37299 	/* The #if defined() clutter here handles the JX/JC enable/disable
37300 	 * combinations properly.
37301 	 */
37302 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37303 	js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_NULL;  /* standard JSON; array gaps */
37304 #if defined(DUK_USE_JX)
37305 	if (flags & DUK_JSON_FLAG_EXT_CUSTOM) {
37306 		js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_UNDEFINED;
37307 		js_ctx->stridx_custom_nan = DUK_STRIDX_NAN;
37308 		js_ctx->stridx_custom_neginf = DUK_STRIDX_MINUS_INFINITY;
37309 		js_ctx->stridx_custom_posinf = DUK_STRIDX_INFINITY;
37310 		js_ctx->stridx_custom_function =
37311 		        (flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES) ?
37312 		                DUK_STRIDX_JSON_EXT_FUNCTION2 :
37313 		                DUK_STRIDX_JSON_EXT_FUNCTION1;
37314 	}
37315 #endif  /* DUK_USE_JX */
37316 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
37317 	else
37318 #endif  /* DUK_USE_JX && DUK_USE_JC */
37319 #if defined(DUK_USE_JC)
37320 	if (js_ctx->flags & DUK_JSON_FLAG_EXT_COMPATIBLE) {
37321 		js_ctx->stridx_custom_undefined = DUK_STRIDX_JSON_EXT_UNDEFINED;
37322 		js_ctx->stridx_custom_nan = DUK_STRIDX_JSON_EXT_NAN;
37323 		js_ctx->stridx_custom_neginf = DUK_STRIDX_JSON_EXT_NEGINF;
37324 		js_ctx->stridx_custom_posinf = DUK_STRIDX_JSON_EXT_POSINF;
37325 		js_ctx->stridx_custom_function = DUK_STRIDX_JSON_EXT_FUNCTION1;
37326 	}
37327 #endif  /* DUK_USE_JC */
37328 #endif  /* DUK_USE_JX || DUK_USE_JC */
37329 
37330 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37331 	if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
37332 	                     DUK_JSON_FLAG_EXT_COMPATIBLE)) {
37333 		DUK_ASSERT(js_ctx->mask_for_undefined == 0);  /* already zero */
37334 	}
37335 	else
37336 #endif  /* DUK_USE_JX || DUK_USE_JC */
37337 	{
37338 		/* Plain buffer is treated like ArrayBuffer and serialized.
37339 		 * Lightfuncs are treated like objects, but JSON explicitly
37340 		 * skips serializing Function objects so we can just reject
37341 		 * lightfuncs here.
37342 		 */
37343 		js_ctx->mask_for_undefined = DUK_TYPE_MASK_UNDEFINED |
37344 		                             DUK_TYPE_MASK_POINTER |
37345 		                             DUK_TYPE_MASK_LIGHTFUNC;
37346 	}
37347 
37348 	DUK_BW_INIT_PUSHBUF(thr, &js_ctx->bw, DUK__JSON_STRINGIFY_BUFSIZE);
37349 
37350 	js_ctx->idx_loop = duk_push_bare_object(thr);
37351 	DUK_ASSERT(js_ctx->idx_loop >= 0);
37352 
37353 	/* [ ... buf loop ] */
37354 
37355 	/*
37356 	 *  Process replacer/proplist (2nd argument to JSON.stringify)
37357 	 */
37358 
37359 	h = duk_get_hobject(thr, idx_replacer);
37360 	if (h != NULL) {
37361 		if (DUK_HOBJECT_IS_CALLABLE(h)) {
37362 			js_ctx->h_replacer = h;
37363 		} else if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
37364 			/* Here the specification requires correct array index enumeration
37365 			 * which is a bit tricky for sparse arrays (it is handled by the
37366 			 * enum setup code).  We now enumerate ancestors too, although the
37367 			 * specification is not very clear on whether that is required.
37368 			 */
37369 
37370 			duk_uarridx_t plist_idx = 0;
37371 			duk_small_uint_t enum_flags;
37372 
37373 			js_ctx->idx_proplist = duk_push_array(thr);  /* XXX: array internal? */
37374 
37375 			enum_flags = DUK_ENUM_ARRAY_INDICES_ONLY |
37376 			             DUK_ENUM_SORT_ARRAY_INDICES;  /* expensive flag */
37377 			duk_enum(thr, idx_replacer, enum_flags);
37378 			while (duk_next(thr, -1 /*enum_index*/, 1 /*get_value*/)) {
37379 				/* [ ... proplist enum_obj key val ] */
37380 				if (duk__enc_allow_into_proplist(duk_get_tval(thr, -1))) {
37381 					/* XXX: duplicates should be eliminated here */
37382 					DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> accept",
37383 					                     (duk_tval *) duk_get_tval(thr, -2),
37384 					                     (duk_tval *) duk_get_tval(thr, -1)));
37385 					duk_to_string(thr, -1);  /* extra coercion of strings is OK */
37386 					duk_put_prop_index(thr, -4, plist_idx);  /* -> [ ... proplist enum_obj key ] */
37387 					plist_idx++;
37388 					duk_pop(thr);
37389 				} else {
37390 					DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> reject",
37391 					                     (duk_tval *) duk_get_tval(thr, -2),
37392 					                     (duk_tval *) duk_get_tval(thr, -1)));
37393 					duk_pop_2(thr);
37394 				}
37395                         }
37396                         duk_pop(thr);  /* pop enum */
37397 
37398 			/* [ ... proplist ] */
37399 		}
37400 	}
37401 
37402 	/* [ ... buf loop (proplist) ] */
37403 
37404 	/*
37405 	 *  Process space (3rd argument to JSON.stringify)
37406 	 */
37407 
37408 	h = duk_get_hobject(thr, idx_space);
37409 	if (h != NULL) {
37410 		duk_small_uint_t c = DUK_HOBJECT_GET_CLASS_NUMBER(h);
37411 		if (c == DUK_HOBJECT_CLASS_NUMBER) {
37412 			duk_to_number(thr, idx_space);
37413 		} else if (c == DUK_HOBJECT_CLASS_STRING) {
37414 			duk_to_string(thr, idx_space);
37415 		}
37416 	}
37417 
37418 	if (duk_is_number(thr, idx_space)) {
37419 		duk_small_int_t nspace;
37420 		/* spaces[] must be static to allow initializer with old compilers like BCC */
37421 		static const char spaces[10] = {
37422 			DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
37423 			DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
37424 			DUK_ASC_SPACE, DUK_ASC_SPACE
37425 		};  /* XXX: helper */
37426 
37427 		/* ToInteger() coercion; NaN -> 0, infinities are clamped to 0 and 10 */
37428 		nspace = (duk_small_int_t) duk_to_int_clamped(thr, idx_space, 0 /*minval*/, 10 /*maxval*/);
37429 		DUK_ASSERT(nspace >= 0 && nspace <= 10);
37430 
37431 		duk_push_lstring(thr, spaces, (duk_size_t) nspace);
37432 		js_ctx->h_gap = duk_known_hstring(thr, -1);
37433 		DUK_ASSERT(js_ctx->h_gap != NULL);
37434 	} else if (duk_is_string_notsymbol(thr, idx_space)) {
37435 		duk_dup(thr, idx_space);
37436 		duk_substring(thr, -1, 0, 10);  /* clamp to 10 chars */
37437 		js_ctx->h_gap = duk_known_hstring(thr, -1);
37438 	} else {
37439 		/* nop */
37440 	}
37441 
37442 	if (js_ctx->h_gap != NULL) {
37443 		/* If gap is empty, behave as if not given at all.  Check
37444 		 * against byte length because character length is more
37445 		 * expensive.
37446 		 */
37447 		if (DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) == 0) {
37448 			js_ctx->h_gap = NULL;
37449 		}
37450 	}
37451 
37452 	/* [ ... buf loop (proplist) (gap) ] */
37453 
37454 	/*
37455 	 *  Fast path: assume no mutation, iterate object property tables
37456 	 *  directly; bail out if that assumption doesn't hold.
37457 	 */
37458 
37459 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
37460 	if (js_ctx->h_replacer == NULL &&  /* replacer is a mutation risk */
37461 	    js_ctx->idx_proplist == -1) {  /* proplist is very rare */
37462 		duk_int_t pcall_rc;
37463 		duk_small_uint_t prev_ms_base_flags;
37464 
37465 		DUK_DD(DUK_DDPRINT("try JSON.stringify() fast path"));
37466 
37467 		/* Use recursion_limit to ensure we don't overwrite js_ctx->visiting[]
37468 		 * array so we don't need two counter checks in the fast path.  The
37469 		 * slow path has a much larger recursion limit which we'll use if
37470 		 * necessary.
37471 		 */
37472 		DUK_ASSERT(DUK_USE_JSON_ENC_RECLIMIT >= DUK_JSON_ENC_LOOPARRAY);
37473 		js_ctx->recursion_limit = DUK_JSON_ENC_LOOPARRAY;
37474 		DUK_ASSERT(js_ctx->recursion_depth == 0);
37475 
37476 		/* Execute the fast path in a protected call.  If any error is thrown,
37477 		 * fall back to the slow path.  This includes e.g. recursion limit
37478 		 * because the fast path has a smaller recursion limit (and simpler,
37479 		 * limited loop detection).
37480 		 */
37481 
37482 		duk_dup(thr, idx_value);
37483 
37484 		/* Must prevent finalizers which may have arbitrary side effects. */
37485 		prev_ms_base_flags = thr->heap->ms_base_flags;
37486 		thr->heap->ms_base_flags |=
37487 		        DUK_MS_FLAG_NO_OBJECT_COMPACTION;      /* Avoid attempt to compact any objects. */
37488 		thr->heap->pf_prevent_count++;                 /* Prevent finalizers. */
37489 		DUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */
37490 
37491 		pcall_rc = duk_safe_call(thr, duk__json_stringify_fast, (void *) js_ctx /*udata*/, 1 /*nargs*/, 0 /*nret*/);
37492 
37493 		DUK_ASSERT(thr->heap->pf_prevent_count > 0);
37494 		thr->heap->pf_prevent_count--;
37495 		thr->heap->ms_base_flags = prev_ms_base_flags;
37496 
37497 		if (pcall_rc == DUK_EXEC_SUCCESS) {
37498 			DUK_DD(DUK_DDPRINT("fast path successful"));
37499 			DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
37500 			goto replace_finished;
37501 		}
37502 
37503 		/* We come here for actual aborts (like encountering .toJSON())
37504 		 * but also for recursion/loop errors.  Bufwriter size can be
37505 		 * kept because we'll probably need at least as much as we've
37506 		 * allocated so far.
37507 		 */
37508 		DUK_D(DUK_DPRINT("fast path failed, serialize using slow path instead"));
37509 		DUK_BW_RESET_SIZE(thr, &js_ctx->bw);
37510 		js_ctx->recursion_depth = 0;
37511 	}
37512 #endif
37513 
37514 	/*
37515 	 *  Create wrapper object and serialize
37516 	 */
37517 
37518 	idx_holder = duk_push_object(thr);
37519 	duk_dup(thr, idx_value);
37520 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_EMPTY_STRING);
37521 
37522 	DUK_DDD(DUK_DDDPRINT("before: flags=0x%08lx, loop=%!T, replacer=%!O, "
37523 	                     "proplist=%!T, gap=%!O, holder=%!T",
37524 	                     (unsigned long) js_ctx->flags,
37525 	                     (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop),
37526 	                     (duk_heaphdr *) js_ctx->h_replacer,
37527 	                     (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(thr, js_ctx->idx_proplist) : NULL),
37528 	                     (duk_heaphdr *) js_ctx->h_gap,
37529 	                     (duk_tval *) duk_get_tval(thr, -1)));
37530 
37531 	/* serialize the wrapper with empty string key */
37532 
37533 	duk_push_hstring_empty(thr);
37534 
37535 	/* [ ... buf loop (proplist) (gap) holder "" ] */
37536 
37537 	js_ctx->recursion_limit = DUK_USE_JSON_ENC_RECLIMIT;
37538 	DUK_ASSERT(js_ctx->recursion_depth == 0);
37539 
37540 	if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_holder) == 0)) {  /* [ ... holder key ] -> [ ... holder ] */
37541 		/* Result is undefined. */
37542 		duk_push_undefined(thr);
37543 	} else {
37544 		/* Convert buffer to result string. */
37545 		DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
37546 	}
37547 
37548 	DUK_DDD(DUK_DDDPRINT("after: flags=0x%08lx, loop=%!T, replacer=%!O, "
37549 	                     "proplist=%!T, gap=%!O, holder=%!T",
37550 	                     (unsigned long) js_ctx->flags,
37551 	                     (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop),
37552 	                     (duk_heaphdr *) js_ctx->h_replacer,
37553 	                     (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(thr, js_ctx->idx_proplist) : NULL),
37554 	                     (duk_heaphdr *) js_ctx->h_gap,
37555 	                     (duk_tval *) duk_get_tval(thr, idx_holder)));
37556 
37557 	/* The stack has a variable shape here, so force it to the
37558 	 * desired one explicitly.
37559 	 */
37560 
37561 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
37562  replace_finished:
37563 #endif
37564 	duk_replace(thr, entry_top);
37565 	duk_set_top(thr, entry_top + 1);
37566 
37567 	DUK_DDD(DUK_DDDPRINT("JSON stringify end: value=%!T, replacer=%!T, space=%!T, "
37568 	                     "flags=0x%08lx, result=%!T, stack_top=%ld",
37569 	                     (duk_tval *) duk_get_tval(thr, idx_value),
37570 	                     (duk_tval *) duk_get_tval(thr, idx_replacer),
37571 	                     (duk_tval *) duk_get_tval(thr, idx_space),
37572 	                     (unsigned long) flags,
37573 	                     (duk_tval *) duk_get_tval(thr, -1),
37574 	                     (long) duk_get_top(thr)));
37575 
37576 	DUK_ASSERT(duk_get_top(thr) == entry_top + 1);
37577 }
37578 
37579 #if defined(DUK_USE_JSON_BUILTIN)
37580 
37581 /*
37582  *  Entry points
37583  */
37584 
37585 DUK_INTERNAL duk_ret_t duk_bi_json_object_parse(duk_hthread *thr) {
37586 	duk_bi_json_parse_helper(thr,
37587 	                         0 /*idx_value*/,
37588 	                         1 /*idx_replacer*/,
37589 	                         0 /*flags*/);
37590 	return 1;
37591 }
37592 
37593 DUK_INTERNAL duk_ret_t duk_bi_json_object_stringify(duk_hthread *thr) {
37594 	duk_bi_json_stringify_helper(thr,
37595 	                             0 /*idx_value*/,
37596 	                             1 /*idx_replacer*/,
37597 	                             2 /*idx_space*/,
37598 	                             0 /*flags*/);
37599 	return 1;
37600 }
37601 
37602 #endif  /* DUK_USE_JSON_BUILTIN */
37603 
37604 #endif  /* DUK_USE_JSON_SUPPORT */
37605 
37606 /* automatic undefs */
37607 #undef DUK__EMIT_1
37608 #undef DUK__EMIT_2
37609 #undef DUK__EMIT_CSTR
37610 #undef DUK__EMIT_HSTR
37611 #undef DUK__EMIT_STRIDX
37612 #undef DUK__JSON_DECSTR_BUFSIZE
37613 #undef DUK__JSON_DECSTR_CHUNKSIZE
37614 #undef DUK__JSON_ENCSTR_CHUNKSIZE
37615 #undef DUK__JSON_MAX_ESC_LEN
37616 #undef DUK__JSON_STRINGIFY_BUFSIZE
37617 #undef DUK__MKESC
37618 #undef DUK__UNEMIT_1
37619 /*
37620  *  Math built-ins
37621  */
37622 
37623 /* #include duk_internal.h -> already included */
37624 
37625 #if defined(DUK_USE_MATH_BUILTIN)
37626 
37627 /*
37628  *  Use static helpers which can work with math.h functions matching
37629  *  the following signatures. This is not portable if any of these math
37630  *  functions is actually a macro.
37631  *
37632  *  Typing here is intentionally 'double' wherever values interact with
37633  *  the standard library APIs.
37634  */
37635 
37636 typedef double (*duk__one_arg_func)(double);
37637 typedef double (*duk__two_arg_func)(double, double);
37638 
37639 DUK_LOCAL duk_ret_t duk__math_minmax(duk_hthread *thr, duk_double_t initial, duk__two_arg_func min_max) {
37640 	duk_idx_t n = duk_get_top(thr);
37641 	duk_idx_t i;
37642 	duk_double_t res = initial;
37643 	duk_double_t t;
37644 
37645 	/*
37646 	 *  Note: fmax() does not match the E5 semantics.  E5 requires
37647 	 *  that if -any- input to Math.max() is a NaN, the result is a
37648 	 *  NaN.  fmax() will return a NaN only if -both- inputs are NaN.
37649 	 *  Same applies to fmin().
37650 	 *
37651 	 *  Note: every input value must be coerced with ToNumber(), even
37652 	 *  if we know the result will be a NaN anyway: ToNumber() may have
37653 	 *  side effects for which even order of evaluation matters.
37654 	 */
37655 
37656 	for (i = 0; i < n; i++) {
37657 		t = duk_to_number(thr, i);
37658 		if (DUK_FPCLASSIFY(t) == DUK_FP_NAN || DUK_FPCLASSIFY(res) == DUK_FP_NAN) {
37659 			/* Note: not normalized, but duk_push_number() will normalize */
37660 			res = (duk_double_t) DUK_DOUBLE_NAN;
37661 		} else {
37662 			res = (duk_double_t) min_max(res, (double) t);
37663 		}
37664 	}
37665 
37666 	duk_push_number(thr, res);
37667 	return 1;
37668 }
37669 
37670 DUK_LOCAL double duk__fmin_fixed(double x, double y) {
37671 	/* fmin() with args -0 and +0 is not guaranteed to return
37672 	 * -0 as ECMAScript requires.
37673 	 */
37674 	if (x == 0 && y == 0) {
37675 		duk_double_union du1, du2;
37676 		du1.d = x;
37677 		du2.d = y;
37678 
37679 		/* Already checked to be zero so these must hold, and allow us
37680 		 * to check for "x is -0 or y is -0" by ORing the high parts
37681 		 * for comparison.
37682 		 */
37683 		DUK_ASSERT(du1.ui[DUK_DBL_IDX_UI0] == 0 || du1.ui[DUK_DBL_IDX_UI0] == 0x80000000UL);
37684 		DUK_ASSERT(du2.ui[DUK_DBL_IDX_UI0] == 0 || du2.ui[DUK_DBL_IDX_UI0] == 0x80000000UL);
37685 
37686 		/* XXX: what's the safest way of creating a negative zero? */
37687 		if ((du1.ui[DUK_DBL_IDX_UI0] | du2.ui[DUK_DBL_IDX_UI0]) != 0) {
37688 			/* Enter here if either x or y (or both) is -0. */
37689 			return -0.0;
37690 		} else {
37691 			return +0.0;
37692 		}
37693 	}
37694 	return duk_double_fmin(x, y);
37695 }
37696 
37697 DUK_LOCAL double duk__fmax_fixed(double x, double y) {
37698 	/* fmax() with args -0 and +0 is not guaranteed to return
37699 	 * +0 as ECMAScript requires.
37700 	 */
37701 	if (x == 0 && y == 0) {
37702 		if (DUK_SIGNBIT(x) == 0 || DUK_SIGNBIT(y) == 0) {
37703 			return +0.0;
37704 		} else {
37705 			return -0.0;
37706 		}
37707 	}
37708 	return duk_double_fmax(x, y);
37709 }
37710 
37711 #if defined(DUK_USE_ES6)
37712 DUK_LOCAL double duk__cbrt(double x) {
37713 	/* cbrt() is C99.  To avoid hassling embedders with the need to provide a
37714 	 * cube root function, we can get by with pow().  The result is not
37715 	 * identical, but that's OK: ES2015 says it's implementation-dependent.
37716 	 */
37717 
37718 #if defined(DUK_CBRT)
37719 	/* cbrt() matches ES2015 requirements. */
37720 	return DUK_CBRT(x);
37721 #else
37722 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
37723 
37724 	/* pow() does not, however. */
37725 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
37726 		return x;
37727 	}
37728 	if (DUK_SIGNBIT(x)) {
37729 		return -DUK_POW(-x, 1.0 / 3.0);
37730 	} else {
37731 		return DUK_POW(x, 1.0 / 3.0);
37732 	}
37733 #endif
37734 }
37735 
37736 DUK_LOCAL double duk__log2(double x) {
37737 #if defined(DUK_LOG2)
37738 	return DUK_LOG2(x);
37739 #else
37740 	return DUK_LOG(x) * DUK_DOUBLE_LOG2E;
37741 #endif
37742 }
37743 
37744 DUK_LOCAL double duk__log10(double x) {
37745 #if defined(DUK_LOG10)
37746 	return DUK_LOG10(x);
37747 #else
37748 	return DUK_LOG(x) * DUK_DOUBLE_LOG10E;
37749 #endif
37750 }
37751 
37752 DUK_LOCAL double duk__trunc(double x) {
37753 #if defined(DUK_TRUNC)
37754 	return DUK_TRUNC(x);
37755 #else
37756 	/* Handles -0 correctly: -0.0 matches 'x >= 0.0' but floor()
37757 	 * is required to return -0 when the argument is -0.
37758 	 */
37759 	return x >= 0.0 ? DUK_FLOOR(x) : DUK_CEIL(x);
37760 #endif
37761 }
37762 #endif  /* DUK_USE_ES6 */
37763 
37764 DUK_LOCAL double duk__round_fixed(double x) {
37765 	/* Numbers half-way between integers must be rounded towards +Infinity,
37766 	 * e.g. -3.5 must be rounded to -3 (not -4).  When rounded to zero, zero
37767 	 * sign must be set appropriately.  E5.1 Section 15.8.2.15.
37768 	 *
37769 	 * Note that ANSI C round() is "round to nearest integer, away from zero",
37770 	 * which is incorrect for negative values.  Here we make do with floor().
37771 	 */
37772 
37773 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
37774 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
37775 		return x;
37776 	}
37777 
37778 	/*
37779 	 *  x is finite and non-zero
37780 	 *
37781 	 *  -1.6 -> floor(-1.1) -> -2
37782 	 *  -1.5 -> floor(-1.0) -> -1  (towards +Inf)
37783 	 *  -1.4 -> floor(-0.9) -> -1
37784 	 *  -0.5 -> -0.0               (special case)
37785 	 *  -0.1 -> -0.0               (special case)
37786 	 *  +0.1 -> +0.0               (special case)
37787 	 *  +0.5 -> floor(+1.0) -> 1   (towards +Inf)
37788 	 *  +1.4 -> floor(+1.9) -> 1
37789 	 *  +1.5 -> floor(+2.0) -> 2   (towards +Inf)
37790 	 *  +1.6 -> floor(+2.1) -> 2
37791 	 */
37792 
37793 	if (x >= -0.5 && x < 0.5) {
37794 		/* +0.5 is handled by floor, this is on purpose */
37795 		if (x < 0.0) {
37796 			return -0.0;
37797 		} else {
37798 			return +0.0;
37799 		}
37800 	}
37801 
37802 	return DUK_FLOOR(x + 0.5);
37803 }
37804 
37805 /* Wrappers for calling standard math library methods.  These may be required
37806  * on platforms where one or more of the math built-ins are defined as macros
37807  * or inline functions and are thus not suitable to be used as function pointers.
37808  */
37809 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
37810 DUK_LOCAL double duk__fabs(double x) {
37811 	return DUK_FABS(x);
37812 }
37813 DUK_LOCAL double duk__acos(double x) {
37814 	return DUK_ACOS(x);
37815 }
37816 DUK_LOCAL double duk__asin(double x) {
37817 	return DUK_ASIN(x);
37818 }
37819 DUK_LOCAL double duk__atan(double x) {
37820 	return DUK_ATAN(x);
37821 }
37822 DUK_LOCAL double duk__ceil(double x) {
37823 	return DUK_CEIL(x);
37824 }
37825 DUK_LOCAL double duk__cos(double x) {
37826 	return DUK_COS(x);
37827 }
37828 DUK_LOCAL double duk__exp(double x) {
37829 	return DUK_EXP(x);
37830 }
37831 DUK_LOCAL double duk__floor(double x) {
37832 	return DUK_FLOOR(x);
37833 }
37834 DUK_LOCAL double duk__log(double x) {
37835 	return DUK_LOG(x);
37836 }
37837 DUK_LOCAL double duk__sin(double x) {
37838 	return DUK_SIN(x);
37839 }
37840 DUK_LOCAL double duk__sqrt(double x) {
37841 	return DUK_SQRT(x);
37842 }
37843 DUK_LOCAL double duk__tan(double x) {
37844 	return DUK_TAN(x);
37845 }
37846 DUK_LOCAL double duk__atan2_fixed(double x, double y) {
37847 #if defined(DUK_USE_ATAN2_WORKAROUNDS)
37848 	/* Specific fixes to common atan2() implementation issues:
37849 	 * - test-bug-mingw-math-issues.js
37850 	 */
37851 	if (DUK_ISINF(x) && DUK_ISINF(y)) {
37852 		if (DUK_SIGNBIT(x)) {
37853 			if (DUK_SIGNBIT(y)) {
37854 				return -2.356194490192345;
37855 			} else {
37856 				return -0.7853981633974483;
37857 			}
37858 		} else {
37859 			if (DUK_SIGNBIT(y)) {
37860 				return 2.356194490192345;
37861 			} else {
37862 				return 0.7853981633974483;
37863 			}
37864 		}
37865 	}
37866 #else
37867 	/* Some ISO C assumptions. */
37868 	DUK_ASSERT(DUK_ATAN2(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY) == 0.7853981633974483);
37869 	DUK_ASSERT(DUK_ATAN2(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY) == -0.7853981633974483);
37870 	DUK_ASSERT(DUK_ATAN2(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY) == 2.356194490192345);
37871 	DUK_ASSERT(DUK_ATAN2(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY) == -2.356194490192345);
37872 #endif
37873 
37874 	return DUK_ATAN2(x, y);
37875 }
37876 #endif  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
37877 
37878 /* order must match constants in genbuiltins.py */
37879 DUK_LOCAL const duk__one_arg_func duk__one_arg_funcs[] = {
37880 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
37881 	duk__fabs,
37882 	duk__acos,
37883 	duk__asin,
37884 	duk__atan,
37885 	duk__ceil,
37886 	duk__cos,
37887 	duk__exp,
37888 	duk__floor,
37889 	duk__log,
37890 	duk__round_fixed,
37891 	duk__sin,
37892 	duk__sqrt,
37893 	duk__tan,
37894 #if defined(DUK_USE_ES6)
37895 	duk__cbrt,
37896 	duk__log2,
37897 	duk__log10,
37898 	duk__trunc
37899 #endif
37900 #else  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
37901 	DUK_FABS,
37902 	DUK_ACOS,
37903 	DUK_ASIN,
37904 	DUK_ATAN,
37905 	DUK_CEIL,
37906 	DUK_COS,
37907 	DUK_EXP,
37908 	DUK_FLOOR,
37909 	DUK_LOG,
37910 	duk__round_fixed,
37911 	DUK_SIN,
37912 	DUK_SQRT,
37913 	DUK_TAN,
37914 #if defined(DUK_USE_ES6)
37915 	duk__cbrt,
37916 	duk__log2,
37917 	duk__log10,
37918 	duk__trunc
37919 #endif
37920 #endif  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
37921 };
37922 
37923 /* order must match constants in genbuiltins.py */
37924 DUK_LOCAL const duk__two_arg_func duk__two_arg_funcs[] = {
37925 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
37926 	duk__atan2_fixed,
37927 	duk_js_arith_pow
37928 #else
37929 	duk__atan2_fixed,
37930 	duk_js_arith_pow
37931 #endif
37932 };
37933 
37934 DUK_INTERNAL duk_ret_t duk_bi_math_object_onearg_shared(duk_hthread *thr) {
37935 	duk_small_int_t fun_idx = duk_get_current_magic(thr);
37936 	duk__one_arg_func fun;
37937 	duk_double_t arg1;
37938 
37939 	DUK_ASSERT(fun_idx >= 0);
37940 	DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__one_arg_funcs) / sizeof(duk__one_arg_func)));
37941 	arg1 = duk_to_number(thr, 0);
37942 	fun = duk__one_arg_funcs[fun_idx];
37943 	duk_push_number(thr, (duk_double_t) fun((double) arg1));
37944 	return 1;
37945 }
37946 
37947 DUK_INTERNAL duk_ret_t duk_bi_math_object_twoarg_shared(duk_hthread *thr) {
37948 	duk_small_int_t fun_idx = duk_get_current_magic(thr);
37949 	duk__two_arg_func fun;
37950 	duk_double_t arg1;
37951 	duk_double_t arg2;
37952 
37953 	DUK_ASSERT(fun_idx >= 0);
37954 	DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__two_arg_funcs) / sizeof(duk__two_arg_func)));
37955 	arg1 = duk_to_number(thr, 0);  /* explicit ordered evaluation to match coercion semantics */
37956 	arg2 = duk_to_number(thr, 1);
37957 	fun = duk__two_arg_funcs[fun_idx];
37958 	duk_push_number(thr, (duk_double_t) fun((double) arg1, (double) arg2));
37959 	return 1;
37960 }
37961 
37962 DUK_INTERNAL duk_ret_t duk_bi_math_object_max(duk_hthread *thr) {
37963 	return duk__math_minmax(thr, -DUK_DOUBLE_INFINITY, duk__fmax_fixed);
37964 }
37965 
37966 DUK_INTERNAL duk_ret_t duk_bi_math_object_min(duk_hthread *thr) {
37967 	return duk__math_minmax(thr, DUK_DOUBLE_INFINITY, duk__fmin_fixed);
37968 }
37969 
37970 DUK_INTERNAL duk_ret_t duk_bi_math_object_random(duk_hthread *thr) {
37971 	duk_push_number(thr, (duk_double_t) DUK_UTIL_GET_RANDOM_DOUBLE(thr));
37972 	return 1;
37973 }
37974 
37975 #if defined(DUK_USE_ES6)
37976 DUK_INTERNAL duk_ret_t duk_bi_math_object_hypot(duk_hthread *thr) {
37977 	/*
37978 	 *  E6 Section 20.2.2.18: Math.hypot
37979 	 *
37980 	 *  - If no arguments are passed, the result is +0.
37981 	 *  - If any argument is +inf, the result is +inf.
37982 	 *  - If any argument is -inf, the result is +inf.
37983 	 *  - If no argument is +inf or -inf, and any argument is NaN, the result is
37984 	 *    NaN.
37985 	 *  - If all arguments are either +0 or -0, the result is +0.
37986 	 */
37987 
37988 	duk_idx_t nargs;
37989 	duk_idx_t i;
37990 	duk_bool_t found_nan;
37991 	duk_double_t max;
37992 	duk_double_t sum, summand;
37993 	duk_double_t comp, prelim;
37994 	duk_double_t t;
37995 
37996 	nargs = duk_get_top(thr);
37997 
37998 	/* Find the highest value.  Also ToNumber() coerces. */
37999 	max = 0.0;
38000 	found_nan = 0;
38001 	for (i = 0; i < nargs; i++) {
38002 		t = DUK_FABS(duk_to_number(thr, i));
38003 		if (DUK_FPCLASSIFY(t) == DUK_FP_NAN) {
38004 			found_nan = 1;
38005 		} else {
38006 			max = duk_double_fmax(max, t);
38007 		}
38008 	}
38009 
38010 	/* Early return cases. */
38011 	if (max == DUK_DOUBLE_INFINITY) {
38012 		duk_push_number(thr, DUK_DOUBLE_INFINITY);
38013 		return 1;
38014 	} else if (found_nan) {
38015 		duk_push_number(thr, DUK_DOUBLE_NAN);
38016 		return 1;
38017 	} else if (max == 0.0) {
38018 		duk_push_number(thr, 0.0);
38019 		/* Otherwise we'd divide by zero. */
38020 		return 1;
38021 	}
38022 
38023 	/* Use Kahan summation and normalize to the highest value to minimize
38024 	 * floating point rounding error and avoid overflow.
38025 	 *
38026 	 * https://en.wikipedia.org/wiki/Kahan_summation_algorithm
38027 	 */
38028 	sum = 0.0;
38029 	comp = 0.0;
38030 	for (i = 0; i < nargs; i++) {
38031 		t = DUK_FABS(duk_get_number(thr, i)) / max;
38032 		summand = (t * t) - comp;
38033 		prelim = sum + summand;
38034 		comp = (prelim - sum) - summand;
38035 		sum = prelim;
38036 	}
38037 
38038 	duk_push_number(thr, (duk_double_t) DUK_SQRT(sum) * max);
38039 	return 1;
38040 }
38041 #endif  /* DUK_USE_ES6 */
38042 
38043 #if defined(DUK_USE_ES6)
38044 DUK_INTERNAL duk_ret_t duk_bi_math_object_sign(duk_hthread *thr) {
38045 	duk_double_t d;
38046 
38047 	d = duk_to_number(thr, 0);
38048 	if (duk_double_is_nan(d)) {
38049 		DUK_ASSERT(duk_is_nan(thr, -1));
38050 		return 1;  /* NaN input -> return NaN */
38051 	}
38052 	if (d == 0.0) {
38053 		/* Zero sign kept, i.e. -0 -> -0, +0 -> +0. */
38054 		return 1;
38055 	}
38056 	duk_push_int(thr, (d > 0.0 ? 1 : -1));
38057 	return 1;
38058 }
38059 #endif  /* DUK_USE_ES6 */
38060 
38061 #if defined(DUK_USE_ES6)
38062 DUK_INTERNAL duk_ret_t duk_bi_math_object_clz32(duk_hthread *thr) {
38063 	duk_uint32_t x;
38064 	duk_small_uint_t i;
38065 
38066 #if defined(DUK_USE_PREFER_SIZE)
38067 	duk_uint32_t mask;
38068 
38069 	x = duk_to_uint32(thr, 0);
38070 	for (i = 0, mask = 0x80000000UL; mask != 0; mask >>= 1) {
38071 		if (x & mask) {
38072 			break;
38073 		}
38074 		i++;
38075 	}
38076 	DUK_ASSERT(i <= 32);
38077 	duk_push_uint(thr, i);
38078 	return 1;
38079 #else  /* DUK_USE_PREFER_SIZE */
38080 	i = 0;
38081 	x = duk_to_uint32(thr, 0);
38082 	if (x & 0xffff0000UL) {
38083 		x >>= 16;
38084 	} else {
38085 		i += 16;
38086 	}
38087 	if (x & 0x0000ff00UL) {
38088 		x >>= 8;
38089 	} else {
38090 		i += 8;
38091 	}
38092 	if (x & 0x000000f0UL) {
38093 		x >>= 4;
38094 	} else {
38095 		i += 4;
38096 	}
38097 	if (x & 0x0000000cUL) {
38098 		x >>= 2;
38099 	} else {
38100 		i += 2;
38101 	}
38102 	if (x & 0x00000002UL) {
38103 		x >>= 1;
38104 	} else {
38105 		i += 1;
38106 	}
38107 	if (x & 0x00000001UL) {
38108 		;
38109 	} else {
38110 		i += 1;
38111 	}
38112 	DUK_ASSERT(i <= 32);
38113 	duk_push_uint(thr, i);
38114 	return 1;
38115 #endif  /* DUK_USE_PREFER_SIZE */
38116 }
38117 #endif  /* DUK_USE_ES6 */
38118 
38119 #if defined(DUK_USE_ES6)
38120 DUK_INTERNAL duk_ret_t duk_bi_math_object_imul(duk_hthread *thr) {
38121 	duk_uint32_t x, y, z;
38122 
38123 	x = duk_to_uint32(thr, 0);
38124 	y = duk_to_uint32(thr, 1);
38125 	z = x * y;
38126 
38127 	/* While arguments are ToUint32() coerced and the multiplication
38128 	 * is unsigned as such, the final result is curiously interpreted
38129 	 * as a signed 32-bit value.
38130 	 */
38131 	duk_push_i32(thr, (duk_int32_t) z);
38132 	return 1;
38133 }
38134 #endif  /* DUK_USE_ES6 */
38135 
38136 #endif  /* DUK_USE_MATH_BUILTIN */
38137 /*
38138  *  Number built-ins
38139  */
38140 
38141 /* #include duk_internal.h -> already included */
38142 
38143 #if defined(DUK_USE_NUMBER_BUILTIN)
38144 
38145 DUK_LOCAL duk_double_t duk__push_this_number_plain(duk_hthread *thr) {
38146 	duk_hobject *h;
38147 
38148 	/* Number built-in accepts a plain number or a Number object (whose
38149 	 * internal value is operated on).  Other types cause TypeError.
38150 	 */
38151 
38152 	duk_push_this(thr);
38153 	if (duk_is_number(thr, -1)) {
38154 		DUK_DDD(DUK_DDDPRINT("plain number value: %!T", (duk_tval *) duk_get_tval(thr, -1)));
38155 		goto done;
38156 	}
38157 	h = duk_get_hobject(thr, -1);
38158 	if (!h ||
38159 	    (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_NUMBER)) {
38160 		DUK_DDD(DUK_DDDPRINT("unacceptable this value: %!T", (duk_tval *) duk_get_tval(thr, -1)));
38161 		DUK_ERROR_TYPE(thr, "number expected");
38162 		DUK_WO_NORETURN(return 0.0;);
38163 	}
38164 	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
38165 	DUK_ASSERT(duk_is_number(thr, -1));
38166 	DUK_DDD(DUK_DDDPRINT("number object: %!T, internal value: %!T",
38167 	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
38168 	duk_remove_m2(thr);
38169 
38170  done:
38171 	return duk_get_number(thr, -1);
38172 }
38173 
38174 DUK_INTERNAL duk_ret_t duk_bi_number_constructor(duk_hthread *thr) {
38175 	duk_idx_t nargs;
38176 	duk_hobject *h_this;
38177 
38178 	/*
38179 	 *  The Number constructor uses ToNumber(arg) for number coercion
38180 	 *  (coercing an undefined argument to NaN).  However, if the
38181 	 *  argument is not given at all, +0 must be used instead.  To do
38182 	 *  this, a vararg function is used.
38183 	 */
38184 
38185 	nargs = duk_get_top(thr);
38186 	if (nargs == 0) {
38187 		duk_push_int(thr, 0);
38188 	}
38189 	duk_to_number(thr, 0);
38190 	duk_set_top(thr, 1);
38191 	DUK_ASSERT_TOP(thr, 1);
38192 
38193 	if (!duk_is_constructor_call(thr)) {
38194 		return 1;
38195 	}
38196 
38197 	/*
38198 	 *  E5 Section 15.7.2.1 requires that the constructed object
38199 	 *  must have the original Number.prototype as its internal
38200 	 *  prototype.  However, since Number.prototype is non-writable
38201 	 *  and non-configurable, this doesn't have to be enforced here:
38202 	 *  The default object (bound to 'this') is OK, though we have
38203 	 *  to change its class.
38204 	 *
38205 	 *  Internal value set to ToNumber(arg) or +0; if no arg given,
38206 	 *  ToNumber(undefined) = NaN, so special treatment is needed
38207 	 *  (above).  String internal value is immutable.
38208 	 */
38209 
38210 	/* XXX: helper */
38211 	duk_push_this(thr);
38212 	h_this = duk_known_hobject(thr, -1);
38213 	DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_NUMBER);
38214 
38215 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE]);
38216 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_this) == DUK_HOBJECT_CLASS_NUMBER);
38217 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_this));
38218 
38219 	duk_dup_0(thr);  /* -> [ val obj val ] */
38220 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
38221 	return 0;  /* no return value -> don't replace created value */
38222 }
38223 
38224 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_value_of(duk_hthread *thr) {
38225 	(void) duk__push_this_number_plain(thr);
38226 	return 1;
38227 }
38228 
38229 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_string(duk_hthread *thr) {
38230 	duk_small_int_t radix;
38231 	duk_small_uint_t n2s_flags;
38232 
38233 	(void) duk__push_this_number_plain(thr);
38234 	if (duk_is_undefined(thr, 0)) {
38235 		radix = 10;
38236 	} else {
38237 		radix = (duk_small_int_t) duk_to_int_check_range(thr, 0, 2, 36);
38238 	}
38239 	DUK_DDD(DUK_DDDPRINT("radix=%ld", (long) radix));
38240 
38241 	n2s_flags = 0;
38242 
38243 	duk_numconv_stringify(thr,
38244 	                      radix /*radix*/,
38245 	                      0 /*digits*/,
38246 	                      n2s_flags /*flags*/);
38247 	return 1;
38248 }
38249 
38250 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_hthread *thr) {
38251 	/* XXX: just use toString() for now; permitted although not recommended.
38252 	 * nargs==1, so radix is passed to toString().
38253 	 */
38254 	return duk_bi_number_prototype_to_string(thr);
38255 }
38256 
38257 /*
38258  *  toFixed(), toExponential(), toPrecision()
38259  */
38260 
38261 /* XXX: shared helper for toFixed(), toExponential(), toPrecision()? */
38262 
38263 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_fixed(duk_hthread *thr) {
38264 	duk_small_int_t frac_digits;
38265 	duk_double_t d;
38266 	duk_small_int_t c;
38267 	duk_small_uint_t n2s_flags;
38268 
38269 	/* In ES5.1 frac_digits is coerced first; in ES2015 the 'this number
38270 	 * value' check is done first.
38271 	 */
38272 	d = duk__push_this_number_plain(thr);
38273 	frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);
38274 
38275 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
38276 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
38277 		goto use_to_string;
38278 	}
38279 
38280 	if (d >= 1.0e21 || d <= -1.0e21) {
38281 		goto use_to_string;
38282 	}
38283 
38284 	n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
38285 	            DUK_N2S_FLAG_FRACTION_DIGITS;
38286 
38287 	duk_numconv_stringify(thr,
38288 	                      10 /*radix*/,
38289 	                      frac_digits /*digits*/,
38290 	                      n2s_flags /*flags*/);
38291 	return 1;
38292 
38293  use_to_string:
38294 	DUK_ASSERT_TOP(thr, 2);
38295 	duk_to_string(thr, -1);
38296 	return 1;
38297 }
38298 
38299 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_exponential(duk_hthread *thr) {
38300 	duk_bool_t frac_undefined;
38301 	duk_small_int_t frac_digits;
38302 	duk_double_t d;
38303 	duk_small_int_t c;
38304 	duk_small_uint_t n2s_flags;
38305 
38306 	d = duk__push_this_number_plain(thr);
38307 
38308 	frac_undefined = duk_is_undefined(thr, 0);
38309 	duk_to_int(thr, 0);  /* for side effects */
38310 
38311 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
38312 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
38313 		goto use_to_string;
38314 	}
38315 
38316 	frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);
38317 
38318 	n2s_flags = DUK_N2S_FLAG_FORCE_EXP |
38319 	           (frac_undefined ? 0 : DUK_N2S_FLAG_FIXED_FORMAT);
38320 
38321 	duk_numconv_stringify(thr,
38322 	                      10 /*radix*/,
38323 	                      frac_digits + 1 /*leading digit + fractions*/,
38324 	                      n2s_flags /*flags*/);
38325 	return 1;
38326 
38327  use_to_string:
38328 	DUK_ASSERT_TOP(thr, 2);
38329 	duk_to_string(thr, -1);
38330 	return 1;
38331 }
38332 
38333 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_precision(duk_hthread *thr) {
38334 	/* The specification has quite awkward order of coercion and
38335 	 * checks for toPrecision().  The operations below are a bit
38336 	 * reordered, within constraints of observable side effects.
38337 	 */
38338 
38339 	duk_double_t d;
38340 	duk_small_int_t prec;
38341 	duk_small_int_t c;
38342 	duk_small_uint_t n2s_flags;
38343 
38344 	DUK_ASSERT_TOP(thr, 1);
38345 
38346 	d = duk__push_this_number_plain(thr);
38347 	if (duk_is_undefined(thr, 0)) {
38348 		goto use_to_string;
38349 	}
38350 	DUK_ASSERT_TOP(thr, 2);
38351 
38352 	duk_to_int(thr, 0);  /* for side effects */
38353 
38354 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
38355 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
38356 		goto use_to_string;
38357 	}
38358 
38359 	prec = (duk_small_int_t) duk_to_int_check_range(thr, 0, 1, 21);
38360 
38361 	n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
38362 	            DUK_N2S_FLAG_NO_ZERO_PAD;
38363 
38364 	duk_numconv_stringify(thr,
38365 	                      10 /*radix*/,
38366 	                      prec /*digits*/,
38367 	                      n2s_flags /*flags*/);
38368 	return 1;
38369 
38370  use_to_string:
38371 	/* Used when precision is undefined; also used for NaN (-> "NaN"),
38372 	 * and +/- infinity (-> "Infinity", "-Infinity").
38373 	 */
38374 
38375 	DUK_ASSERT_TOP(thr, 2);
38376 	duk_to_string(thr, -1);
38377 	return 1;
38378 }
38379 
38380 /*
38381  *  ES2015 isFinite() etc
38382  */
38383 
38384 #if defined(DUK_USE_ES6)
38385 DUK_INTERNAL duk_ret_t duk_bi_number_check_shared(duk_hthread *thr) {
38386 	duk_int_t magic;
38387 	duk_bool_t ret = 0;
38388 
38389 	if (duk_is_number(thr, 0)) {
38390 		duk_double_t d;
38391 
38392 		magic = duk_get_current_magic(thr);
38393 		d = duk_get_number(thr, 0);
38394 
38395 		switch (magic) {
38396 		case 0:  /* isFinite() */
38397 			ret = duk_double_is_finite(d);
38398 			break;
38399 		case 1:  /* isInteger() */
38400 			ret = duk_double_is_integer(d);
38401 			break;
38402 		case 2:  /* isNaN() */
38403 			ret = duk_double_is_nan(d);
38404 			break;
38405 		default:  /* isSafeInteger() */
38406 			DUK_ASSERT(magic == 3);
38407 			ret = duk_double_is_safe_integer(d);
38408 		}
38409 	}
38410 
38411 	duk_push_boolean(thr, ret);
38412 	return 1;
38413 }
38414 #endif  /* DUK_USE_ES6 */
38415 
38416 #endif  /* DUK_USE_NUMBER_BUILTIN */
38417 /*
38418  *  Object built-ins
38419  */
38420 
38421 /* #include duk_internal.h -> already included */
38422 
38423 /* Needed even when Object built-in disabled. */
38424 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_string(duk_hthread *thr) {
38425 	duk_tval *tv;
38426 
38427 	tv = DUK_HTHREAD_THIS_PTR(thr);
38428 	duk_push_class_string_tval(thr, tv, 0 /*avoid_side_effects*/);
38429 	return 1;
38430 }
38431 
38432 #if defined(DUK_USE_OBJECT_BUILTIN)
38433 DUK_INTERNAL duk_ret_t duk_bi_object_constructor(duk_hthread *thr) {
38434 	duk_uint_t arg_mask;
38435 
38436 	arg_mask = duk_get_type_mask(thr, 0);
38437 
38438 	if (!duk_is_constructor_call(thr) &&  /* not a constructor call */
38439 	    ((arg_mask & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED)) == 0)) {  /* and argument not null or undefined */
38440 		duk_to_object(thr, 0);
38441 		return 1;
38442 	}
38443 
38444 	/* Pointer and buffer primitive values are treated like other
38445 	 * primitives values which have a fully fledged object counterpart:
38446 	 * promote to an object value.  Lightfuncs and plain buffers are
38447 	 * coerced with ToObject() even they could also be returned as is.
38448 	 */
38449 	if (arg_mask & (DUK_TYPE_MASK_OBJECT |
38450 	                DUK_TYPE_MASK_STRING |
38451 	                DUK_TYPE_MASK_BOOLEAN |
38452 	                DUK_TYPE_MASK_NUMBER |
38453 	                DUK_TYPE_MASK_POINTER |
38454 	                DUK_TYPE_MASK_BUFFER |
38455 	                DUK_TYPE_MASK_LIGHTFUNC)) {
38456 		/* For DUK_TYPE_OBJECT the coercion is a no-op and could
38457 		 * be checked for explicitly, but Object(obj) calls are
38458 		 * not very common so opt for minimal footprint.
38459 		 */
38460 		duk_to_object(thr, 0);
38461 		return 1;
38462 	}
38463 
38464 	(void) duk_push_object_helper(thr,
38465 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
38466 	                              DUK_HOBJECT_FLAG_FASTREFS |
38467 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
38468 	                              DUK_BIDX_OBJECT_PROTOTYPE);
38469 	return 1;
38470 }
38471 #endif  /* DUK_USE_OBJECT_BUILTIN */
38472 
38473 #if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)
38474 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_assign(duk_hthread *thr) {
38475 	duk_idx_t nargs;
38476 	duk_int_t idx;
38477 
38478 	nargs = duk_get_top_require_min(thr, 1 /*min_top*/);
38479 
38480 	duk_to_object(thr, 0);
38481 	for (idx = 1; idx < nargs; idx++) {
38482 		/* E7 19.1.2.1 (step 4a) */
38483 		if (duk_is_null_or_undefined(thr, idx)) {
38484 			continue;
38485 		}
38486 
38487 		/* duk_enum() respects ES2015+ [[OwnPropertyKeys]] ordering, which is
38488 		 * convenient here.
38489 		 */
38490 		duk_to_object(thr, idx);
38491 		duk_enum(thr, idx, DUK_ENUM_OWN_PROPERTIES_ONLY);
38492 		while (duk_next(thr, -1, 1 /*get_value*/)) {
38493 			/* [ target ... enum key value ] */
38494 			duk_put_prop(thr, 0);
38495 			/* [ target ... enum ] */
38496 		}
38497 		/* Could pop enumerator, but unnecessary because of duk_set_top()
38498 		 * below.
38499 		 */
38500 	}
38501 
38502 	duk_set_top(thr, 1);
38503 	return 1;
38504 }
38505 #endif
38506 
38507 #if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)
38508 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is(duk_hthread *thr) {
38509 	DUK_ASSERT_TOP(thr, 2);
38510 	duk_push_boolean(thr, duk_samevalue(thr, 0, 1));
38511 	return 1;
38512 }
38513 #endif
38514 
38515 #if defined(DUK_USE_OBJECT_BUILTIN)
38516 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_create(duk_hthread *thr) {
38517 	duk_hobject *proto;
38518 
38519 	DUK_ASSERT_TOP(thr, 2);
38520 
38521 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
38522 	duk_hbufobj_promote_plain(thr, 0);
38523 #endif
38524 	proto = duk_require_hobject_accept_mask(thr, 0, DUK_TYPE_MASK_NULL);
38525 	DUK_ASSERT(proto != NULL || duk_is_null(thr, 0));
38526 
38527 	(void) duk_push_object_helper_proto(thr,
38528 	                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
38529 	                                    DUK_HOBJECT_FLAG_FASTREFS |
38530 	                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
38531 	                                    proto);
38532 
38533 	if (!duk_is_undefined(thr, 1)) {
38534 		/* [ O Properties obj ] */
38535 
38536 		duk_replace(thr, 0);
38537 
38538 		/* [ obj Properties ] */
38539 
38540 		/* Just call the "original" Object.defineProperties() to
38541 		 * finish up.
38542 		 */
38543 
38544 		return duk_bi_object_constructor_define_properties(thr);
38545 	}
38546 
38547 	/* [ O Properties obj ] */
38548 
38549 	return 1;
38550 }
38551 #endif  /* DUK_USE_OBJECT_BUILTIN */
38552 
38553 #if defined(DUK_USE_OBJECT_BUILTIN)
38554 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_hthread *thr) {
38555 	duk_small_uint_t pass;
38556 	duk_uint_t defprop_flags;
38557 	duk_hobject *obj;
38558 	duk_idx_t idx_value;
38559 	duk_hobject *get;
38560 	duk_hobject *set;
38561 
38562 	/* Lightfunc and plain buffer handling by ToObject() coercion. */
38563 	obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
38564 	DUK_ASSERT(obj != NULL);
38565 
38566 	duk_to_object(thr, 1);        /* properties object */
38567 
38568 	DUK_DDD(DUK_DDDPRINT("target=%!iT, properties=%!iT",
38569 	                     (duk_tval *) duk_get_tval(thr, 0),
38570 	                     (duk_tval *) duk_get_tval(thr, 1)));
38571 
38572 	/*
38573 	 *  Two pass approach to processing the property descriptors.
38574 	 *  On first pass validate and normalize all descriptors before
38575 	 *  any changes are made to the target object.  On second pass
38576 	 *  make the actual modifications to the target object.
38577 	 *
38578 	 *  Right now we'll just use the same normalize/validate helper
38579 	 *  on both passes, ignoring its outputs on the first pass.
38580 	 */
38581 
38582 	for (pass = 0; pass < 2; pass++) {
38583 		duk_set_top(thr, 2);  /* -> [ hobject props ] */
38584 		duk_enum(thr, 1, DUK_ENUM_OWN_PROPERTIES_ONLY | DUK_ENUM_INCLUDE_SYMBOLS /*enum_flags*/);
38585 
38586 		for (;;) {
38587 			duk_hstring *key;
38588 
38589 			/* [ hobject props enum(props) ] */
38590 
38591 			duk_set_top(thr, 3);
38592 
38593 			if (!duk_next(thr, 2, 1 /*get_value*/)) {
38594 				break;
38595 			}
38596 
38597 			DUK_DDD(DUK_DDDPRINT("-> key=%!iT, desc=%!iT",
38598 			                     (duk_tval *) duk_get_tval(thr, -2),
38599 			                     (duk_tval *) duk_get_tval(thr, -1)));
38600 
38601 			/* [ hobject props enum(props) key desc ] */
38602 
38603 			duk_hobject_prepare_property_descriptor(thr,
38604 			                                        4 /*idx_desc*/,
38605 			                                        &defprop_flags,
38606 			                                        &idx_value,
38607 			                                        &get,
38608 			                                        &set);
38609 
38610 			/* [ hobject props enum(props) key desc [multiple values] ] */
38611 
38612 			if (pass == 0) {
38613 				continue;
38614 			}
38615 
38616 			/* This allows symbols on purpose. */
38617 			key = duk_known_hstring(thr, 3);
38618 			DUK_ASSERT(key != NULL);
38619 
38620 			duk_hobject_define_property_helper(thr,
38621 			                                   defprop_flags,
38622 			                                   obj,
38623 			                                   key,
38624 			                                   idx_value,
38625 			                                   get,
38626 			                                   set,
38627 			                                   1 /*throw_flag*/);
38628 		}
38629 	}
38630 
38631 	/*
38632 	 *  Return target object
38633 	 */
38634 
38635 	duk_dup_0(thr);
38636 	return 1;
38637 }
38638 #endif  /* DUK_USE_OBJECT_BUILTIN */
38639 
38640 #if defined(DUK_USE_OBJECT_BUILTIN)
38641 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_hthread *thr) {
38642 	DUK_ASSERT_TOP(thr, 1);
38643 
38644 	duk_seal_freeze_raw(thr, 0, (duk_bool_t) duk_get_current_magic(thr) /*is_freeze*/);
38645 	return 1;
38646 }
38647 #endif  /* DUK_USE_OBJECT_BUILTIN */
38648 
38649 #if defined(DUK_USE_OBJECT_BUILTIN)
38650 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_hthread *thr) {
38651 	duk_hobject *h;
38652 	duk_bool_t is_frozen;
38653 	duk_uint_t mask;
38654 
38655 	is_frozen = (duk_bool_t) duk_get_current_magic(thr);
38656 	mask = duk_get_type_mask(thr, 0);
38657 	if (mask & (DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
38658 		DUK_ASSERT(is_frozen == 0 || is_frozen == 1);
38659 		duk_push_boolean(thr, (mask & DUK_TYPE_MASK_LIGHTFUNC) ?
38660 		                          1 :               /* lightfunc always frozen and sealed */
38661 		                          (is_frozen ^ 1)); /* buffer sealed but not frozen (index props writable) */
38662 	} else {
38663 		/* ES2015 Sections 19.1.2.12, 19.1.2.13: anything other than an object
38664 		 * is considered to be already sealed and frozen.
38665 		 */
38666 		h = duk_get_hobject(thr, 0);
38667 		duk_push_boolean(thr, (h == NULL) ||
38668 		                      duk_hobject_object_is_sealed_frozen_helper(thr, h, is_frozen /*is_frozen*/));
38669 	}
38670 	return 1;
38671 }
38672 #endif  /* DUK_USE_OBJECT_BUILTIN */
38673 
38674 #if defined(DUK_USE_OBJECT_BUILTIN)
38675 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_hthread *thr) {
38676 	DUK_ASSERT_TOP(thr, 0);
38677 	(void) duk_push_this_coercible_to_object(thr);
38678 	duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_TO_STRING);
38679 #if 0  /* This is mentioned explicitly in the E5.1 spec, but duk_call_method() checks for it in practice. */
38680 	duk_require_callable(thr, 1);
38681 #endif
38682 	duk_dup_0(thr);  /* -> [ O toString O ] */
38683 	duk_call_method(thr, 0);  /* XXX: call method tail call? */
38684 	return 1;
38685 }
38686 #endif  /* DUK_USE_OBJECT_BUILTIN */
38687 
38688 #if defined(DUK_USE_OBJECT_BUILTIN)
38689 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_value_of(duk_hthread *thr) {
38690 	/* For lightfuncs and plain buffers, returns Object() coerced. */
38691 	(void) duk_push_this_coercible_to_object(thr);
38692 	return 1;
38693 }
38694 #endif  /* DUK_USE_OBJECT_BUILTIN */
38695 
38696 #if defined(DUK_USE_OBJECT_BUILTIN)
38697 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_hthread *thr) {
38698 	duk_hobject *h_v;
38699 	duk_hobject *h_obj;
38700 
38701 	DUK_ASSERT_TOP(thr, 1);
38702 
38703 	h_v = duk_get_hobject(thr, 0);
38704 	if (!h_v) {
38705 		duk_push_false(thr);  /* XXX: tail call: return duk_push_false(thr) */
38706 		return 1;
38707 	}
38708 
38709 	h_obj = duk_push_this_coercible_to_object(thr);
38710 	DUK_ASSERT(h_obj != NULL);
38711 
38712 	/* E5.1 Section 15.2.4.6, step 3.a, lookup proto once before compare.
38713 	 * Prototype loops should cause an error to be thrown.
38714 	 */
38715 	duk_push_boolean(thr, duk_hobject_prototype_chain_contains(thr, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_v), h_obj, 0 /*ignore_loop*/));
38716 	return 1;
38717 }
38718 #endif  /* DUK_USE_OBJECT_BUILTIN */
38719 
38720 #if defined(DUK_USE_OBJECT_BUILTIN)
38721 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_has_own_property(duk_hthread *thr) {
38722 	return (duk_ret_t) duk_hobject_object_ownprop_helper(thr, 0 /*required_desc_flags*/);
38723 }
38724 #endif  /* DUK_USE_OBJECT_BUILTIN */
38725 
38726 #if defined(DUK_USE_OBJECT_BUILTIN)
38727 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_hthread *thr) {
38728 	return (duk_ret_t) duk_hobject_object_ownprop_helper(thr, DUK_PROPDESC_FLAG_ENUMERABLE /*required_desc_flags*/);
38729 }
38730 #endif  /* DUK_USE_OBJECT_BUILTIN */
38731 
38732 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38733 /* Shared helper to implement Object.getPrototypeOf,
38734  * Object.prototype.__proto__ getter, and Reflect.getPrototypeOf.
38735  *
38736  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
38737  */
38738 DUK_INTERNAL duk_ret_t duk_bi_object_getprototype_shared(duk_hthread *thr) {
38739 	/*
38740 	 *  magic = 0: __proto__ getter
38741 	 *  magic = 1: Object.getPrototypeOf()
38742 	 *  magic = 2: Reflect.getPrototypeOf()
38743 	 */
38744 
38745 	duk_hobject *h;
38746 	duk_hobject *proto;
38747 	duk_tval *tv;
38748 	duk_int_t magic;
38749 
38750 	magic = duk_get_current_magic(thr);
38751 
38752 	if (magic == 0) {
38753 		DUK_ASSERT_TOP(thr, 0);
38754 		duk_push_this_coercible_to_object(thr);
38755 	}
38756 	DUK_ASSERT(duk_get_top(thr) >= 1);
38757 	if (magic < 2) {
38758 		/* ES2015 Section 19.1.2.9, step 1 */
38759 		duk_to_object(thr, 0);
38760 	}
38761 	tv = DUK_GET_TVAL_POSIDX(thr, 0);
38762 
38763 	switch (DUK_TVAL_GET_TAG(tv)) {
38764 	case DUK_TAG_BUFFER:
38765 		proto = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
38766 		break;
38767 	case DUK_TAG_LIGHTFUNC:
38768 		proto = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
38769 		break;
38770 	case DUK_TAG_OBJECT:
38771 		h = DUK_TVAL_GET_OBJECT(tv);
38772 		proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
38773 		break;
38774 	default:
38775 		/* This implicitly handles CheckObjectCoercible() caused
38776 		 * TypeError.
38777 		 */
38778 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
38779 	}
38780 	if (proto != NULL) {
38781 		duk_push_hobject(thr, proto);
38782 	} else {
38783 		duk_push_null(thr);
38784 	}
38785 	return 1;
38786 }
38787 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
38788 
38789 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38790 /* Shared helper to implement ES2015 Object.setPrototypeOf,
38791  * Object.prototype.__proto__ setter, and Reflect.setPrototypeOf.
38792  *
38793  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
38794  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.setprototypeof
38795  */
38796 DUK_INTERNAL duk_ret_t duk_bi_object_setprototype_shared(duk_hthread *thr) {
38797 	/*
38798 	 *  magic = 0: __proto__ setter
38799 	 *  magic = 1: Object.setPrototypeOf()
38800 	 *  magic = 2: Reflect.setPrototypeOf()
38801 	 */
38802 
38803 	duk_hobject *h_obj;
38804 	duk_hobject *h_new_proto;
38805 	duk_hobject *h_curr;
38806 	duk_ret_t ret_success = 1;  /* retval for success path */
38807 	duk_uint_t mask;
38808 	duk_int_t magic;
38809 
38810 	/* Preliminaries for __proto__ and setPrototypeOf (E6 19.1.2.18 steps 1-4). */
38811 	magic = duk_get_current_magic(thr);
38812 	if (magic == 0) {
38813 		duk_push_this_check_object_coercible(thr);
38814 		duk_insert(thr, 0);
38815 		if (!duk_check_type_mask(thr, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT)) {
38816 			return 0;
38817 		}
38818 
38819 		/* __proto__ setter returns 'undefined' on success unlike the
38820 		 * setPrototypeOf() call which returns the target object.
38821 		 */
38822 		ret_success = 0;
38823 	} else {
38824 		if (magic == 1) {
38825 			duk_require_object_coercible(thr, 0);
38826 		} else {
38827 			duk_require_hobject_accept_mask(thr, 0,
38828 			                                DUK_TYPE_MASK_LIGHTFUNC |
38829 			                                DUK_TYPE_MASK_BUFFER);
38830 		}
38831 		duk_require_type_mask(thr, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT);
38832 	}
38833 
38834 	h_new_proto = duk_get_hobject(thr, 1);
38835 	/* h_new_proto may be NULL */
38836 
38837 	mask = duk_get_type_mask(thr, 0);
38838 	if (mask & (DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
38839 		duk_hobject *curr_proto;
38840 		curr_proto = thr->builtins[(mask & DUK_TYPE_MASK_LIGHTFUNC) ?
38841 		                               DUK_BIDX_FUNCTION_PROTOTYPE :
38842 		                               DUK_BIDX_UINT8ARRAY_PROTOTYPE];
38843 		if (h_new_proto == curr_proto) {
38844 			goto skip;
38845 		}
38846 		goto fail_nonextensible;
38847 	}
38848 	h_obj = duk_get_hobject(thr, 0);
38849 	if (h_obj == NULL) {
38850 		goto skip;
38851 	}
38852 	DUK_ASSERT(h_obj != NULL);
38853 
38854 	/* [[SetPrototypeOf]] standard behavior, E6 9.1.2. */
38855 	/* TODO: implement Proxy object support here */
38856 
38857 	if (h_new_proto == DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_obj)) {
38858 		goto skip;
38859 	}
38860 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(h_obj)) {
38861 		goto fail_nonextensible;
38862 	}
38863 	for (h_curr = h_new_proto; h_curr != NULL; h_curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_curr)) {
38864 		/* Loop prevention. */
38865 		if (h_curr == h_obj) {
38866 			goto fail_loop;
38867 		}
38868 	}
38869 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h_obj, h_new_proto);
38870 	/* fall thru */
38871 
38872  skip:
38873 	duk_set_top(thr, 1);
38874 	if (magic == 2) {
38875 		duk_push_true(thr);
38876 	}
38877 	return ret_success;
38878 
38879  fail_nonextensible:
38880  fail_loop:
38881 	if (magic != 2) {
38882 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
38883 	} else {
38884 		duk_push_false(thr);
38885 		return 1;
38886 	}
38887 }
38888 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
38889 
38890 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38891 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_property(duk_hthread *thr) {
38892 	/*
38893 	 *  magic = 0: Object.defineProperty()
38894 	 *  magic = 1: Reflect.defineProperty()
38895 	 */
38896 
38897 	duk_hobject *obj;
38898 	duk_hstring *key;
38899 	duk_hobject *get;
38900 	duk_hobject *set;
38901 	duk_idx_t idx_value;
38902 	duk_uint_t defprop_flags;
38903 	duk_small_uint_t magic;
38904 	duk_bool_t throw_flag;
38905 	duk_bool_t ret;
38906 
38907 	DUK_ASSERT(thr != NULL);
38908 
38909 	DUK_DDD(DUK_DDDPRINT("Object.defineProperty(): ctx=%p obj=%!T key=%!T desc=%!T",
38910 	                     (void *) thr,
38911 	                     (duk_tval *) duk_get_tval(thr, 0),
38912 	                     (duk_tval *) duk_get_tval(thr, 1),
38913 	                     (duk_tval *) duk_get_tval(thr, 2)));
38914 
38915 	/* [ obj key desc ] */
38916 
38917 	magic = (duk_small_uint_t) duk_get_current_magic(thr);
38918 
38919 	/* Lightfuncs are currently supported by coercing to a temporary
38920 	 * Function object; changes will be allowed (the coerced value is
38921 	 * extensible) but will be lost.  Same for plain buffers.
38922 	 */
38923 	obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
38924 	DUK_ASSERT(obj != NULL);
38925 	key = duk_to_property_key_hstring(thr, 1);
38926 	(void) duk_require_hobject(thr, 2);
38927 
38928 	DUK_ASSERT(obj != NULL);
38929 	DUK_ASSERT(key != NULL);
38930 	DUK_ASSERT(duk_get_hobject(thr, 2) != NULL);
38931 
38932 	/*
38933 	 *  Validate and convert argument property descriptor (an ECMAScript
38934 	 *  object) into a set of defprop_flags and possibly property value,
38935 	 *  getter, and/or setter values on the value stack.
38936 	 *
38937 	 *  Lightfunc set/get values are coerced to full Functions.
38938 	 */
38939 
38940 	duk_hobject_prepare_property_descriptor(thr,
38941 	                                        2 /*idx_desc*/,
38942 	                                        &defprop_flags,
38943 	                                        &idx_value,
38944 	                                        &get,
38945 	                                        &set);
38946 
38947 	/*
38948 	 *  Use Object.defineProperty() helper for the actual operation.
38949 	 */
38950 
38951 	DUK_ASSERT(magic == 0U || magic == 1U);
38952 	throw_flag = magic ^ 1U;
38953 	ret = duk_hobject_define_property_helper(thr,
38954 	                                         defprop_flags,
38955 	                                         obj,
38956 	                                         key,
38957 	                                         idx_value,
38958 	                                         get,
38959 	                                         set,
38960 	                                         throw_flag);
38961 
38962 	/* Ignore the normalize/validate helper outputs on the value stack,
38963 	 * they're popped automatically.
38964 	 */
38965 
38966 	if (magic == 0U) {
38967 		/* Object.defineProperty(): return target object. */
38968 		duk_push_hobject(thr, obj);
38969 	} else {
38970 		/* Reflect.defineProperty(): return success/fail. */
38971 		duk_push_boolean(thr, ret);
38972 	}
38973 	return 1;
38974 }
38975 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
38976 
38977 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38978 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_hthread *thr) {
38979 	DUK_ASSERT_TOP(thr, 2);
38980 
38981 	/* ES2015 Section 19.1.2.6, step 1 */
38982 	if (duk_get_current_magic(thr) == 0) {
38983 		duk_to_object(thr, 0);
38984 	}
38985 
38986 	/* [ obj key ] */
38987 
38988 	duk_hobject_object_get_own_property_descriptor(thr, -2);
38989 	return 1;
38990 }
38991 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
38992 
38993 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38994 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_extensible(duk_hthread *thr) {
38995 	/*
38996 	 *  magic = 0: Object.isExtensible()
38997 	 *  magic = 1: Reflect.isExtensible()
38998 	 */
38999 
39000 	duk_hobject *h;
39001 
39002 	if (duk_get_current_magic(thr) == 0) {
39003 		h = duk_get_hobject(thr, 0);
39004 	} else {
39005 		/* Reflect.isExtensible(): throw if non-object, but we accept lightfuncs
39006 		 * and plain buffers here because they pretend to be objects.
39007 		 */
39008 		h = duk_require_hobject_accept_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
39009 	}
39010 
39011 	duk_push_boolean(thr, (h != NULL) && DUK_HOBJECT_HAS_EXTENSIBLE(h));
39012 	return 1;
39013 }
39014 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
39015 
39016 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
39017 /* Shared helper for various key/symbol listings, magic:
39018  * 0=Object.keys()
39019  * 1=Object.getOwnPropertyNames(),
39020  * 2=Object.getOwnPropertySymbols(),
39021  * 3=Reflect.ownKeys()
39022  */
39023 DUK_LOCAL const duk_small_uint_t duk__object_keys_enum_flags[4] = {
39024 	/* Object.keys() */
39025 	DUK_ENUM_OWN_PROPERTIES_ONLY |
39026 	    DUK_ENUM_NO_PROXY_BEHAVIOR,
39027 
39028 	/* Object.getOwnPropertyNames() */
39029 	DUK_ENUM_INCLUDE_NONENUMERABLE |
39030 	    DUK_ENUM_OWN_PROPERTIES_ONLY |
39031 	    DUK_ENUM_NO_PROXY_BEHAVIOR,
39032 
39033 	/* Object.getOwnPropertySymbols() */
39034 	DUK_ENUM_INCLUDE_SYMBOLS |
39035 	    DUK_ENUM_OWN_PROPERTIES_ONLY |
39036 	    DUK_ENUM_EXCLUDE_STRINGS |
39037 	    DUK_ENUM_INCLUDE_NONENUMERABLE |
39038 	    DUK_ENUM_NO_PROXY_BEHAVIOR,
39039 
39040 	/* Reflect.ownKeys() */
39041 	DUK_ENUM_INCLUDE_SYMBOLS |
39042 	    DUK_ENUM_OWN_PROPERTIES_ONLY |
39043 	    DUK_ENUM_INCLUDE_NONENUMERABLE |
39044 	    DUK_ENUM_NO_PROXY_BEHAVIOR
39045 };
39046 
39047 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_hthread *thr) {
39048 	duk_hobject *obj;
39049 #if defined(DUK_USE_ES6_PROXY)
39050 	duk_hobject *h_proxy_target;
39051 	duk_hobject *h_proxy_handler;
39052 	duk_hobject *h_trap_result;
39053 #endif
39054 	duk_small_uint_t enum_flags;
39055 	duk_int_t magic;
39056 
39057 	DUK_ASSERT_TOP(thr, 1);
39058 
39059 	magic = duk_get_current_magic(thr);
39060 	if (magic == 3) {
39061 		/* ES2015 Section 26.1.11 requires a TypeError for non-objects.  Lightfuncs
39062 		 * and plain buffers pretend to be objects, so accept those too.
39063 		 */
39064 		obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
39065 	} else {
39066 		/* ES2015: ToObject coerce. */
39067 		obj = duk_to_hobject(thr, 0);
39068 	}
39069 	DUK_ASSERT(obj != NULL);
39070 	DUK_UNREF(obj);
39071 
39072 	/* XXX: proxy chains */
39073 
39074 #if defined(DUK_USE_ES6_PROXY)
39075 	/* XXX: better sharing of code between proxy target call sites */
39076 	if (DUK_LIKELY(!duk_hobject_proxy_check(obj,
39077 	                                        &h_proxy_target,
39078 	                                        &h_proxy_handler))) {
39079 		goto skip_proxy;
39080 	}
39081 
39082 	duk_push_hobject(thr, h_proxy_handler);
39083 	if (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_OWN_KEYS)) {
39084 		/* Careful with reachability here: don't pop 'obj' before pushing
39085 		 * proxy target.
39086 		 */
39087 		DUK_DDD(DUK_DDDPRINT("no ownKeys trap, get keys of target instead"));
39088 		duk_pop_2(thr);
39089 		duk_push_hobject(thr, h_proxy_target);
39090 		duk_replace(thr, 0);
39091 		DUK_ASSERT_TOP(thr, 1);
39092 		goto skip_proxy;
39093 	}
39094 
39095 	/* [ obj handler trap ] */
39096 	duk_insert(thr, -2);
39097 	duk_push_hobject(thr, h_proxy_target);  /* -> [ obj trap handler target ] */
39098 	duk_call_method(thr, 1 /*nargs*/);      /* -> [ obj trap_result ] */
39099 	h_trap_result = duk_require_hobject(thr, -1);
39100 	DUK_UNREF(h_trap_result);
39101 
39102 	magic = duk_get_current_magic(thr);
39103 	DUK_ASSERT(magic >= 0 && magic < (duk_int_t) (sizeof(duk__object_keys_enum_flags) / sizeof(duk_small_uint_t)));
39104 	enum_flags = duk__object_keys_enum_flags[magic];
39105 
39106 	duk_proxy_ownkeys_postprocess(thr, h_proxy_target, enum_flags);
39107 	return 1;
39108 
39109  skip_proxy:
39110 #endif  /* DUK_USE_ES6_PROXY */
39111 
39112 	DUK_ASSERT_TOP(thr, 1);
39113 	magic = duk_get_current_magic(thr);
39114 	DUK_ASSERT(magic >= 0 && magic < (duk_int_t) (sizeof(duk__object_keys_enum_flags) / sizeof(duk_small_uint_t)));
39115 	enum_flags = duk__object_keys_enum_flags[magic];
39116 	return duk_hobject_get_enumerated_keys(thr, enum_flags);
39117 }
39118 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
39119 
39120 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
39121 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_hthread *thr) {
39122 	/*
39123 	 *  magic = 0: Object.preventExtensions()
39124 	 *  magic = 1: Reflect.preventExtensions()
39125 	 */
39126 
39127 	duk_hobject *h;
39128 	duk_uint_t mask;
39129 	duk_int_t magic;
39130 
39131 	magic = duk_get_current_magic(thr);
39132 
39133 	/* Silent success for lightfuncs and plain buffers always. */
39134 	mask = DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER;
39135 
39136 	/* Object.preventExtensions() silent success for non-object. */
39137 	if (magic == 0) {
39138 		mask |= DUK_TYPE_MASK_UNDEFINED |
39139 		        DUK_TYPE_MASK_NULL |
39140 		        DUK_TYPE_MASK_BOOLEAN |
39141 		        DUK_TYPE_MASK_NUMBER |
39142 		        DUK_TYPE_MASK_STRING |
39143 		        DUK_TYPE_MASK_POINTER;
39144 	}
39145 
39146 	if (duk_check_type_mask(thr, 0, mask)) {
39147 		/* Not an object, already non-extensible so always success. */
39148 		goto done;
39149 	}
39150 	h = duk_require_hobject(thr, 0);
39151 	DUK_ASSERT(h != NULL);
39152 
39153 	DUK_HOBJECT_CLEAR_EXTENSIBLE(h);
39154 
39155 	/* A non-extensible object cannot gain any more properties,
39156 	 * so this is a good time to compact.
39157 	 */
39158 	duk_hobject_compact_props(thr, h);
39159 
39160  done:
39161 	if (magic == 1) {
39162 		duk_push_true(thr);
39163 	}
39164 	return 1;
39165 }
39166 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
39167 
39168 /*
39169  *  __defineGetter__, __defineSetter__, __lookupGetter__, __lookupSetter__
39170  */
39171 
39172 #if defined(DUK_USE_ES8)
39173 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_defineaccessor(duk_hthread *thr) {
39174 	duk_push_this(thr);
39175 	duk_insert(thr, 0);
39176 	duk_to_object(thr, 0);
39177 	duk_require_callable(thr, 2);
39178 
39179 	/* [ ToObject(this) key getter/setter ] */
39180 
39181 	/* ToPropertyKey() coercion is not needed, duk_def_prop() does it. */
39182 	duk_def_prop(thr, 0, DUK_DEFPROP_SET_ENUMERABLE |
39183 	                     DUK_DEFPROP_SET_CONFIGURABLE |
39184 	                     (duk_get_current_magic(thr) ? DUK_DEFPROP_HAVE_SETTER : DUK_DEFPROP_HAVE_GETTER));
39185 	return 0;
39186 }
39187 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_hthread *thr) {
39188 	duk_uint_t sanity;
39189 
39190 	duk_push_this(thr);
39191 	duk_to_object(thr, -1);
39192 
39193 	/* XXX: Prototype walk (with sanity) should be a core property
39194 	 * operation, could add a flag to e.g. duk_get_prop_desc().
39195 	 */
39196 
39197 	/* ToPropertyKey() coercion is not needed, duk_get_prop_desc() does it. */
39198 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
39199 	while (!duk_is_undefined(thr, -1)) {
39200 		/* [ key obj ] */
39201 		duk_dup(thr, 0);
39202 		duk_get_prop_desc(thr, 1, 0 /*flags*/);
39203 		if (!duk_is_undefined(thr, -1)) {
39204 			duk_get_prop_stridx(thr, -1, (duk_get_current_magic(thr) != 0 ? DUK_STRIDX_SET : DUK_STRIDX_GET));
39205 			return 1;
39206 		}
39207 		duk_pop(thr);
39208 
39209 		if (DUK_UNLIKELY(sanity-- == 0)) {
39210 			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
39211 			DUK_WO_NORETURN(return 0;);
39212 		}
39213 
39214 		duk_get_prototype(thr, -1);
39215 		duk_remove(thr, -2);
39216 	}
39217 	return 1;
39218 }
39219 #endif  /* DUK_USE_ES8 */
39220 /*
39221  *  High resolution time API (performance.now() et al)
39222  *
39223  *  API specification: https://encoding.spec.whatwg.org/#ap://www.w3.org/TR/hr-time/
39224  */
39225 
39226 /* #include duk_internal.h -> already included */
39227 
39228 #if defined(DUK_USE_PERFORMANCE_BUILTIN)
39229 DUK_INTERNAL duk_ret_t duk_bi_performance_now(duk_hthread *thr) {
39230 	/* From API spec:
39231 	 * The DOMHighResTimeStamp type is used to store a time value in
39232 	 * milliseconds, measured relative from the time origin, global
39233 	 * monotonic clock, or a time value that represents a duration
39234 	 * between two DOMHighResTimeStamp's.
39235 	 */
39236 	duk_push_number(thr, duk_time_get_monotonic_time(thr));
39237 	return 1;
39238 }
39239 
39240 #if 0  /* Missing until semantics decided. */
39241 DUK_INTERNAL duk_ret_t duk_bi_performance_timeorigin_getter(duk_hthread *thr) {
39242 	/* No decision yet how to handle timeOrigins, e.g. should one be
39243 	 * initialized per heap, or per global object set.  See
39244 	 * https://www.w3.org/TR/hr-time/#time-origin.
39245 	 */
39246 	duk_push_uint(thr, 0);
39247 	return 1;
39248 }
39249 #endif  /* 0 */
39250 #endif  /* DUK_USE_PERFORMANCE_BUILTIN */
39251 /*
39252  *  Pointer built-ins
39253  */
39254 
39255 /* #include duk_internal.h -> already included */
39256 
39257 /*
39258  *  Constructor
39259  */
39260 
39261 DUK_INTERNAL duk_ret_t duk_bi_pointer_constructor(duk_hthread *thr) {
39262 	/* XXX: this behavior is quite useless now; it would be nice to be able
39263 	 * to create pointer values from e.g. numbers or strings.  Numbers are
39264 	 * problematic on 64-bit platforms though.  Hex encoded strings?
39265 	 */
39266 	if (duk_get_top(thr) == 0) {
39267 		duk_push_pointer(thr, NULL);
39268 	} else {
39269 		duk_to_pointer(thr, 0);
39270 	}
39271 	DUK_ASSERT(duk_is_pointer(thr, 0));
39272 	duk_set_top(thr, 1);
39273 
39274 	if (duk_is_constructor_call(thr)) {
39275 		(void) duk_push_object_helper(thr,
39276 		                              DUK_HOBJECT_FLAG_EXTENSIBLE |
39277 		                              DUK_HOBJECT_FLAG_FASTREFS |
39278 		                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER),
39279 		                              DUK_BIDX_POINTER_PROTOTYPE);
39280 
39281 		/* Pointer object internal value is immutable. */
39282 		duk_dup_0(thr);
39283 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
39284 	}
39285 	/* Note: unbalanced stack on purpose */
39286 
39287 	return 1;
39288 }
39289 
39290 /*
39291  *  toString(), valueOf()
39292  */
39293 
39294 DUK_INTERNAL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_hthread *thr) {
39295 	duk_tval *tv;
39296 	duk_small_int_t to_string = duk_get_current_magic(thr);
39297 
39298 	duk_push_this(thr);
39299 	tv = duk_require_tval(thr, -1);
39300 	DUK_ASSERT(tv != NULL);
39301 
39302 	if (DUK_TVAL_IS_POINTER(tv)) {
39303 		/* nop */
39304 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
39305 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
39306 		DUK_ASSERT(h != NULL);
39307 
39308 		/* Must be a "pointer object", i.e. class "Pointer" */
39309 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_POINTER) {
39310 			goto type_error;
39311 		}
39312 
39313 		duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
39314 	} else {
39315 		goto type_error;
39316 	}
39317 
39318 	if (to_string) {
39319 		duk_to_string(thr, -1);
39320 	}
39321 	return 1;
39322 
39323  type_error:
39324 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
39325 }
39326 /*
39327  *  Promise built-in
39328  */
39329 
39330 /* #include duk_internal.h -> already included */
39331 
39332 #if defined(DUK_USE_PROMISE_BUILTIN)
39333 
39334 DUK_INTERNAL duk_ret_t duk_bi_promise_constructor(duk_hthread *thr) {
39335 	DUK_ERROR_TYPE(thr, "unimplemented");
39336 	DUK_WO_NORETURN(return 0;);
39337 }
39338 
39339 DUK_INTERNAL duk_ret_t duk_bi_promise_all(duk_hthread *thr) {
39340 	DUK_ERROR_TYPE(thr, "unimplemented");
39341 	DUK_WO_NORETURN(return 0;);
39342 }
39343 
39344 DUK_INTERNAL duk_ret_t duk_bi_promise_race(duk_hthread *thr) {
39345 	DUK_ERROR_TYPE(thr, "unimplemented");
39346 	DUK_WO_NORETURN(return 0;);
39347 }
39348 
39349 DUK_INTERNAL duk_ret_t duk_bi_promise_reject(duk_hthread *thr) {
39350 	DUK_ERROR_TYPE(thr, "unimplemented");
39351 	DUK_WO_NORETURN(return 0;);
39352 }
39353 
39354 DUK_INTERNAL duk_ret_t duk_bi_promise_resolve(duk_hthread *thr) {
39355 	DUK_ERROR_TYPE(thr, "unimplemented");
39356 	DUK_WO_NORETURN(return 0;);
39357 }
39358 
39359 DUK_INTERNAL duk_ret_t duk_bi_promise_catch(duk_hthread *thr) {
39360 	DUK_ERROR_TYPE(thr, "unimplemented");
39361 	DUK_WO_NORETURN(return 0;);
39362 }
39363 
39364 DUK_INTERNAL duk_ret_t duk_bi_promise_then(duk_hthread *thr) {
39365 	DUK_ERROR_TYPE(thr, "unimplemented");
39366 	DUK_WO_NORETURN(return 0;);
39367 }
39368 
39369 #endif  /* DUK_USE_PROMISE_BUILTIN */
39370 /*
39371  *  Proxy built-in (ES2015)
39372  */
39373 
39374 /* #include duk_internal.h -> already included */
39375 
39376 #if defined(DUK_USE_ES6_PROXY)
39377 /* Post-process a Proxy ownKeys() result at stack top.  Push a cleaned up
39378  * array of valid result keys (strings or symbols).  TypeError for invalid
39379  * values.  Flags are shared with duk_enum().
39380  */
39381 DUK_INTERNAL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h_proxy_target, duk_uint_t flags) {
39382 	duk_uarridx_t i, len, idx;
39383 	duk_propdesc desc;
39384 
39385 	DUK_CTX_ASSERT_VALID(thr);
39386 	DUK_ASSERT(h_proxy_target != NULL);
39387 
39388 	len = (duk_uarridx_t) duk_get_length(thr, -1);
39389 	idx = 0;
39390 	duk_push_array(thr);
39391 	/* XXX: preallocated dense array, fill in directly */
39392 	for (i = 0; i < len; i++) {
39393 		duk_hstring *h;
39394 
39395 		/* [ obj trap_result res_arr ] */
39396 		(void) duk_get_prop_index(thr, -2, i);
39397 		h = duk_get_hstring(thr, -1);
39398 		if (h == NULL) {
39399 			DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr);
39400 			DUK_WO_NORETURN(return;);
39401 		}
39402 
39403 		if (!(flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
39404 			/* No support for 'getOwnPropertyDescriptor' trap yet,
39405 			 * so check enumerability always from target object
39406 			 * descriptor.
39407 			 */
39408 			if (duk_hobject_get_own_propdesc(thr, h_proxy_target, duk_known_hstring(thr, -1), &desc, 0 /*flags*/)) {
39409 				if ((desc.flags & DUK_PROPDESC_FLAG_ENUMERABLE) == 0) {
39410 					DUK_DDD(DUK_DDDPRINT("ignore non-enumerable property: %!T", duk_get_tval(thr, -1)));
39411 					goto skip_key;
39412 				}
39413 			} else {
39414 				DUK_DDD(DUK_DDDPRINT("ignore non-existent property: %!T", duk_get_tval(thr, -1)));
39415 				goto skip_key;
39416 			}
39417 		}
39418 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
39419 			if (!(flags & DUK_ENUM_INCLUDE_SYMBOLS)) {
39420 				DUK_DDD(DUK_DDDPRINT("ignore symbol property: %!T", duk_get_tval(thr, -1)));
39421 				goto skip_key;
39422 			}
39423 			if (DUK_HSTRING_HAS_HIDDEN(h) && !(flags & DUK_ENUM_INCLUDE_HIDDEN)) {
39424 				DUK_DDD(DUK_DDDPRINT("ignore hidden symbol property: %!T", duk_get_tval(thr, -1)));
39425 				goto skip_key;
39426 			}
39427 		} else {
39428 			if (flags & DUK_ENUM_EXCLUDE_STRINGS) {
39429 				DUK_DDD(DUK_DDDPRINT("ignore string property: %!T", duk_get_tval(thr, -1)));
39430 				goto skip_key;
39431 			}
39432 		}
39433 
39434 		/* [ obj trap_result res_arr propname ] */
39435 		duk_put_prop_index(thr, -2, idx++);
39436 		continue;
39437 
39438 	 skip_key:
39439 		duk_pop(thr);
39440 		continue;
39441 	}
39442 
39443 	/* XXX: Missing trap result validation for non-configurable target keys
39444 	 * (must be present), for non-extensible target all target keys must be
39445 	 * present and no extra keys can be present.
39446 	 * http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys
39447 	 */
39448 
39449 	/* XXX: The key enumerability check should trigger the "getOwnPropertyDescriptor"
39450 	 * trap which has not yet been implemented.  In the absence of such a trap,
39451 	 * the enumerability should be checked from the target object; this is
39452 	 * handled above.
39453 	 */
39454 }
39455 #endif  /* DUK_USE_ES6_PROXY */
39456 
39457 #if defined(DUK_USE_ES6_PROXY)
39458 DUK_INTERNAL duk_ret_t duk_bi_proxy_constructor(duk_hthread *thr) {
39459 	DUK_ASSERT_TOP(thr, 2);  /* [ target handler ] */
39460 
39461 	duk_require_constructor_call(thr);
39462 	duk_push_proxy(thr, 0 /*flags*/);  /* [ target handler ] -> [ proxy ] */
39463 	return 1;  /* replacement */
39464 }
39465 #endif  /* DUK_USE_ES6_PROXY */
39466 /*
39467  *  'Reflect' built-in (ES2016 Section 26.1)
39468  *  http://www.ecma-international.org/ecma-262/7.0/#sec-reflect-object
39469  *
39470  *  Many Reflect built-in functions are provided by shared helpers in
39471  *  duk_bi_object.c or duk_bi_function.c.
39472  */
39473 
39474 /* #include duk_internal.h -> already included */
39475 
39476 #if defined(DUK_USE_REFLECT_BUILTIN)
39477 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_delete_property(duk_hthread *thr) {
39478 	duk_tval *tv_obj;
39479 	duk_tval *tv_key;
39480 	duk_bool_t ret;
39481 
39482 	DUK_ASSERT_TOP(thr, 2);
39483 	(void) duk_require_hobject(thr, 0);
39484 	(void) duk_to_string(thr, 1);
39485 
39486 	/* [ target key ] */
39487 
39488 	DUK_ASSERT(thr != NULL);
39489 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
39490 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
39491 	ret = duk_hobject_delprop(thr, tv_obj, tv_key, 0 /*throw_flag*/);
39492 	duk_push_boolean(thr, ret);
39493 	return 1;
39494 }
39495 
39496 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_get(duk_hthread *thr) {
39497 	duk_tval *tv_obj;
39498 	duk_tval *tv_key;
39499 	duk_idx_t nargs;
39500 
39501 	DUK_ASSERT(thr != NULL);
39502 	nargs = duk_get_top_require_min(thr, 2 /*min_top*/);
39503 	(void) duk_require_hobject(thr, 0);
39504 	(void) duk_to_string(thr, 1);
39505 	if (nargs >= 3 && !duk_strict_equals(thr, 0, 2)) {
39506 		/* XXX: [[Get]] receiver currently unsupported */
39507 		DUK_ERROR_UNSUPPORTED(thr);
39508 		DUK_WO_NORETURN(return 0;);
39509 	}
39510 
39511 	/* [ target key receiver? ...? ] */
39512 
39513 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
39514 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
39515 	(void) duk_hobject_getprop(thr, tv_obj, tv_key);  /* This could also be a duk_get_prop(). */
39516 	return 1;
39517 }
39518 
39519 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_has(duk_hthread *thr) {
39520 	duk_tval *tv_obj;
39521 	duk_tval *tv_key;
39522 	duk_bool_t ret;
39523 
39524 	DUK_ASSERT(thr != NULL);
39525 	DUK_ASSERT_TOP(thr, 2);
39526 	(void) duk_require_hobject(thr, 0);
39527 	(void) duk_to_string(thr, 1);
39528 
39529 	/* [ target key ] */
39530 
39531 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
39532 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
39533 	ret = duk_hobject_hasprop(thr, tv_obj, tv_key);
39534 	duk_push_boolean(thr, ret);
39535 	return 1;
39536 }
39537 
39538 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_set(duk_hthread *thr) {
39539 	duk_tval *tv_obj;
39540 	duk_tval *tv_key;
39541 	duk_tval *tv_val;
39542 	duk_idx_t nargs;
39543 	duk_bool_t ret;
39544 
39545 	DUK_ASSERT(thr != NULL);
39546 	nargs = duk_get_top_require_min(thr, 3 /*min_top*/);
39547 	(void) duk_require_hobject(thr, 0);
39548 	(void) duk_to_string(thr, 1);
39549 	if (nargs >= 4 && !duk_strict_equals(thr, 0, 3)) {
39550 		/* XXX: [[Set]] receiver currently unsupported */
39551 		DUK_ERROR_UNSUPPORTED(thr);
39552 		DUK_WO_NORETURN(return 0;);
39553 	}
39554 
39555 	/* [ target key value receiver? ...? ] */
39556 
39557 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
39558 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
39559 	tv_val = DUK_GET_TVAL_POSIDX(thr, 2);
39560 	ret = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, 0 /*throw_flag*/);
39561 	duk_push_boolean(thr, ret);
39562 	return 1;
39563 }
39564 #endif  /* DUK_USE_REFLECT_BUILTIN */
39565 /*
39566  *  RegExp built-ins
39567  */
39568 
39569 /* #include duk_internal.h -> already included */
39570 
39571 #if defined(DUK_USE_REGEXP_SUPPORT)
39572 
39573 DUK_LOCAL void duk__get_this_regexp(duk_hthread *thr) {
39574 	duk_hobject *h;
39575 
39576 	duk_push_this(thr);
39577 	h = duk_require_hobject_with_class(thr, -1, DUK_HOBJECT_CLASS_REGEXP);
39578 	DUK_ASSERT(h != NULL);
39579 	DUK_UNREF(h);
39580 	duk_insert(thr, 0);  /* prepend regexp to valstack 0 index */
39581 }
39582 
39583 /* XXX: much to improve (code size) */
39584 DUK_INTERNAL duk_ret_t duk_bi_regexp_constructor(duk_hthread *thr) {
39585 	duk_hobject *h_pattern;
39586 
39587 	DUK_ASSERT_TOP(thr, 2);
39588 	h_pattern = duk_get_hobject(thr, 0);
39589 
39590 	if (!duk_is_constructor_call(thr) &&
39591 	    h_pattern != NULL &&
39592 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP &&
39593 	    duk_is_undefined(thr, 1)) {
39594 		/* Called as a function, pattern has [[Class]] "RegExp" and
39595 		 * flags is undefined -> return object as is.
39596 		 */
39597 		/* XXX: ES2015 has a NewTarget SameValue() check which is not
39598 		 * yet implemented.
39599 		 */
39600 		duk_dup_0(thr);
39601 		return 1;
39602 	}
39603 
39604 	/* Else functionality is identical for function call and constructor
39605 	 * call.
39606 	 */
39607 
39608 	if (h_pattern != NULL &&
39609 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP) {
39610 		duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_SOURCE);
39611 		if (duk_is_undefined(thr, 1)) {
39612 			/* In ES5 one would need to read the flags individually;
39613 			 * in ES2015 just read .flags.
39614 			 */
39615 			duk_get_prop_stridx(thr, 0, DUK_STRIDX_FLAGS);
39616 		} else {
39617 			/* In ES2015 allowed; overrides argument RegExp flags. */
39618 			duk_dup_1(thr);
39619 		}
39620 	} else {
39621 		if (duk_is_undefined(thr, 0)) {
39622 			duk_push_hstring_empty(thr);
39623 		} else {
39624 			duk_dup_0(thr);
39625 			duk_to_string(thr, -1);  /* Rejects Symbols. */
39626 		}
39627 		if (duk_is_undefined(thr, 1)) {
39628 			duk_push_hstring_empty(thr);
39629 		} else {
39630 			duk_dup_1(thr);
39631 			duk_to_string(thr, -1);  /* Rejects Symbols. */
39632 		}
39633 
39634 		/* [ ... pattern flags ] */
39635 	}
39636 
39637 	DUK_DDD(DUK_DDDPRINT("RegExp constructor/function call, pattern=%!T, flags=%!T",
39638 	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
39639 
39640 	/* [ ... pattern flags ] (both uncoerced) */
39641 
39642 	duk_to_string(thr, -2);
39643 	duk_to_string(thr, -1);
39644 	duk_regexp_compile(thr);
39645 
39646 	/* [ ... bytecode escaped_source ] */
39647 
39648 	duk_regexp_create_instance(thr);
39649 
39650 	/* [ ... RegExp ] */
39651 
39652 	return 1;
39653 }
39654 
39655 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_exec(duk_hthread *thr) {
39656 	duk__get_this_regexp(thr);
39657 
39658 	/* [ regexp input ] */
39659 
39660 	duk_regexp_match(thr);
39661 
39662 	/* [ result ] */
39663 
39664 	return 1;
39665 }
39666 
39667 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_test(duk_hthread *thr) {
39668 	duk__get_this_regexp(thr);
39669 
39670 	/* [ regexp input ] */
39671 
39672 	/* result object is created and discarded; wasteful but saves code space */
39673 	duk_regexp_match(thr);
39674 
39675 	/* [ result ] */
39676 
39677 	duk_push_boolean(thr, (duk_is_null(thr, -1) ? 0 : 1));
39678 
39679 	return 1;
39680 }
39681 
39682 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_tostring(duk_hthread *thr) {
39683 	/* This must be generic in ES2015 and later. */
39684 	DUK_ASSERT_TOP(thr, 0);
39685 	duk_push_this(thr);
39686 	duk_push_literal(thr, "/");
39687 	duk_get_prop_stridx(thr, 0, DUK_STRIDX_SOURCE);
39688 	duk_dup_m2(thr);  /* another "/" */
39689 	duk_get_prop_stridx(thr, 0, DUK_STRIDX_FLAGS);
39690 	duk_concat(thr, 4);
39691 	return 1;
39692 }
39693 
39694 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_flags(duk_hthread *thr) {
39695 	/* .flags is ES2015 but present even when ES2015 bindings are
39696 	 * disabled because the constructor relies on it.
39697 	 */
39698 	duk_uint8_t buf[8];  /* enough for all flags + NUL */
39699 	duk_uint8_t *p = buf;
39700 
39701 	/* .flags is generic and works on any object. */
39702 	duk_push_this(thr);
39703 	(void) duk_require_hobject(thr, -1);
39704 	if (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL)) {
39705 		*p++ = DUK_ASC_LC_G;
39706 	}
39707 	if (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_IGNORE_CASE, NULL)) {
39708 		*p++ = DUK_ASC_LC_I;
39709 	}
39710 	if (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_MULTILINE, NULL)) {
39711 		*p++ = DUK_ASC_LC_M;
39712 	}
39713 	/* .unicode: to be added */
39714 	/* .sticky: to be added */
39715 	*p++ = DUK_ASC_NUL;
39716 	DUK_ASSERT((duk_size_t) (p - buf) <= sizeof(buf));
39717 
39718 	duk_push_string(thr, (const char *) buf);
39719 	return 1;
39720 }
39721 
39722 /* Shared helper for providing .source, .global, .multiline, etc getters. */
39723 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_hthread *thr) {
39724 	duk_hstring *h_bc;
39725 	duk_small_uint_t re_flags;
39726 	duk_hobject *h;
39727 	duk_int_t magic;
39728 
39729 	DUK_ASSERT_TOP(thr, 0);
39730 
39731 	duk_push_this(thr);
39732 	h = duk_require_hobject(thr, -1);
39733 	magic = duk_get_current_magic(thr);
39734 
39735 	if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_REGEXP) {
39736 		duk_xget_owndataprop_stridx_short(thr, 0, DUK_STRIDX_INT_SOURCE);
39737 		duk_xget_owndataprop_stridx_short(thr, 0, DUK_STRIDX_INT_BYTECODE);
39738 		h_bc = duk_require_hstring(thr, -1);
39739 		re_flags = (duk_small_uint_t) DUK_HSTRING_GET_DATA(h_bc)[0];  /* Safe even if h_bc length is 0 (= NUL) */
39740 		duk_pop(thr);
39741 	} else if (h == thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]) {
39742 		/* In ES2015 and ES2016 a TypeError would be thrown here.
39743 		 * However, this had real world issues so ES2017 draft
39744 		 * allows RegExp.prototype specifically, returning '(?:)'
39745 		 * for .source and undefined for all flags.
39746 		 */
39747 		if (magic != 16 /* .source */) {
39748 			return 0;
39749 		}
39750 		duk_push_literal(thr, "(?:)");  /* .source handled by switch-case */
39751 		re_flags = 0;
39752 	} else {
39753 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
39754 	}
39755 
39756 	/* [ regexp source ] */
39757 
39758 	switch (magic) {
39759 	case 0: {  /* global */
39760 		duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_GLOBAL));
39761 		break;
39762 	}
39763 	case 1: {  /* ignoreCase */
39764 		duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_IGNORE_CASE));
39765 		break;
39766 	}
39767 	case 2: {  /* multiline */
39768 		duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_MULTILINE));
39769 		break;
39770 	}
39771 #if 0
39772 	/* Don't provide until implemented to avoid interfering with feature
39773 	 * detection in user code.
39774 	 */
39775 	case 3:    /* sticky */
39776 	case 4: {  /* unicode */
39777 		duk_push_false(thr);
39778 		break;
39779 	}
39780 #endif
39781 	default: {  /* source */
39782 		/* leave 'source' on top */
39783 		break;
39784 	}
39785 	}
39786 
39787 	return 1;
39788 }
39789 
39790 #endif  /* DUK_USE_REGEXP_SUPPORT */
39791 /*
39792  *  String built-ins
39793  *
39794  *  Most String built-ins must only accept strings (or String objects).
39795  *  Symbols, represented internally as strings, must be generally rejected.
39796  *  The duk_push_this_coercible_to_string() helper does this automatically.
39797  */
39798 
39799 /* XXX: There are several limitations in the current implementation for
39800  * strings with >= 0x80000000UL characters.  In some cases one would need
39801  * to be able to represent the range [-0xffffffff,0xffffffff] and so on.
39802  * Generally character and byte length are assumed to fit into signed 32
39803  * bits (< 0x80000000UL).  Places with issues are not marked explicitly
39804  * below in all cases, look for signed type usage (duk_int_t etc) for
39805  * offsets/lengths.
39806  */
39807 
39808 /* #include duk_internal.h -> already included */
39809 
39810 #if defined(DUK_USE_STRING_BUILTIN)
39811 
39812 /*
39813  *  Helpers
39814  */
39815 
39816 DUK_LOCAL duk_hstring *duk__str_tostring_notregexp(duk_hthread *thr, duk_idx_t idx) {
39817 	duk_hstring *h;
39818 
39819 	if (duk_get_class_number(thr, idx) == DUK_HOBJECT_CLASS_REGEXP) {
39820 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
39821 		DUK_WO_NORETURN(return NULL;);
39822 	}
39823 	h = duk_to_hstring(thr, idx);
39824 	DUK_ASSERT(h != NULL);
39825 
39826 	return h;
39827 }
39828 
39829 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) {
39830 	duk_int_t cpos;
39831 	duk_int_t bpos;
39832 	const duk_uint8_t *p_start, *p_end, *p;
39833 	const duk_uint8_t *q_start;
39834 	duk_int_t q_blen;
39835 	duk_uint8_t firstbyte;
39836 	duk_uint8_t t;
39837 
39838 	cpos = start_cpos;
39839 
39840 	/* Empty searchstring always matches; cpos must be clamped here.
39841 	 * (If q_blen were < 0 due to clamped coercion, it would also be
39842 	 * caught here.)
39843 	 */
39844 	q_start = DUK_HSTRING_GET_DATA(h_search);
39845 	q_blen = (duk_int_t) DUK_HSTRING_GET_BYTELEN(h_search);
39846 	if (q_blen <= 0) {
39847 		return cpos;
39848 	}
39849 	DUK_ASSERT(q_blen > 0);
39850 
39851 	bpos = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_this, (duk_uint32_t) cpos);
39852 
39853 	p_start = DUK_HSTRING_GET_DATA(h_this);
39854 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_this);
39855 	p = p_start + bpos;
39856 
39857 	/* This loop is optimized for size.  For speed, there should be
39858 	 * two separate loops, and we should ensure that memcmp() can be
39859 	 * used without an extra "will searchstring fit" check.  Doing
39860 	 * the preconditioning for 'p' and 'p_end' is easy but cpos
39861 	 * must be updated if 'p' is wound back (backward scanning).
39862 	 */
39863 
39864 	firstbyte = q_start[0];  /* leading byte of match string */
39865 	while (p <= p_end && p >= p_start) {
39866 		t = *p;
39867 
39868 		/* For ECMAScript strings, this check can only match for
39869 		 * initial UTF-8 bytes (not continuation bytes).  For other
39870 		 * strings all bets are off.
39871 		 */
39872 
39873 		if ((t == firstbyte) && ((duk_size_t) (p_end - p) >= (duk_size_t) q_blen)) {
39874 			DUK_ASSERT(q_blen > 0);
39875 			if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
39876 				return cpos;
39877 			}
39878 		}
39879 
39880 		/* track cpos while scanning */
39881 		if (backwards) {
39882 			/* when going backwards, we decrement cpos 'early';
39883 			 * 'p' may point to a continuation byte of the char
39884 			 * at offset 'cpos', but that's OK because we'll
39885 			 * backtrack all the way to the initial byte.
39886 			 */
39887 			if ((t & 0xc0) != 0x80) {
39888 				cpos--;
39889 			}
39890 			p--;
39891 		} else {
39892 			if ((t & 0xc0) != 0x80) {
39893 				cpos++;
39894 			}
39895 			p++;
39896 		}
39897 	}
39898 
39899 	/* Not found.  Empty string case is handled specially above. */
39900 	return -1;
39901 }
39902 
39903 /*
39904  *  Constructor
39905  */
39906 
39907 DUK_INTERNAL duk_ret_t duk_bi_string_constructor(duk_hthread *thr) {
39908 	duk_hstring *h;
39909 	duk_uint_t flags;
39910 
39911 	/* String constructor needs to distinguish between an argument not given at all
39912 	 * vs. given as 'undefined'.  We're a vararg function to handle this properly.
39913 	 */
39914 
39915 	/* XXX: copy current activation flags to thr, including current magic,
39916 	 * is_constructor_call etc.  This takes a few bytes in duk_hthread but
39917 	 * makes call sites smaller (there are >30 is_constructor_call and get
39918 	 * current magic call sites.
39919 	 */
39920 
39921 	if (duk_get_top(thr) == 0) {
39922 		duk_push_hstring_empty(thr);
39923 	} else {
39924 		h = duk_to_hstring_acceptsymbol(thr, 0);
39925 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h) && !duk_is_constructor_call(thr))) {
39926 			duk_push_symbol_descriptive_string(thr, h);
39927 			duk_replace(thr, 0);
39928 		}
39929 	}
39930 	duk_to_string(thr, 0);  /* catches symbol argument for constructor call */
39931 	DUK_ASSERT(duk_is_string(thr, 0));
39932 	duk_set_top(thr, 1);  /* Top may be 1 or larger. */
39933 
39934 	if (duk_is_constructor_call(thr)) {
39935 		/* String object internal value is immutable */
39936 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
39937 		        DUK_HOBJECT_FLAG_FASTREFS |
39938 		        DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
39939 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
39940 		duk_push_object_helper(thr, flags, DUK_BIDX_STRING_PROTOTYPE);
39941 		duk_dup_0(thr);
39942 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
39943 	}
39944 	/* Note: unbalanced stack on purpose */
39945 
39946 	return 1;
39947 }
39948 
39949 DUK_LOCAL duk_ret_t duk__construct_from_codepoints(duk_hthread *thr, duk_bool_t nonbmp) {
39950 	duk_bufwriter_ctx bw_alloc;
39951 	duk_bufwriter_ctx *bw;
39952 	duk_idx_t i, n;
39953 	duk_ucodepoint_t cp;
39954 
39955 	/* XXX: It would be nice to build the string directly but ToUint16()
39956 	 * coercion is needed so a generic helper would not be very
39957 	 * helpful (perhaps coerce the value stack first here and then
39958 	 * build a string from a duk_tval number sequence in one go?).
39959 	 */
39960 
39961 	n = duk_get_top(thr);
39962 
39963 	bw = &bw_alloc;
39964 	DUK_BW_INIT_PUSHBUF(thr, bw, (duk_size_t) n);  /* initial estimate for ASCII only codepoints */
39965 
39966 	for (i = 0; i < n; i++) {
39967 		/* XXX: could improve bufwriter handling to write multiple codepoints
39968 		 * with one ensure call but the relative benefit would be quite small.
39969 		 */
39970 
39971 		if (nonbmp) {
39972 			/* ES2015 requires that (1) SameValue(cp, ToInteger(cp)) and
39973 			 * (2) cp >= 0 and cp <= 0x10ffff.  This check does not
39974 			 * implement the steps exactly but the outcome should be
39975 			 * the same.
39976 			 */
39977 			duk_int32_t i32 = 0;
39978 			if (!duk_is_whole_get_int32(duk_to_number(thr, i), &i32) ||
39979 			    i32 < 0 || i32 > 0x10ffffL) {
39980 				DUK_DCERROR_RANGE_INVALID_ARGS(thr);
39981 			}
39982 			DUK_ASSERT(i32 >= 0 && i32 <= 0x10ffffL);
39983 			cp = (duk_ucodepoint_t) i32;
39984 			DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
39985 		} else {
39986 #if defined(DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT)
39987 			/* ToUint16() coercion is mandatory in the E5.1 specification, but
39988 			 * this non-compliant behavior makes more sense because we support
39989 			 * non-BMP codepoints.  Don't use CESU-8 because that'd create
39990 			 * surrogate pairs.
39991 			 */
39992 			cp = (duk_ucodepoint_t) duk_to_uint32(thr, i);
39993 			DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
39994 #else
39995 			cp = (duk_ucodepoint_t) duk_to_uint16(thr, i);
39996 			DUK_ASSERT(cp >= 0 && cp <= 0x10ffffL);
39997 			DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
39998 #endif
39999 		}
40000 	}
40001 
40002 	DUK_BW_COMPACT(thr, bw);
40003 	(void) duk_buffer_to_string(thr, -1);  /* Safe, extended UTF-8 or CESU-8 encoded. */
40004 	return 1;
40005 }
40006 
40007 DUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_char_code(duk_hthread *thr) {
40008 	return duk__construct_from_codepoints(thr, 0 /*nonbmp*/);
40009 }
40010 
40011 #if defined(DUK_USE_ES6)
40012 DUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_code_point(duk_hthread *thr) {
40013 	return duk__construct_from_codepoints(thr, 1 /*nonbmp*/);
40014 }
40015 #endif
40016 
40017 /*
40018  *  toString(), valueOf()
40019  */
40020 
40021 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_to_string(duk_hthread *thr) {
40022 	duk_tval *tv;
40023 
40024 	duk_push_this(thr);
40025 	tv = duk_require_tval(thr, -1);
40026 	DUK_ASSERT(tv != NULL);
40027 
40028 	if (DUK_TVAL_IS_STRING(tv)) {
40029 		/* return as is */
40030 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
40031 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
40032 		DUK_ASSERT(h != NULL);
40033 
40034 		/* Must be a "string object", i.e. class "String" */
40035 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_STRING) {
40036 			goto type_error;
40037 		}
40038 
40039 		duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
40040 		DUK_ASSERT(duk_is_string(thr, -1));
40041 	} else {
40042 		goto type_error;
40043 	}
40044 
40045 	(void) duk_require_hstring_notsymbol(thr, -1);  /* Reject symbols (and wrapped symbols). */
40046 	return 1;
40047 
40048  type_error:
40049 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
40050 }
40051 
40052 /*
40053  *  Character and charcode access
40054  */
40055 
40056 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_at(duk_hthread *thr) {
40057 	duk_hstring *h;
40058 	duk_int_t pos;
40059 
40060 	/* XXX: faster implementation */
40061 
40062 	h = duk_push_this_coercible_to_string(thr);
40063 	DUK_ASSERT(h != NULL);
40064 
40065 	pos = duk_to_int(thr, 0);
40066 
40067 	if (sizeof(duk_size_t) >= sizeof(duk_uint_t)) {
40068 		/* Cast to duk_size_t works in this case:
40069 		 * - If pos < 0, (duk_size_t) pos will always be
40070 		 *   >= max_charlen, and result will be the empty string
40071 		 *   (see duk_substring()).
40072 		 * - If pos >= 0, pos + 1 cannot wrap.
40073 		 */
40074 		DUK_ASSERT((duk_size_t) DUK_INT_MIN >= DUK_HSTRING_MAX_BYTELEN);
40075 		DUK_ASSERT((duk_size_t) DUK_INT_MAX + 1U > (duk_size_t) DUK_INT_MAX);
40076 		duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) pos + 1U);
40077 	} else {
40078 		/* If size_t is smaller than int, explicit bounds checks
40079 		 * are needed because an int may wrap multiple times.
40080 		 */
40081 		if (DUK_UNLIKELY(pos < 0 || (duk_uint_t) pos >= (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h))) {
40082 			duk_push_hstring_empty(thr);
40083 		} else {
40084 			duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) pos + 1U);
40085 		}
40086 	}
40087 
40088 	return 1;
40089 }
40090 
40091 /* Magic: 0=charCodeAt, 1=codePointAt */
40092 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_code_at(duk_hthread *thr) {
40093 	duk_int_t pos;
40094 	duk_hstring *h;
40095 	duk_bool_t clamped;
40096 	duk_uint32_t cp;
40097 	duk_int_t magic;
40098 
40099 	/* XXX: faster implementation */
40100 
40101 	DUK_DDD(DUK_DDDPRINT("arg=%!T", (duk_tval *) duk_get_tval(thr, 0)));
40102 
40103 	h = duk_push_this_coercible_to_string(thr);
40104 	DUK_ASSERT(h != NULL);
40105 
40106 	pos = duk_to_int_clamped_raw(thr,
40107 	                             0 /*index*/,
40108 	                             0 /*min(incl)*/,
40109 	                             (duk_int_t) DUK_HSTRING_GET_CHARLEN(h) - 1 /*max(incl)*/,
40110 	                             &clamped /*out_clamped*/);
40111 #if defined(DUK_USE_ES6)
40112 	magic = duk_get_current_magic(thr);
40113 #else
40114 	DUK_ASSERT(duk_get_current_magic(thr) == 0);
40115 	magic = 0;
40116 #endif
40117 	if (clamped) {
40118 		/* For out-of-bounds indices .charCodeAt() returns NaN and
40119 		 * .codePointAt() returns undefined.
40120 		 */
40121 		if (magic != 0) {
40122 			return 0;
40123 		}
40124 		duk_push_nan(thr);
40125 	} else {
40126 		DUK_ASSERT(pos >= 0);
40127 		cp = (duk_uint32_t) duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) pos, (duk_bool_t) magic /*surrogate_aware*/);
40128 		duk_push_u32(thr, cp);
40129 	}
40130 	return 1;
40131 }
40132 
40133 /*
40134  *  substring(), substr(), slice()
40135  */
40136 
40137 /* XXX: any chance of merging these three similar but still slightly
40138  * different algorithms so that footprint would be reduced?
40139  */
40140 
40141 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substring(duk_hthread *thr) {
40142 	duk_hstring *h;
40143 	duk_int_t start_pos, end_pos;
40144 	duk_int_t len;
40145 
40146 	h = duk_push_this_coercible_to_string(thr);
40147 	DUK_ASSERT(h != NULL);
40148 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
40149 
40150 	/* [ start end str ] */
40151 
40152 	start_pos = duk_to_int_clamped(thr, 0, 0, len);
40153 	if (duk_is_undefined(thr, 1)) {
40154 		end_pos = len;
40155 	} else {
40156 		end_pos = duk_to_int_clamped(thr, 1, 0, len);
40157 	}
40158 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
40159 	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
40160 
40161 	if (start_pos > end_pos) {
40162 		duk_int_t tmp = start_pos;
40163 		start_pos = end_pos;
40164 		end_pos = tmp;
40165 	}
40166 
40167 	DUK_ASSERT(end_pos >= start_pos);
40168 
40169 	duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
40170 	return 1;
40171 }
40172 
40173 #if defined(DUK_USE_SECTION_B)
40174 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substr(duk_hthread *thr) {
40175 	duk_hstring *h;
40176 	duk_int_t start_pos, end_pos;
40177 	duk_int_t len;
40178 
40179 	/* Unlike non-obsolete String calls, substr() algorithm in E5.1
40180 	 * specification will happily coerce undefined and null to strings
40181 	 * ("undefined" and "null").
40182 	 */
40183 	duk_push_this(thr);
40184 	h = duk_to_hstring_m1(thr);  /* Reject Symbols. */
40185 	DUK_ASSERT(h != NULL);
40186 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
40187 
40188 	/* [ start length str ] */
40189 
40190 	/* The implementation for computing of start_pos and end_pos differs
40191 	 * from the standard algorithm, but is intended to result in the exactly
40192 	 * same behavior.  This is not always obvious.
40193 	 */
40194 
40195 	/* combines steps 2 and 5; -len ensures max() not needed for step 5 */
40196 	start_pos = duk_to_int_clamped(thr, 0, -len, len);
40197 	if (start_pos < 0) {
40198 		start_pos = len + start_pos;
40199 	}
40200 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
40201 
40202 	/* combines steps 3, 6; step 7 is not needed */
40203 	if (duk_is_undefined(thr, 1)) {
40204 		end_pos = len;
40205 	} else {
40206 		DUK_ASSERT(start_pos <= len);
40207 		end_pos = start_pos + duk_to_int_clamped(thr, 1, 0, len - start_pos);
40208 	}
40209 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
40210 	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
40211 	DUK_ASSERT(end_pos >= start_pos);
40212 
40213 	duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
40214 	return 1;
40215 }
40216 #endif  /* DUK_USE_SECTION_B */
40217 
40218 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_slice(duk_hthread *thr) {
40219 	duk_hstring *h;
40220 	duk_int_t start_pos, end_pos;
40221 	duk_int_t len;
40222 
40223 	h = duk_push_this_coercible_to_string(thr);
40224 	DUK_ASSERT(h != NULL);
40225 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
40226 
40227 	/* [ start end str ] */
40228 
40229 	start_pos = duk_to_int_clamped(thr, 0, -len, len);
40230 	if (start_pos < 0) {
40231 		start_pos = len + start_pos;
40232 	}
40233 	if (duk_is_undefined(thr, 1)) {
40234 		end_pos = len;
40235 	} else {
40236 		end_pos = duk_to_int_clamped(thr, 1, -len, len);
40237 		if (end_pos < 0) {
40238 			end_pos = len + end_pos;
40239 		}
40240 	}
40241 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
40242 	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
40243 
40244 	if (end_pos < start_pos) {
40245 		end_pos = start_pos;
40246 	}
40247 
40248 	DUK_ASSERT(end_pos >= start_pos);
40249 
40250 	duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
40251 	return 1;
40252 }
40253 
40254 /*
40255  *  Case conversion
40256  */
40257 
40258 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_hthread *thr) {
40259 	duk_small_int_t uppercase = duk_get_current_magic(thr);
40260 
40261 	(void) duk_push_this_coercible_to_string(thr);
40262 	duk_unicode_case_convert_string(thr, (duk_bool_t) uppercase);
40263 	return 1;
40264 }
40265 
40266 /*
40267  *  indexOf() and lastIndexOf()
40268  */
40269 
40270 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_hthread *thr) {
40271 	duk_hstring *h_this;
40272 	duk_hstring *h_search;
40273 	duk_int_t clen_this;
40274 	duk_int_t cpos;
40275 	duk_small_uint_t is_lastindexof = (duk_small_uint_t) duk_get_current_magic(thr);  /* 0=indexOf, 1=lastIndexOf */
40276 
40277 	h_this = duk_push_this_coercible_to_string(thr);
40278 	DUK_ASSERT(h_this != NULL);
40279 	clen_this = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_this);
40280 
40281 	h_search = duk_to_hstring(thr, 0);
40282 	DUK_ASSERT(h_search != NULL);
40283 
40284 	duk_to_number(thr, 1);
40285 	if (duk_is_nan(thr, 1) && is_lastindexof) {
40286 		/* indexOf: NaN should cause pos to be zero.
40287 		 * lastIndexOf: NaN should cause pos to be +Infinity
40288 		 * (and later be clamped to len).
40289 		 */
40290 		cpos = clen_this;
40291 	} else {
40292 		cpos = duk_to_int_clamped(thr, 1, 0, clen_this);
40293 	}
40294 
40295 	cpos = duk__str_search_shared(thr, h_this, h_search, cpos, is_lastindexof /*backwards*/);
40296 	duk_push_int(thr, cpos);
40297 	return 1;
40298 }
40299 
40300 /*
40301  *  replace()
40302  */
40303 
40304 /* XXX: the current implementation works but is quite clunky; it compiles
40305  * to almost 1,4kB of x86 code so it needs to be simplified (better approach,
40306  * shared helpers, etc).  Some ideas for refactoring:
40307  *
40308  * - a primitive to convert a string into a regexp matcher (reduces matching
40309  *   code at the cost of making matching much slower)
40310  * - use replace() as a basic helper for match() and split(), which are both
40311  *   much simpler
40312  * - API call to get_prop and to_boolean
40313  */
40314 
40315 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
40316 	duk_hstring *h_input;
40317 	duk_hstring *h_match;
40318 	duk_hstring *h_search;
40319 	duk_hobject *h_re;
40320 	duk_bufwriter_ctx bw_alloc;
40321 	duk_bufwriter_ctx *bw;
40322 #if defined(DUK_USE_REGEXP_SUPPORT)
40323 	duk_bool_t is_regexp;
40324 	duk_bool_t is_global;
40325 #endif
40326 	duk_bool_t is_repl_func;
40327 	duk_uint32_t match_start_coff, match_start_boff;
40328 #if defined(DUK_USE_REGEXP_SUPPORT)
40329 	duk_int_t match_caps;
40330 #endif
40331 	duk_uint32_t prev_match_end_boff;
40332 	const duk_uint8_t *r_start, *r_end, *r;   /* repl string scan */
40333 	duk_size_t tmp_sz;
40334 
40335 	DUK_ASSERT_TOP(thr, 2);
40336 	h_input = duk_push_this_coercible_to_string(thr);
40337 	DUK_ASSERT(h_input != NULL);
40338 
40339 	bw = &bw_alloc;
40340 	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* input size is good output starting point */
40341 
40342 	DUK_ASSERT_TOP(thr, 4);
40343 
40344 	/* stack[0] = search value
40345 	 * stack[1] = replace value
40346 	 * stack[2] = input string
40347 	 * stack[3] = result buffer
40348 	 */
40349 
40350 	h_re = duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_REGEXP);
40351 	if (h_re) {
40352 #if defined(DUK_USE_REGEXP_SUPPORT)
40353 		is_regexp = 1;
40354 		is_global = duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL);
40355 
40356 		if (is_global) {
40357 			/* start match from beginning */
40358 			duk_push_int(thr, 0);
40359 			duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40360 		}
40361 #else  /* DUK_USE_REGEXP_SUPPORT */
40362 		DUK_DCERROR_UNSUPPORTED(thr);
40363 #endif  /* DUK_USE_REGEXP_SUPPORT */
40364 	} else {
40365 		duk_to_string(thr, 0);  /* rejects symbols */
40366 #if defined(DUK_USE_REGEXP_SUPPORT)
40367 		is_regexp = 0;
40368 		is_global = 0;
40369 #endif
40370 	}
40371 
40372 	if (duk_is_function(thr, 1)) {
40373 		is_repl_func = 1;
40374 		r_start = NULL;
40375 		r_end = NULL;
40376 	} else {
40377 		duk_hstring *h_repl;
40378 
40379 		is_repl_func = 0;
40380 		h_repl = duk_to_hstring(thr, 1);  /* reject symbols */
40381 		DUK_ASSERT(h_repl != NULL);
40382 		r_start = DUK_HSTRING_GET_DATA(h_repl);
40383 		r_end = r_start + DUK_HSTRING_GET_BYTELEN(h_repl);
40384 	}
40385 
40386 	prev_match_end_boff = 0;
40387 
40388 	for (;;) {
40389 		/*
40390 		 *  If matching with a regexp:
40391 		 *    - non-global RegExp: lastIndex not touched on a match, zeroed
40392 		 *      on a non-match
40393 		 *    - global RegExp: on match, lastIndex will be updated by regexp
40394 		 *      executor to point to next char after the matching part (so that
40395 		 *      characters in the matching part are not matched again)
40396 		 *
40397 		 *  If matching with a string:
40398 		 *    - always non-global match, find first occurrence
40399 		 *
40400 		 *  We need:
40401 		 *    - The character offset of start-of-match for the replacer function
40402 		 *    - The byte offsets for start-of-match and end-of-match to implement
40403 		 *      the replacement values $&, $`, and $', and to copy non-matching
40404 		 *      input string portions (including header and trailer) verbatim.
40405 		 *
40406 		 *  NOTE: the E5.1 specification is a bit vague how the RegExp should
40407 		 *  behave in the replacement process; e.g. is matching done first for
40408 		 *  all matches (in the global RegExp case) before any replacer calls
40409 		 *  are made?  See: test-bi-string-proto-replace.js for discussion.
40410 		 */
40411 
40412 		DUK_ASSERT_TOP(thr, 4);
40413 
40414 #if defined(DUK_USE_REGEXP_SUPPORT)
40415 		if (is_regexp) {
40416 			duk_dup_0(thr);
40417 			duk_dup_2(thr);
40418 			duk_regexp_match(thr);  /* [ ... regexp input ] -> [ res_obj ] */
40419 			if (!duk_is_object(thr, -1)) {
40420 				duk_pop(thr);
40421 				break;
40422 			}
40423 
40424 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);
40425 			DUK_ASSERT(duk_is_number(thr, -1));
40426 			match_start_coff = duk_get_uint(thr, -1);
40427 			duk_pop(thr);
40428 
40429 			duk_get_prop_index(thr, -1, 0);
40430 			DUK_ASSERT(duk_is_string(thr, -1));
40431 			h_match = duk_known_hstring(thr, -1);
40432 			duk_pop(thr);  /* h_match is borrowed, remains reachable through match_obj */
40433 
40434 			if (DUK_HSTRING_GET_BYTELEN(h_match) == 0) {
40435 				/* This should be equivalent to match() algorithm step 8.f.iii.2:
40436 				 * detect an empty match and allow it, but don't allow it twice.
40437 				 */
40438 				duk_uint32_t last_index;
40439 
40440 				duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40441 				last_index = (duk_uint32_t) duk_get_uint(thr, -1);
40442 				DUK_DDD(DUK_DDDPRINT("empty match, bump lastIndex: %ld -> %ld",
40443 				                     (long) last_index, (long) (last_index + 1)));
40444 				duk_pop(thr);
40445 				duk_push_uint(thr, (duk_uint_t) (last_index + 1));
40446 				duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40447 			}
40448 
40449 			DUK_ASSERT(duk_get_length(thr, -1) <= DUK_INT_MAX);  /* string limits */
40450 			match_caps = (duk_int_t) duk_get_length(thr, -1);
40451 		} else {
40452 #else  /* DUK_USE_REGEXP_SUPPORT */
40453 		{  /* unconditionally */
40454 #endif  /* DUK_USE_REGEXP_SUPPORT */
40455 			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
40456 			const duk_uint8_t *q_start;               /* match string */
40457 			duk_size_t q_blen;
40458 
40459 #if defined(DUK_USE_REGEXP_SUPPORT)
40460 			DUK_ASSERT(!is_global);  /* single match always */
40461 #endif
40462 
40463 			p_start = DUK_HSTRING_GET_DATA(h_input);
40464 			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
40465 			p = p_start;
40466 
40467 			h_search = duk_known_hstring(thr, 0);
40468 			q_start = DUK_HSTRING_GET_DATA(h_search);
40469 			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search);
40470 
40471 			p_end -= q_blen;  /* ensure full memcmp() fits in while */
40472 
40473 			match_start_coff = 0;
40474 
40475 			while (p <= p_end) {
40476 				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
40477 				if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
40478 					duk_dup_0(thr);
40479 					h_match = duk_known_hstring(thr, -1);
40480 #if defined(DUK_USE_REGEXP_SUPPORT)
40481 					match_caps = 0;
40482 #endif
40483 					goto found;
40484 				}
40485 
40486 				/* track utf-8 non-continuation bytes */
40487 				if ((p[0] & 0xc0) != 0x80) {
40488 					match_start_coff++;
40489 				}
40490 				p++;
40491 			}
40492 
40493 			/* not found */
40494 			break;
40495 		}
40496 	 found:
40497 
40498 		/* stack[0] = search value
40499 		 * stack[1] = replace value
40500 		 * stack[2] = input string
40501 		 * stack[3] = result buffer
40502 		 * stack[4] = regexp match OR match string
40503 		 */
40504 
40505 		match_start_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
40506 
40507 		tmp_sz = (duk_size_t) (match_start_boff - prev_match_end_boff);
40508 		DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
40509 
40510 		prev_match_end_boff = match_start_boff + DUK_HSTRING_GET_BYTELEN(h_match);
40511 
40512 		if (is_repl_func) {
40513 			duk_idx_t idx_args;
40514 			duk_hstring *h_repl;
40515 
40516 			/* regexp res_obj is at index 4 */
40517 
40518 			duk_dup_1(thr);
40519 			idx_args = duk_get_top(thr);
40520 
40521 #if defined(DUK_USE_REGEXP_SUPPORT)
40522 			if (is_regexp) {
40523 				duk_int_t idx;
40524 				duk_require_stack(thr, match_caps + 2);
40525 				for (idx = 0; idx < match_caps; idx++) {
40526 					/* match followed by capture(s) */
40527 					duk_get_prop_index(thr, 4, (duk_uarridx_t) idx);
40528 				}
40529 			} else {
40530 #else  /* DUK_USE_REGEXP_SUPPORT */
40531 			{  /* unconditionally */
40532 #endif  /* DUK_USE_REGEXP_SUPPORT */
40533 				/* match == search string, by definition */
40534 				duk_dup_0(thr);
40535 			}
40536 			duk_push_uint(thr, (duk_uint_t) match_start_coff);
40537 			duk_dup_2(thr);
40538 
40539 			/* [ ... replacer match [captures] match_char_offset input ] */
40540 
40541 			duk_call(thr, duk_get_top(thr) - idx_args);
40542 			h_repl = duk_to_hstring_m1(thr);  /* -> [ ... repl_value ] */
40543 			DUK_ASSERT(h_repl != NULL);
40544 
40545 			DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_repl);
40546 
40547 			duk_pop(thr);  /* repl_value */
40548 		} else {
40549 			r = r_start;
40550 
40551 			while (r < r_end) {
40552 				duk_int_t ch1;
40553 				duk_int_t ch2;
40554 #if defined(DUK_USE_REGEXP_SUPPORT)
40555 				duk_int_t ch3;
40556 #endif
40557 				duk_size_t left;
40558 
40559 				ch1 = *r++;
40560 				if (ch1 != DUK_ASC_DOLLAR) {
40561 					goto repl_write;
40562 				}
40563 				DUK_ASSERT(r <= r_end);
40564 				left = (duk_size_t) (r_end - r);
40565 
40566 				if (left <= 0) {
40567 					goto repl_write;
40568 				}
40569 
40570 				ch2 = r[0];
40571 				switch (ch2) {
40572 				case DUK_ASC_DOLLAR: {
40573 					ch1 = (1 << 8) + DUK_ASC_DOLLAR;
40574 					goto repl_write;
40575 				}
40576 				case DUK_ASC_AMP: {
40577 					DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_match);
40578 					r++;
40579 					continue;
40580 				}
40581 				case DUK_ASC_GRAVE: {
40582 					tmp_sz = (duk_size_t) match_start_boff;
40583 					DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input), tmp_sz);
40584 					r++;
40585 					continue;
40586 				}
40587 				case DUK_ASC_SINGLEQUOTE: {
40588 					duk_uint32_t match_end_boff;
40589 
40590 					/* Use match charlen instead of bytelen, just in case the input and
40591 					 * match codepoint encodings would have different lengths.
40592 					 */
40593 					/* XXX: charlen computed here, and also in char2byte helper. */
40594 					match_end_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr,
40595 					                                                                   h_input,
40596 					                                                                   match_start_coff + (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_match));
40597 
40598 					tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff);
40599 					DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + match_end_boff, tmp_sz);
40600 					r++;
40601 					continue;
40602 				}
40603 				default: {
40604 #if defined(DUK_USE_REGEXP_SUPPORT)
40605 					duk_int_t capnum, captmp, capadv;
40606 					/* XXX: optional check, match_caps is zero if no regexp,
40607 					 * so dollar will be interpreted literally anyway.
40608 					 */
40609 
40610 					if (!is_regexp) {
40611 						goto repl_write;
40612 					}
40613 
40614 					if (!(ch2 >= DUK_ASC_0 && ch2 <= DUK_ASC_9)) {
40615 						goto repl_write;
40616 					}
40617 					capnum = ch2 - DUK_ASC_0;
40618 					capadv = 1;
40619 
40620 					if (left >= 2) {
40621 						ch3 = r[1];
40622 						if (ch3 >= DUK_ASC_0 && ch3 <= DUK_ASC_9) {
40623 							captmp = capnum * 10 + (ch3 - DUK_ASC_0);
40624 							if (captmp < match_caps) {
40625 								capnum = captmp;
40626 								capadv = 2;
40627 							}
40628 						}
40629 					}
40630 
40631 					if (capnum > 0 && capnum < match_caps) {
40632 						DUK_ASSERT(is_regexp != 0);  /* match_caps == 0 without regexps */
40633 
40634 						/* regexp res_obj is at offset 4 */
40635 						duk_get_prop_index(thr, 4, (duk_uarridx_t) capnum);
40636 						if (duk_is_string(thr, -1)) {
40637 							duk_hstring *h_tmp_str;
40638 
40639 							h_tmp_str = duk_known_hstring(thr, -1);
40640 
40641 							DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_tmp_str);
40642 						} else {
40643 							/* undefined -> skip (replaced with empty) */
40644 						}
40645 						duk_pop(thr);
40646 						r += capadv;
40647 						continue;
40648 					} else {
40649 						goto repl_write;
40650 					}
40651 #else  /* DUK_USE_REGEXP_SUPPORT */
40652 					goto repl_write;  /* unconditionally */
40653 #endif  /* DUK_USE_REGEXP_SUPPORT */
40654 				}  /* default case */
40655 				}  /* switch (ch2) */
40656 
40657 			 repl_write:
40658 				/* ch1 = (r_increment << 8) + byte */
40659 
40660 				DUK_BW_WRITE_ENSURE_U8(thr, bw, (duk_uint8_t) (ch1 & 0xff));
40661 				r += ch1 >> 8;
40662 			}  /* while repl */
40663 		}  /* if (is_repl_func) */
40664 
40665 		duk_pop(thr);  /* pop regexp res_obj or match string */
40666 
40667 #if defined(DUK_USE_REGEXP_SUPPORT)
40668 		if (!is_global) {
40669 #else
40670 		{  /* unconditionally; is_global==0 */
40671 #endif
40672 			break;
40673 		}
40674 	}
40675 
40676 	/* trailer */
40677 	tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff);
40678 	DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
40679 
40680 	DUK_ASSERT_TOP(thr, 4);
40681 	DUK_BW_COMPACT(thr, bw);
40682 	(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */
40683 	return 1;
40684 }
40685 
40686 /*
40687  *  split()
40688  */
40689 
40690 /* XXX: very messy now, but works; clean up, remove unused variables (nomimally
40691  * used so compiler doesn't complain).
40692  */
40693 
40694 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {
40695 	duk_hstring *h_input;
40696 	duk_hstring *h_sep;
40697 	duk_uint32_t limit;
40698 	duk_uint32_t arr_idx;
40699 #if defined(DUK_USE_REGEXP_SUPPORT)
40700 	duk_bool_t is_regexp;
40701 #endif
40702 	duk_bool_t matched;  /* set to 1 if any match exists (needed for empty input special case) */
40703 	duk_uint32_t prev_match_end_coff, prev_match_end_boff;
40704 	duk_uint32_t match_start_boff, match_start_coff;
40705 	duk_uint32_t match_end_boff, match_end_coff;
40706 
40707 	h_input = duk_push_this_coercible_to_string(thr);
40708 	DUK_ASSERT(h_input != NULL);
40709 
40710 	duk_push_array(thr);
40711 
40712 	if (duk_is_undefined(thr, 1)) {
40713 		limit = 0xffffffffUL;
40714 	} else {
40715 		limit = duk_to_uint32(thr, 1);
40716 	}
40717 
40718 	if (limit == 0) {
40719 		return 1;
40720 	}
40721 
40722 	/* If the separator is a RegExp, make a "clone" of it.  The specification
40723 	 * algorithm calls [[Match]] directly for specific indices; we emulate this
40724 	 * by tweaking lastIndex and using a "force global" variant of duk_regexp_match()
40725 	 * which will use global-style matching even when the RegExp itself is non-global.
40726 	 */
40727 
40728 	if (duk_is_undefined(thr, 0)) {
40729 		/* The spec algorithm first does "R = ToString(separator)" before checking
40730 		 * whether separator is undefined.  Since this is side effect free, we can
40731 		 * skip the ToString() here.
40732 		 */
40733 		duk_dup_2(thr);
40734 		duk_put_prop_index(thr, 3, 0);
40735 		return 1;
40736 	} else if (duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_REGEXP) != NULL) {
40737 #if defined(DUK_USE_REGEXP_SUPPORT)
40738 		duk_push_hobject_bidx(thr, DUK_BIDX_REGEXP_CONSTRUCTOR);
40739 		duk_dup_0(thr);
40740 		duk_new(thr, 1);  /* [ ... RegExp val ] -> [ ... res ] */
40741 		duk_replace(thr, 0);
40742 		/* lastIndex is initialized to zero by new RegExp() */
40743 		is_regexp = 1;
40744 #else
40745 		DUK_DCERROR_UNSUPPORTED(thr);
40746 #endif
40747 	} else {
40748 		duk_to_string(thr, 0);
40749 #if defined(DUK_USE_REGEXP_SUPPORT)
40750 		is_regexp = 0;
40751 #endif
40752 	}
40753 
40754 	/* stack[0] = separator (string or regexp)
40755 	 * stack[1] = limit
40756 	 * stack[2] = input string
40757 	 * stack[3] = result array
40758 	 */
40759 
40760 	prev_match_end_boff = 0;
40761 	prev_match_end_coff = 0;
40762 	arr_idx = 0;
40763 	matched = 0;
40764 
40765 	for (;;) {
40766 		/*
40767 		 *  The specification uses RegExp [[Match]] to attempt match at specific
40768 		 *  offsets.  We don't have such a primitive, so we use an actual RegExp
40769 		 *  and tweak lastIndex.  Since the RegExp may be non-global, we use a
40770 		 *  special variant which forces global-like behavior for matching.
40771 		 */
40772 
40773 		DUK_ASSERT_TOP(thr, 4);
40774 
40775 #if defined(DUK_USE_REGEXP_SUPPORT)
40776 		if (is_regexp) {
40777 			duk_dup_0(thr);
40778 			duk_dup_2(thr);
40779 			duk_regexp_match_force_global(thr);  /* [ ... regexp input ] -> [ res_obj ] */
40780 			if (!duk_is_object(thr, -1)) {
40781 				duk_pop(thr);
40782 				break;
40783 			}
40784 			matched = 1;
40785 
40786 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);
40787 			DUK_ASSERT(duk_is_number(thr, -1));
40788 			match_start_coff = duk_get_uint(thr, -1);
40789 			match_start_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
40790 			duk_pop(thr);
40791 
40792 			if (match_start_coff == DUK_HSTRING_GET_CHARLEN(h_input)) {
40793 				/* don't allow an empty match at the end of the string */
40794 				duk_pop(thr);
40795 				break;
40796 			}
40797 
40798 			duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40799 			DUK_ASSERT(duk_is_number(thr, -1));
40800 			match_end_coff = duk_get_uint(thr, -1);
40801 			match_end_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_end_coff);
40802 			duk_pop(thr);
40803 
40804 			/* empty match -> bump and continue */
40805 			if (prev_match_end_boff == match_end_boff) {
40806 				duk_push_uint(thr, (duk_uint_t) (match_end_coff + 1));
40807 				duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40808 				duk_pop(thr);
40809 				continue;
40810 			}
40811 		} else {
40812 #else  /* DUK_USE_REGEXP_SUPPORT */
40813 		{  /* unconditionally */
40814 #endif  /* DUK_USE_REGEXP_SUPPORT */
40815 			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
40816 			const duk_uint8_t *q_start;               /* match string */
40817 			duk_size_t q_blen, q_clen;
40818 
40819 			p_start = DUK_HSTRING_GET_DATA(h_input);
40820 			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
40821 			p = p_start + prev_match_end_boff;
40822 
40823 			h_sep = duk_known_hstring(thr, 0);  /* symbol already rejected above */
40824 			q_start = DUK_HSTRING_GET_DATA(h_sep);
40825 			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sep);
40826 			q_clen = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_sep);
40827 
40828 			p_end -= q_blen;  /* ensure full memcmp() fits in while */
40829 
40830 			match_start_coff = prev_match_end_coff;
40831 
40832 			if (q_blen == 0) {
40833 				/* Handle empty separator case: it will always match, and always
40834 				 * triggers the check in step 13.c.iii initially.  Note that we
40835 				 * must skip to either end of string or start of first codepoint,
40836 				 * skipping over any continuation bytes!
40837 				 *
40838 				 * Don't allow an empty string to match at the end of the input.
40839 				 */
40840 
40841 				matched = 1;  /* empty separator can always match */
40842 
40843 				match_start_coff++;
40844 				p++;
40845 				while (p < p_end) {
40846 					if ((p[0] & 0xc0) != 0x80) {
40847 						goto found;
40848 					}
40849 					p++;
40850 				}
40851 				goto not_found;
40852 			}
40853 
40854 			DUK_ASSERT(q_blen > 0 && q_clen > 0);
40855 			while (p <= p_end) {
40856 				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
40857 				DUK_ASSERT(q_blen > 0);  /* no issues with empty memcmp() */
40858 				if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
40859 					/* never an empty match, so step 13.c.iii can't be triggered */
40860 					goto found;
40861 				}
40862 
40863 				/* track utf-8 non-continuation bytes */
40864 				if ((p[0] & 0xc0) != 0x80) {
40865 					match_start_coff++;
40866 				}
40867 				p++;
40868 			}
40869 
40870 		 not_found:
40871 			/* not found */
40872 			break;
40873 
40874 		 found:
40875 			matched = 1;
40876 			match_start_boff = (duk_uint32_t) (p - p_start);
40877 			match_end_coff = (duk_uint32_t) (match_start_coff + q_clen);  /* constrained by string length */
40878 			match_end_boff = (duk_uint32_t) (match_start_boff + q_blen);  /* ditto */
40879 
40880 			/* empty match (may happen with empty separator) -> bump and continue */
40881 			if (prev_match_end_boff == match_end_boff) {
40882 				prev_match_end_boff++;
40883 				prev_match_end_coff++;
40884 				continue;
40885 			}
40886 		}  /* if (is_regexp) */
40887 
40888 		/* stack[0] = separator (string or regexp)
40889 		 * stack[1] = limit
40890 		 * stack[2] = input string
40891 		 * stack[3] = result array
40892 		 * stack[4] = regexp res_obj (if is_regexp)
40893 		 */
40894 
40895 		DUK_DDD(DUK_DDDPRINT("split; match_start b=%ld,c=%ld, match_end b=%ld,c=%ld, prev_end b=%ld,c=%ld",
40896 		                     (long) match_start_boff, (long) match_start_coff,
40897 		                     (long) match_end_boff, (long) match_end_coff,
40898 		                     (long) prev_match_end_boff, (long) prev_match_end_coff));
40899 
40900 		duk_push_lstring(thr,
40901 		                 (const char *) (DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff),
40902 		                 (duk_size_t) (match_start_boff - prev_match_end_boff));
40903 		duk_put_prop_index(thr, 3, arr_idx);
40904 		arr_idx++;
40905 		if (arr_idx >= limit) {
40906 			goto hit_limit;
40907 		}
40908 
40909 #if defined(DUK_USE_REGEXP_SUPPORT)
40910 		if (is_regexp) {
40911 			duk_size_t i, len;
40912 
40913 			len = duk_get_length(thr, 4);
40914 			for (i = 1; i < len; i++) {
40915 				DUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* cannot have >4G captures */
40916 				duk_get_prop_index(thr, 4, (duk_uarridx_t) i);
40917 				duk_put_prop_index(thr, 3, arr_idx);
40918 				arr_idx++;
40919 				if (arr_idx >= limit) {
40920 					goto hit_limit;
40921 				}
40922 			}
40923 
40924 			duk_pop(thr);
40925 			/* lastIndex already set up for next match */
40926 		} else {
40927 #else  /* DUK_USE_REGEXP_SUPPORT */
40928 		{  /* unconditionally */
40929 #endif  /* DUK_USE_REGEXP_SUPPORT */
40930 			/* no action */
40931 		}
40932 
40933 		prev_match_end_boff = match_end_boff;
40934 		prev_match_end_coff = match_end_coff;
40935 		continue;
40936 	}  /* for */
40937 
40938 	/* Combined step 11 (empty string special case) and 14-15. */
40939 
40940 	DUK_DDD(DUK_DDDPRINT("split trailer; prev_end b=%ld,c=%ld",
40941 	                     (long) prev_match_end_boff, (long) prev_match_end_coff));
40942 
40943 	if (DUK_HSTRING_GET_BYTELEN(h_input) > 0 || !matched) {
40944 		/* Add trailer if:
40945 		 *   a) non-empty input
40946 		 *   b) empty input and no (zero size) match found (step 11)
40947 		 */
40948 
40949 		duk_push_lstring(thr,
40950 		                 (const char *) DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff,
40951 		                 (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff));
40952 		duk_put_prop_index(thr, 3, arr_idx);
40953 		/* No arr_idx update or limit check */
40954 	}
40955 
40956 	return 1;
40957 
40958  hit_limit:
40959 #if defined(DUK_USE_REGEXP_SUPPORT)
40960 	if (is_regexp) {
40961 		duk_pop(thr);
40962 	}
40963 #endif
40964 
40965 	return 1;
40966 }
40967 
40968 /*
40969  *  Various
40970  */
40971 
40972 #if defined(DUK_USE_REGEXP_SUPPORT)
40973 DUK_LOCAL void duk__to_regexp_helper(duk_hthread *thr, duk_idx_t idx, duk_bool_t force_new) {
40974 	duk_hobject *h;
40975 
40976 	/* Shared helper for match() steps 3-4, search() steps 3-4. */
40977 
40978 	DUK_ASSERT(idx >= 0);
40979 
40980 	if (force_new) {
40981 		goto do_new;
40982 	}
40983 
40984 	h = duk_get_hobject_with_class(thr, idx, DUK_HOBJECT_CLASS_REGEXP);
40985 	if (!h) {
40986 		goto do_new;
40987 	}
40988 	return;
40989 
40990  do_new:
40991 	duk_push_hobject_bidx(thr, DUK_BIDX_REGEXP_CONSTRUCTOR);
40992 	duk_dup(thr, idx);
40993 	duk_new(thr, 1);  /* [ ... RegExp val ] -> [ ... res ] */
40994 	duk_replace(thr, idx);
40995 }
40996 #endif  /* DUK_USE_REGEXP_SUPPORT */
40997 
40998 #if defined(DUK_USE_REGEXP_SUPPORT)
40999 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_search(duk_hthread *thr) {
41000 	/* Easiest way to implement the search required by the specification
41001 	 * is to do a RegExp test() with lastIndex forced to zero.  To avoid
41002 	 * side effects on the argument, "clone" the RegExp if a RegExp was
41003 	 * given as input.
41004 	 *
41005 	 * The global flag of the RegExp should be ignored; setting lastIndex
41006 	 * to zero (which happens when "cloning" the RegExp) should have an
41007 	 * equivalent effect.
41008 	 */
41009 
41010 	DUK_ASSERT_TOP(thr, 1);
41011 	(void) duk_push_this_coercible_to_string(thr);  /* at index 1 */
41012 	duk__to_regexp_helper(thr, 0 /*index*/, 1 /*force_new*/);
41013 
41014 	/* stack[0] = regexp
41015 	 * stack[1] = string
41016 	 */
41017 
41018 	/* Avoid using RegExp.prototype methods, as they're writable and
41019 	 * configurable and may have been changed.
41020 	 */
41021 
41022 	duk_dup_0(thr);
41023 	duk_dup_1(thr);  /* [ ... re_obj input ] */
41024 	duk_regexp_match(thr);  /* -> [ ... res_obj ] */
41025 
41026 	if (!duk_is_object(thr, -1)) {
41027 		duk_push_int(thr, -1);
41028 		return 1;
41029 	}
41030 
41031 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);
41032 	DUK_ASSERT(duk_is_number(thr, -1));
41033 	return 1;
41034 }
41035 #endif  /* DUK_USE_REGEXP_SUPPORT */
41036 
41037 #if defined(DUK_USE_REGEXP_SUPPORT)
41038 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_match(duk_hthread *thr) {
41039 	duk_bool_t global;
41040 	duk_int_t prev_last_index;
41041 	duk_int_t this_index;
41042 	duk_int_t arr_idx;
41043 
41044 	DUK_ASSERT_TOP(thr, 1);
41045 	(void) duk_push_this_coercible_to_string(thr);
41046 	duk__to_regexp_helper(thr, 0 /*index*/, 0 /*force_new*/);
41047 	global = duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL);
41048 	DUK_ASSERT_TOP(thr, 2);
41049 
41050 	/* stack[0] = regexp
41051 	 * stack[1] = string
41052 	 */
41053 
41054 	if (!global) {
41055 		duk_regexp_match(thr);  /* -> [ res_obj ] */
41056 		return 1;  /* return 'res_obj' */
41057 	}
41058 
41059 	/* Global case is more complex. */
41060 
41061 	/* [ regexp string ] */
41062 
41063 	duk_push_int(thr, 0);
41064 	duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
41065 	duk_push_array(thr);
41066 
41067 	/* [ regexp string res_arr ] */
41068 
41069 	prev_last_index = 0;
41070 	arr_idx = 0;
41071 
41072 	for (;;) {
41073 		DUK_ASSERT_TOP(thr, 3);
41074 
41075 		duk_dup_0(thr);
41076 		duk_dup_1(thr);
41077 		duk_regexp_match(thr);  /* -> [ ... regexp string ] -> [ ... res_obj ] */
41078 
41079 		if (!duk_is_object(thr, -1)) {
41080 			duk_pop(thr);
41081 			break;
41082 		}
41083 
41084 		duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
41085 		DUK_ASSERT(duk_is_number(thr, -1));
41086 		this_index = duk_get_int(thr, -1);
41087 		duk_pop(thr);
41088 
41089 		if (this_index == prev_last_index) {
41090 			this_index++;
41091 			duk_push_int(thr, this_index);
41092 			duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
41093 		}
41094 		prev_last_index = this_index;
41095 
41096 		duk_get_prop_index(thr, -1, 0);  /* match string */
41097 		duk_put_prop_index(thr, 2, (duk_uarridx_t) arr_idx);
41098 		arr_idx++;
41099 		duk_pop(thr);  /* res_obj */
41100 	}
41101 
41102 	if (arr_idx == 0) {
41103 		duk_push_null(thr);
41104 	}
41105 
41106 	return 1;  /* return 'res_arr' or 'null' */
41107 }
41108 #endif  /* DUK_USE_REGEXP_SUPPORT */
41109 
41110 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_concat(duk_hthread *thr) {
41111 	/* duk_concat() coerces arguments with ToString() in correct order */
41112 	(void) duk_push_this_coercible_to_string(thr);
41113 	duk_insert(thr, 0);  /* this is relatively expensive */
41114 	duk_concat(thr, duk_get_top(thr));
41115 	return 1;
41116 }
41117 
41118 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_trim(duk_hthread *thr) {
41119 	DUK_ASSERT_TOP(thr, 0);
41120 	(void) duk_push_this_coercible_to_string(thr);
41121 	duk_trim(thr, 0);
41122 	DUK_ASSERT_TOP(thr, 1);
41123 	return 1;
41124 }
41125 
41126 #if defined(DUK_USE_ES6)
41127 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_repeat(duk_hthread *thr) {
41128 	duk_hstring *h_input;
41129 	duk_size_t input_blen;
41130 	duk_size_t result_len;
41131 	duk_int_t count_signed;
41132 	duk_uint_t count;
41133 	const duk_uint8_t *src;
41134 	duk_uint8_t *buf;
41135 	duk_uint8_t *p;
41136 	duk_double_t d;
41137 #if !defined(DUK_USE_PREFER_SIZE)
41138 	duk_size_t copy_size;
41139 	duk_uint8_t *p_end;
41140 #endif
41141 
41142 	DUK_ASSERT_TOP(thr, 1);
41143 	h_input = duk_push_this_coercible_to_string(thr);
41144 	DUK_ASSERT(h_input != NULL);
41145 	input_blen = DUK_HSTRING_GET_BYTELEN(h_input);
41146 
41147 	/* Count is ToNumber() coerced; +Infinity must be always rejected
41148 	 * (even if input string is zero length), as well as negative values
41149 	 * and -Infinity.  -Infinity doesn't require an explicit check
41150 	 * because duk_get_int() clamps it to DUK_INT_MIN which gets rejected
41151 	 * as a negative value (regardless of input string length).
41152 	 */
41153 	d = duk_to_number(thr, 0);
41154 	if (duk_double_is_posinf(d)) {
41155 		goto fail_range;
41156 	}
41157 	count_signed = duk_get_int(thr, 0);
41158 	if (count_signed < 0) {
41159 		goto fail_range;
41160 	}
41161 	count = (duk_uint_t) count_signed;
41162 
41163 	/* Overflow check for result length. */
41164 	result_len = count * input_blen;
41165 	if (count != 0 && result_len / count != input_blen) {
41166 		goto fail_range;
41167 	}
41168 
41169 	/* Temporary fixed buffer, later converted to string. */
41170 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, result_len);
41171 	DUK_ASSERT(buf != NULL);
41172 	src = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
41173 	DUK_ASSERT(src != NULL);
41174 
41175 #if defined(DUK_USE_PREFER_SIZE)
41176 	p = buf;
41177 	while (count-- > 0) {
41178 		duk_memcpy((void *) p, (const void *) src, input_blen);  /* copy size may be zero, but pointers are valid */
41179 		p += input_blen;
41180 	}
41181 #else  /* DUK_USE_PREFER_SIZE */
41182 	/* Take advantage of already copied pieces to speed up the process
41183 	 * especially for small repeated strings.
41184 	 */
41185 	p = buf;
41186 	p_end = p + result_len;
41187 	copy_size = input_blen;
41188 	for (;;) {
41189 		duk_size_t remain = (duk_size_t) (p_end - p);
41190 		DUK_DDD(DUK_DDDPRINT("remain=%ld, copy_size=%ld, input_blen=%ld, result_len=%ld",
41191 		                     (long) remain, (long) copy_size, (long) input_blen,
41192 		                     (long) result_len));
41193 		if (remain <= copy_size) {
41194 			/* If result_len is zero, this case is taken and does
41195 			 * a zero size copy (with valid pointers).
41196 			 */
41197 			duk_memcpy((void *) p, (const void *) src, remain);
41198 			break;
41199 		} else {
41200 			duk_memcpy((void *) p, (const void *) src, copy_size);
41201 			p += copy_size;
41202 		}
41203 
41204 		src = (const duk_uint8_t *) buf;  /* Use buf as source for larger copies. */
41205 		copy_size = (duk_size_t) (p - buf);
41206 	}
41207 #endif  /* DUK_USE_PREFER_SIZE */
41208 
41209 	/* XXX: It would be useful to be able to create a duk_hstring with
41210 	 * a certain byte size whose data area wasn't initialized and which
41211 	 * wasn't in the string table yet.  This would allow a string to be
41212 	 * constructed directly without a buffer temporary and when it was
41213 	 * finished, it could be injected into the string table.  Currently
41214 	 * this isn't possible because duk_hstrings are only tracked by the
41215 	 * intern table (they are not in heap_allocated).
41216 	 */
41217 
41218 	duk_buffer_to_string(thr, -1);  /* Safe if input is safe. */
41219 	return 1;
41220 
41221  fail_range:
41222 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
41223 }
41224 #endif  /* DUK_USE_ES6 */
41225 
41226 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_locale_compare(duk_hthread *thr) {
41227 	duk_hstring *h1;
41228 	duk_hstring *h2;
41229 	duk_size_t h1_len, h2_len, prefix_len;
41230 	duk_small_int_t ret = 0;
41231 	duk_small_int_t rc;
41232 
41233 	/* The current implementation of localeCompare() is simply a codepoint
41234 	 * by codepoint comparison, implemented with a simple string compare
41235 	 * because UTF-8 should preserve codepoint ordering (assuming valid
41236 	 * shortest UTF-8 encoding).
41237 	 *
41238 	 * The specification requires that the return value must be related
41239 	 * to the sort order: e.g. negative means that 'this' comes before
41240 	 * 'that' in sort order.  We assume an ascending sort order.
41241 	 */
41242 
41243 	/* XXX: could share code with duk_js_ops.c, duk_js_compare_helper */
41244 
41245 	h1 = duk_push_this_coercible_to_string(thr);
41246 	DUK_ASSERT(h1 != NULL);
41247 
41248 	h2 = duk_to_hstring(thr, 0);
41249 	DUK_ASSERT(h2 != NULL);
41250 
41251 	h1_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
41252 	h2_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
41253 	prefix_len = (h1_len <= h2_len ? h1_len : h2_len);
41254 
41255 	rc = (duk_small_int_t) duk_memcmp((const void *) DUK_HSTRING_GET_DATA(h1),
41256 	                                  (const void *) DUK_HSTRING_GET_DATA(h2),
41257 	                                  (size_t) prefix_len);
41258 
41259 	if (rc < 0) {
41260 		ret = -1;
41261 		goto done;
41262 	} else if (rc > 0) {
41263 		ret = 1;
41264 		goto done;
41265 	}
41266 
41267 	/* prefix matches, lengths matter now */
41268 	if (h1_len > h2_len) {
41269 		ret = 1;
41270 		goto done;
41271 	} else if (h1_len == h2_len) {
41272 		DUK_ASSERT(ret == 0);
41273 		goto done;
41274 	}
41275 	ret = -1;
41276 	goto done;
41277 
41278  done:
41279 	duk_push_int(thr, (duk_int_t) ret);
41280 	return 1;
41281 }
41282 
41283 #if defined(DUK_USE_ES6)
41284 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_hthread *thr) {
41285 	duk_int_t magic;
41286 	duk_hstring *h;
41287 	duk_hstring *h_search;
41288 	duk_size_t blen_search;
41289 	const duk_uint8_t *p_cmp_start;
41290 	duk_bool_t result;
41291 
41292 	h = duk_push_this_coercible_to_string(thr);
41293 	DUK_ASSERT(h != NULL);
41294 
41295 	h_search = duk__str_tostring_notregexp(thr, 0);
41296 	DUK_ASSERT(h_search != NULL);
41297 
41298 	magic = duk_get_current_magic(thr);
41299 
41300 	p_cmp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
41301 	blen_search = DUK_HSTRING_GET_BYTELEN(h_search);
41302 
41303 	if (duk_is_undefined(thr, 1)) {
41304 		if (magic) {
41305 			p_cmp_start = p_cmp_start + DUK_HSTRING_GET_BYTELEN(h) - blen_search;
41306 		} else {
41307 			/* p_cmp_start already OK */
41308 		}
41309 	} else {
41310 		duk_int_t len;
41311 		duk_int_t pos;
41312 
41313 		DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= DUK_INT_MAX);
41314 		len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
41315 		pos = duk_to_int_clamped(thr, 1, 0, len);
41316 		DUK_ASSERT(pos >= 0 && pos <= len);
41317 
41318 		if (magic) {
41319 			p_cmp_start -= blen_search;  /* Conceptually subtracted last, but do already here. */
41320 		}
41321 		DUK_ASSERT(pos >= 0 && pos <= len);
41322 
41323 		p_cmp_start += duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) pos);
41324 	}
41325 
41326 	/* The main comparison can be done using a memcmp() rather than
41327 	 * doing codepoint comparisons: for CESU-8 strings there is a
41328 	 * canonical representation for every codepoint.  But we do need
41329 	 * to deal with the char/byte offset translation to find the
41330 	 * comparison range.
41331 	 */
41332 
41333 	result = 0;
41334 	if (p_cmp_start >= DUK_HSTRING_GET_DATA(h) &&
41335 	    (duk_size_t) (p_cmp_start - (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h)) + blen_search <= DUK_HSTRING_GET_BYTELEN(h)) {
41336 		if (duk_memcmp((const void *) p_cmp_start,
41337 		               (const void *) DUK_HSTRING_GET_DATA(h_search),
41338 		               (size_t) blen_search) == 0) {
41339 			result = 1;
41340 		}
41341 	}
41342 
41343 	duk_push_boolean(thr, result);
41344 	return 1;
41345 }
41346 #endif  /* DUK_USE_ES6 */
41347 
41348 #if defined(DUK_USE_ES6)
41349 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_includes(duk_hthread *thr) {
41350 	duk_hstring *h;
41351 	duk_hstring *h_search;
41352 	duk_int_t len;
41353 	duk_int_t pos;
41354 
41355 	h = duk_push_this_coercible_to_string(thr);
41356 	DUK_ASSERT(h != NULL);
41357 
41358 	h_search = duk__str_tostring_notregexp(thr, 0);
41359 	DUK_ASSERT(h_search != NULL);
41360 
41361 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
41362 	pos = duk_to_int_clamped(thr, 1, 0, len);
41363 	DUK_ASSERT(pos >= 0 && pos <= len);
41364 
41365 	pos = duk__str_search_shared(thr, h, h_search, pos, 0 /*backwards*/);
41366 	duk_push_boolean(thr, pos >= 0);
41367 	return 1;
41368 }
41369 #endif  /* DUK_USE_ES6 */
41370 #endif  /* DUK_USE_STRING_BUILTIN */
41371 /*
41372  *  Symbol built-in
41373  */
41374 
41375 /* #include duk_internal.h -> already included */
41376 
41377 #if defined(DUK_USE_SYMBOL_BUILTIN)
41378 
41379 /*
41380  *  Constructor
41381  */
41382 
41383 DUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_hthread *thr) {
41384 	const duk_uint8_t *desc;
41385 	duk_size_t len;
41386 	duk_uint8_t *buf;
41387 	duk_uint8_t *p;
41388 	duk_int_t magic;
41389 
41390 	magic = duk_get_current_magic(thr);
41391 	if (duk_is_undefined(thr, 0) && (magic == 0)) {
41392 		/* Symbol() accepts undefined and empty string, but they are
41393 		 * treated differently.
41394 		 */
41395 		desc = NULL;
41396 		len = 0;
41397 	} else {
41398 		/* Symbol.for() coerces undefined to 'undefined' */
41399 		desc = (const duk_uint8_t *) duk_to_lstring(thr, 0, &len);
41400 	}
41401 
41402 	/* Maximum symbol data length:
41403 	 *   +1    initial byte (0x80 or 0x81)
41404 	 *   +len  description
41405 	 *   +1    0xff after description, before unique suffix
41406 	 *   +17   autogenerated unique suffix: 'ffffffff-ffffffff' is longest
41407 	 *   +1    0xff after unique suffix for symbols with undefined description
41408 	 */
41409 	buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, 1 + len + 1 + 17 + 1);
41410 	DUK_ASSERT(buf != NULL);
41411 	p = buf + 1;
41412 	DUK_ASSERT(desc != NULL || len == 0);  /* may be NULL if len is 0 */
41413 	duk_memcpy_unsafe((void *) p, (const void *) desc, len);
41414 	p += len;
41415 	if (magic == 0) {
41416 		/* Symbol(): create unique symbol.  Use two 32-bit values
41417 		 * to avoid dependency on 64-bit types and 64-bit integer
41418 		 * formatting (at least for now).
41419 		 */
41420 		if (++thr->heap->sym_counter[0] == 0) {
41421 			thr->heap->sym_counter[1]++;
41422 		}
41423 		p += DUK_SPRINTF((char *) p, "\xFF" "%lx-%lx",
41424 		                 (unsigned long) thr->heap->sym_counter[1],
41425 		                 (unsigned long) thr->heap->sym_counter[0]);
41426 		if (desc == NULL) {
41427 			/* Special case for 'undefined' description, trailing
41428 			 * 0xff distinguishes from empty string description,
41429 			 * but needs minimal special case handling elsewhere.
41430 			 */
41431 			*p++ = 0xff;
41432 		}
41433 		buf[0] = 0x81;
41434 	} else {
41435 		/* Symbol.for(): create a global symbol */
41436 		buf[0] = 0x80;
41437 	}
41438 
41439 	duk_push_lstring(thr, (const char *) buf, (duk_size_t) (p - buf));
41440 	DUK_DDD(DUK_DDDPRINT("created symbol: %!T", duk_get_tval(thr, -1)));
41441 	return 1;
41442 }
41443 
41444 DUK_LOCAL duk_hstring *duk__auto_unbox_symbol(duk_hthread *thr, duk_tval *tv_arg) {
41445 	duk_tval *tv;
41446 	duk_hobject *h_obj;
41447 	duk_hstring *h_str;
41448 
41449 	DUK_ASSERT(tv_arg != NULL);
41450 
41451 	/* XXX: add internal helper: duk_auto_unbox_tval(thr, tv, mask); */
41452 	/* XXX: add internal helper: duk_auto_unbox(thr, tv, idx); */
41453 
41454 	tv = tv_arg;
41455 	if (DUK_TVAL_IS_OBJECT(tv)) {
41456 		h_obj = DUK_TVAL_GET_OBJECT(tv);
41457 		DUK_ASSERT(h_obj != NULL);
41458 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_SYMBOL) {
41459 			tv = duk_hobject_get_internal_value_tval_ptr(thr->heap, h_obj);
41460 			if (tv == NULL) {
41461 				return NULL;
41462 			}
41463 		} else {
41464 			return NULL;
41465 		}
41466 	}
41467 
41468 	if (!DUK_TVAL_IS_STRING(tv)) {
41469 		return NULL;
41470 	}
41471 	h_str = DUK_TVAL_GET_STRING(tv);
41472 	DUK_ASSERT(h_str != NULL);
41473 
41474 	/* Here symbol is more expected than not. */
41475 	if (DUK_UNLIKELY(!DUK_HSTRING_HAS_SYMBOL(h_str))) {
41476 		return NULL;
41477 	}
41478 
41479 	return h_str;
41480 }
41481 
41482 DUK_INTERNAL duk_ret_t duk_bi_symbol_tostring_shared(duk_hthread *thr) {
41483 	duk_hstring *h_str;
41484 
41485 	h_str = duk__auto_unbox_symbol(thr, DUK_HTHREAD_THIS_PTR(thr));
41486 	if (h_str == NULL) {
41487 		return DUK_RET_TYPE_ERROR;
41488 	}
41489 
41490 	if (duk_get_current_magic(thr) == 0) {
41491 		/* .toString() */
41492 		duk_push_symbol_descriptive_string(thr, h_str);
41493 	} else {
41494 		/* .valueOf() */
41495 		duk_push_hstring(thr, h_str);
41496 	}
41497 	return 1;
41498 }
41499 
41500 DUK_INTERNAL duk_ret_t duk_bi_symbol_key_for(duk_hthread *thr) {
41501 	duk_hstring *h;
41502 	const duk_uint8_t *p;
41503 
41504 	/* Argument must be a symbol but not checked here.  The initial byte
41505 	 * check will catch non-symbol strings.
41506 	 */
41507 	h = duk_require_hstring(thr, 0);
41508 	DUK_ASSERT(h != NULL);
41509 
41510 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
41511 	DUK_ASSERT(p != NULL);
41512 
41513 	/* Even for zero length strings there's at least one NUL byte so
41514 	 * we can safely check the initial byte.
41515 	 */
41516 	if (p[0] == 0x80) {
41517 		/* Global symbol, return its key (bytes just after the initial byte). */
41518 		duk_push_lstring(thr, (const char *) (p + 1), (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h) - 1));
41519 		return 1;
41520 	} else if (p[0] == 0x81 || p[0] == 0x82 || p[0] == 0xff) {
41521 		/* Local symbol or hidden symbol, return undefined. */
41522 		return 0;
41523 	}
41524 
41525 	/* Covers normal strings and unknown initial bytes. */
41526 	return DUK_RET_TYPE_ERROR;
41527 }
41528 
41529 DUK_INTERNAL duk_ret_t duk_bi_symbol_toprimitive(duk_hthread *thr) {
41530 	duk_hstring *h_str;
41531 
41532 	h_str = duk__auto_unbox_symbol(thr, DUK_HTHREAD_THIS_PTR(thr));
41533 	if (h_str == NULL) {
41534 		return DUK_RET_TYPE_ERROR;
41535 	}
41536 	duk_push_hstring(thr, h_str);
41537 	return 1;
41538 }
41539 
41540 #endif  /* DUK_USE_SYMBOL_BUILTIN */
41541 /*
41542  *  Thread builtins
41543  */
41544 
41545 /* #include duk_internal.h -> already included */
41546 
41547 /*
41548  *  Constructor
41549  */
41550 
41551 #if defined(DUK_USE_COROUTINE_SUPPORT)
41552 DUK_INTERNAL duk_ret_t duk_bi_thread_constructor(duk_hthread *thr) {
41553 	duk_hthread *new_thr;
41554 	duk_hobject *func;
41555 
41556 	/* Check that the argument is callable; this is not 100% because we
41557 	 * don't allow native functions to be a thread's initial function.
41558 	 * Resume will reject such functions in any case.
41559 	 */
41560 	/* XXX: need a duk_require_func_promote_lfunc() */
41561 	func = duk_require_hobject_promote_lfunc(thr, 0);
41562 	DUK_ASSERT(func != NULL);
41563 	duk_require_callable(thr, 0);
41564 
41565 	duk_push_thread(thr);
41566 	new_thr = (duk_hthread *) duk_known_hobject(thr, -1);
41567 	new_thr->state = DUK_HTHREAD_STATE_INACTIVE;
41568 
41569 	/* push initial function call to new thread stack; this is
41570 	 * picked up by resume().
41571 	 */
41572 	duk_push_hobject(new_thr, func);
41573 
41574 	return 1;  /* return thread */
41575 }
41576 #endif
41577 
41578 /*
41579  *  Resume a thread.
41580  *
41581  *  The thread must be in resumable state, either (a) new thread which hasn't
41582  *  yet started, or (b) a thread which has previously yielded.  This method
41583  *  must be called from an ECMAScript function.
41584  *
41585  *  Args:
41586  *    - thread
41587  *    - value
41588  *    - isError (defaults to false)
41589  *
41590  *  Note: yield and resume handling is currently asymmetric.
41591  */
41592 
41593 #if defined(DUK_USE_COROUTINE_SUPPORT)
41594 DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_hthread *ctx) {
41595 	duk_hthread *thr = (duk_hthread *) ctx;
41596 	duk_hthread *thr_resume;
41597 	duk_hobject *caller_func;
41598 	duk_small_uint_t is_error;
41599 
41600 	DUK_DDD(DUK_DDDPRINT("Duktape.Thread.resume(): thread=%!T, value=%!T, is_error=%!T",
41601 	                     (duk_tval *) duk_get_tval(thr, 0),
41602 	                     (duk_tval *) duk_get_tval(thr, 1),
41603 	                     (duk_tval *) duk_get_tval(thr, 2)));
41604 
41605 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
41606 	DUK_ASSERT(thr->heap->curr_thread == thr);
41607 
41608 	thr_resume = duk_require_hthread(thr, 0);
41609 	DUK_ASSERT(duk_get_top(thr) == 3);
41610 	is_error = (duk_small_uint_t) duk_to_boolean_top_pop(thr);
41611 	DUK_ASSERT(duk_get_top(thr) == 2);
41612 
41613 	/* [ thread value ] */
41614 
41615 	/*
41616 	 *  Thread state and calling context checks
41617 	 */
41618 
41619 	if (thr->callstack_top < 2) {
41620 		DUK_DD(DUK_DDPRINT("resume state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.resume)"));
41621 		goto state_error;
41622 	}
41623 	DUK_ASSERT(thr->callstack_curr != NULL);
41624 	DUK_ASSERT(thr->callstack_curr->parent != NULL);
41625 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);  /* us */
41626 	DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
41627 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL);  /* caller */
41628 
41629 	caller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent);
41630 	if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {
41631 		DUK_DD(DUK_DDPRINT("resume state invalid: caller must be ECMAScript code"));
41632 		goto state_error;
41633 	}
41634 
41635 	/* Note: there is no requirement that: 'thr->callstack_preventcount == 1'
41636 	 * like for yield.
41637 	 */
41638 
41639 	if (thr_resume->state != DUK_HTHREAD_STATE_INACTIVE &&
41640 	    thr_resume->state != DUK_HTHREAD_STATE_YIELDED) {
41641 		DUK_DD(DUK_DDPRINT("resume state invalid: target thread must be INACTIVE or YIELDED"));
41642 		goto state_error;
41643 	}
41644 
41645 	DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE ||
41646 	           thr_resume->state == DUK_HTHREAD_STATE_YIELDED);
41647 
41648 	/* Further state-dependent pre-checks */
41649 
41650 	if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
41651 		/* no pre-checks now, assume a previous yield() has left things in
41652 		 * tip-top shape (longjmp handler will assert for these).
41653 		 */
41654 	} else {
41655 		duk_hobject *h_fun;
41656 
41657 		DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE);
41658 
41659 		/* The initial function must be an ECMAScript function (but
41660 		 * can be bound).  We must make sure of that before we longjmp
41661 		 * because an error in the RESUME handler call processing will
41662 		 * not be handled very cleanly.
41663 		 */
41664 		if ((thr_resume->callstack_top != 0) ||
41665 		    (thr_resume->valstack_top - thr_resume->valstack != 1)) {
41666 			goto state_error;
41667 		}
41668 
41669 		duk_push_tval(thr, DUK_GET_TVAL_NEGIDX(thr_resume, -1));
41670 		duk_resolve_nonbound_function(thr);
41671 		h_fun = duk_require_hobject(thr, -1);  /* reject lightfuncs on purpose */
41672 		if (!DUK_HOBJECT_IS_CALLABLE(h_fun) || !DUK_HOBJECT_IS_COMPFUNC(h_fun)) {
41673 			goto state_error;
41674 		}
41675 		duk_pop(thr);
41676 	}
41677 
41678 #if 0
41679 	/* This check would prevent a heap destruction time finalizer from
41680 	 * launching a coroutine, which would ensure that during finalization
41681 	 * 'thr' would always equal heap_thread.  Normal runtime finalizers
41682 	 * run with ms_running == 0, i.e. outside mark-and-sweep.  See GH-2030.
41683 	 */
41684 	if (thr->heap->ms_running) {
41685 		DUK_D(DUK_DPRINT("refuse Duktape.Thread.resume() when ms_running != 0"));
41686 		goto state_error;
41687 	}
41688 #endif
41689 
41690 	/*
41691 	 *  The error object has been augmented with a traceback and other
41692 	 *  info from its creation point -- usually another thread.  The
41693 	 *  error handler is called here right before throwing, but it also
41694 	 *  runs in the resumer's thread.  It might be nice to get a traceback
41695 	 *  from the resumee but this is not the case now.
41696 	 */
41697 
41698 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
41699 	if (is_error) {
41700 		DUK_ASSERT_TOP(thr, 2);  /* value (error) is at stack top */
41701 		duk_err_augment_error_throw(thr);  /* in resumer's context */
41702 	}
41703 #endif
41704 
41705 #if defined(DUK_USE_DEBUG)
41706 	if (is_error) {
41707 		DUK_DDD(DUK_DDDPRINT("RESUME ERROR: thread=%!T, value=%!T",
41708 		                     (duk_tval *) duk_get_tval(thr, 0),
41709 		                     (duk_tval *) duk_get_tval(thr, 1)));
41710 	} else if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
41711 		DUK_DDD(DUK_DDDPRINT("RESUME NORMAL: thread=%!T, value=%!T",
41712 		                     (duk_tval *) duk_get_tval(thr, 0),
41713 		                     (duk_tval *) duk_get_tval(thr, 1)));
41714 	} else {
41715 		DUK_DDD(DUK_DDDPRINT("RESUME INITIAL: thread=%!T, value=%!T",
41716 		                     (duk_tval *) duk_get_tval(thr, 0),
41717 		                     (duk_tval *) duk_get_tval(thr, 1)));
41718 	}
41719 #endif
41720 
41721 	thr->heap->lj.type = DUK_LJ_TYPE_RESUME;
41722 
41723 	/* lj value2: thread */
41724 	DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
41725 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value2, &thr->valstack_bottom[0]);  /* side effects */
41726 
41727 	/* lj value1: value */
41728 	DUK_ASSERT(thr->valstack_bottom + 1 < thr->valstack_top);
41729 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[1]);  /* side effects */
41730 	DUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);
41731 
41732 	thr->heap->lj.iserror = is_error;
41733 
41734 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */
41735 	duk_err_longjmp(thr);  /* execution resumes in bytecode executor */
41736 	DUK_UNREACHABLE();
41737 	/* Never here, fall through to error (from compiler point of view). */
41738 
41739  state_error:
41740 	DUK_DCERROR_TYPE_INVALID_STATE(thr);
41741 }
41742 #endif
41743 
41744 /*
41745  *  Yield the current thread.
41746  *
41747  *  The thread must be in yieldable state: it must have a resumer, and there
41748  *  must not be any yield-preventing calls (native calls and constructor calls,
41749  *  currently) in the thread's call stack (otherwise a resume would not be
41750  *  possible later).  This method must be called from an ECMAScript function.
41751  *
41752  *  Args:
41753  *    - value
41754  *    - isError (defaults to false)
41755  *
41756  *  Note: yield and resume handling is currently asymmetric.
41757  */
41758 
41759 #if defined(DUK_USE_COROUTINE_SUPPORT)
41760 DUK_INTERNAL duk_ret_t duk_bi_thread_yield(duk_hthread *thr) {
41761 	duk_hobject *caller_func;
41762 	duk_small_uint_t is_error;
41763 
41764 	DUK_DDD(DUK_DDDPRINT("Duktape.Thread.yield(): value=%!T, is_error=%!T",
41765 	                     (duk_tval *) duk_get_tval(thr, 0),
41766 	                     (duk_tval *) duk_get_tval(thr, 1)));
41767 
41768 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
41769 	DUK_ASSERT(thr->heap->curr_thread == thr);
41770 
41771 	DUK_ASSERT(duk_get_top(thr) == 2);
41772 	is_error = (duk_small_uint_t) duk_to_boolean_top_pop(thr);
41773 	DUK_ASSERT(duk_get_top(thr) == 1);
41774 
41775 	/* [ value ] */
41776 
41777 	/*
41778 	 *  Thread state and calling context checks
41779 	 */
41780 
41781 	if (!thr->resumer) {
41782 		DUK_DD(DUK_DDPRINT("yield state invalid: current thread must have a resumer"));
41783 		goto state_error;
41784 	}
41785 	DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
41786 
41787 	if (thr->callstack_top < 2) {
41788 		DUK_DD(DUK_DDPRINT("yield state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.yield)"));
41789 		goto state_error;
41790 	}
41791 	DUK_ASSERT(thr->callstack_curr != NULL);
41792 	DUK_ASSERT(thr->callstack_curr->parent != NULL);
41793 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);  /* us */
41794 	DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
41795 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL);  /* caller */
41796 
41797 	caller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent);
41798 	if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {
41799 		DUK_DD(DUK_DDPRINT("yield state invalid: caller must be ECMAScript code"));
41800 		goto state_error;
41801 	}
41802 
41803 	DUK_ASSERT(thr->callstack_preventcount >= 1);  /* should never be zero, because we (Duktape.Thread.yield) are on the stack */
41804 	if (thr->callstack_preventcount != 1) {
41805 		/* Note: the only yield-preventing call is Duktape.Thread.yield(), hence check for 1, not 0 */
41806 		DUK_DD(DUK_DDPRINT("yield state invalid: there must be no yield-preventing calls in current thread callstack (preventcount is %ld)",
41807 		                   (long) thr->callstack_preventcount));
41808 		goto state_error;
41809 	}
41810 
41811 	/*
41812 	 *  The error object has been augmented with a traceback and other
41813 	 *  info from its creation point -- usually the current thread.
41814 	 *  The error handler, however, is called right before throwing
41815 	 *  and runs in the yielder's thread.
41816 	 */
41817 
41818 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
41819 	if (is_error) {
41820 		DUK_ASSERT_TOP(thr, 1);  /* value (error) is at stack top */
41821 		duk_err_augment_error_throw(thr);  /* in yielder's context */
41822 	}
41823 #endif
41824 
41825 #if defined(DUK_USE_DEBUG)
41826 	if (is_error) {
41827 		DUK_DDD(DUK_DDDPRINT("YIELD ERROR: value=%!T",
41828 		                     (duk_tval *) duk_get_tval(thr, 0)));
41829 	} else {
41830 		DUK_DDD(DUK_DDDPRINT("YIELD NORMAL: value=%!T",
41831 		                     (duk_tval *) duk_get_tval(thr, 0)));
41832 	}
41833 #endif
41834 
41835 	/*
41836 	 *  Process yield
41837 	 *
41838 	 *  After longjmp(), processing continues in bytecode executor longjmp
41839 	 *  handler, which will e.g. update thr->resumer to NULL.
41840 	 */
41841 
41842 	thr->heap->lj.type = DUK_LJ_TYPE_YIELD;
41843 
41844 	/* lj value1: value */
41845 	DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
41846 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[0]);  /* side effects */
41847 	DUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);
41848 
41849 	thr->heap->lj.iserror = is_error;
41850 
41851 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */
41852 	duk_err_longjmp(thr);  /* execution resumes in bytecode executor */
41853 	DUK_UNREACHABLE();
41854 	/* Never here, fall through to error (from compiler point of view). */
41855 
41856  state_error:
41857 	DUK_DCERROR_TYPE_INVALID_STATE(thr);
41858 }
41859 #endif
41860 
41861 #if defined(DUK_USE_COROUTINE_SUPPORT)
41862 DUK_INTERNAL duk_ret_t duk_bi_thread_current(duk_hthread *thr) {
41863 	duk_push_current_thread(thr);
41864 	return 1;
41865 }
41866 #endif
41867 /*
41868  *  Type error thrower, E5 Section 13.2.3.
41869  */
41870 
41871 /* #include duk_internal.h -> already included */
41872 
41873 DUK_INTERNAL duk_ret_t duk_bi_type_error_thrower(duk_hthread *thr) {
41874 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
41875 }
41876 /*
41877  *  Fixed buffer helper useful for debugging, requires no allocation
41878  *  which is critical for debugging.
41879  */
41880 
41881 /* #include duk_internal.h -> already included */
41882 
41883 #if defined(DUK_USE_DEBUG)
41884 
41885 DUK_INTERNAL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length) {
41886 	duk_size_t avail;
41887 	duk_size_t copylen;
41888 
41889 	avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
41890 	if (length > avail) {
41891 		copylen = avail;
41892 		fb->truncated = 1;
41893 	} else {
41894 		copylen = length;
41895 	}
41896 	duk_memcpy_unsafe(fb->buffer + fb->offset, buffer, copylen);
41897 	fb->offset += copylen;
41898 }
41899 
41900 DUK_INTERNAL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x) {
41901 	duk_fb_put_bytes(fb, (const duk_uint8_t *) &x, 1);
41902 }
41903 
41904 DUK_INTERNAL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x) {
41905 	duk_fb_put_bytes(fb, (const duk_uint8_t *) x, (duk_size_t) DUK_STRLEN(x));
41906 }
41907 
41908 DUK_INTERNAL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...) {
41909 	duk_size_t avail;
41910 	va_list ap;
41911 
41912 	va_start(ap, fmt);
41913 	avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
41914 	if (avail > 0) {
41915 		duk_int_t res = (duk_int_t) DUK_VSNPRINTF((char *) (fb->buffer + fb->offset), avail, fmt, ap);
41916 		if (res < 0) {
41917 			/* error */
41918 		} else if ((duk_size_t) res >= avail) {
41919 			/* (maybe) truncated */
41920 			fb->offset += avail;
41921 			if ((duk_size_t) res > avail) {
41922 				/* actual chars dropped (not just NUL term) */
41923 				fb->truncated = 1;
41924 			}
41925 		} else {
41926 			/* normal */
41927 			fb->offset += (duk_size_t) res;
41928 		}
41929 	}
41930 	va_end(ap);
41931 }
41932 
41933 DUK_INTERNAL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size) {
41934 	char buf[64+1];
41935 	duk_debug_format_funcptr(buf, sizeof(buf), fptr, fptr_size);
41936 	buf[sizeof(buf) - 1] = (char) 0;
41937 	duk_fb_put_cstring(fb, buf);
41938 }
41939 
41940 DUK_INTERNAL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) {
41941 	return (fb->offset >= fb->length);
41942 }
41943 
41944 #endif  /* DUK_USE_DEBUG */
41945 /*
41946  *  Custom formatter for debug printing, allowing Duktape specific data
41947  *  structures (such as tagged values and heap objects) to be printed with
41948  *  a nice format string.  Because debug printing should not affect execution
41949  *  state, formatting here must be independent of execution (see implications
41950  *  below) and must not allocate memory.
41951  *
41952  *  Custom format tags begin with a '%!' to safely distinguish them from
41953  *  standard format tags.  The following conversions are supported:
41954  *
41955  *     %!T    tagged value (duk_tval *)
41956  *     %!O    heap object (duk_heaphdr *)
41957  *     %!I    decoded bytecode instruction
41958  *     %!X    bytecode instruction opcode name (arg is long)
41959  *     %!C    catcher (duk_catcher *)
41960  *     %!A    activation (duk_activation *)
41961  *
41962  *  Everything is serialized in a JSON-like manner.  The default depth is one
41963  *  level, internal prototype is not followed, and internal properties are not
41964  *  serialized.  The following modifiers change this behavior:
41965  *
41966  *     @      print pointers
41967  *     #      print binary representations (where applicable)
41968  *     d      deep traversal of own properties (not prototype)
41969  *     p      follow prototype chain (useless without 'd')
41970  *     i      include internal properties (other than prototype)
41971  *     x      hexdump buffers
41972  *     h      heavy formatting
41973  *
41974  *  For instance, the following serializes objects recursively, but does not
41975  *  follow the prototype chain nor print internal properties: "%!dO".
41976  *
41977  *  Notes:
41978  *
41979  *    * Standard snprintf return value semantics seem to vary.  This
41980  *      implementation returns the number of bytes it actually wrote
41981  *      (excluding the null terminator).  If retval == buffer size,
41982  *      output was truncated (except for corner cases).
41983  *
41984  *    * Output format is intentionally different from ECMAScript
41985  *      formatting requirements, as formatting here serves debugging
41986  *      of internals.
41987  *
41988  *    * Depth checking (and updating) is done in each type printer
41989  *      separately, to allow them to call each other freely.
41990  *
41991  *    * Some pathological structures might take ages to print (e.g.
41992  *      self recursion with 100 properties pointing to the object
41993  *      itself).  To guard against these, each printer also checks
41994  *      whether the output buffer is full; if so, early exit.
41995  *
41996  *    * Reference loops are detected using a loop stack.
41997  */
41998 
41999 /* #include duk_internal.h -> already included */
42000 
42001 #if defined(DUK_USE_DEBUG)
42002 
42003 /* #include stdio.h -> already included */
42004 /* #include stdarg.h -> already included */
42005 #include <string.h>
42006 
42007 /* list of conversion specifiers that terminate a format tag;
42008  * this is unfortunately guesswork.
42009  */
42010 #define DUK__ALLOWED_STANDARD_SPECIFIERS  "diouxXeEfFgGaAcsCSpnm"
42011 
42012 /* maximum length of standard format tag that we support */
42013 #define DUK__MAX_FORMAT_TAG_LENGTH  32
42014 
42015 /* heapobj recursion depth when deep printing is selected */
42016 #define DUK__DEEP_DEPTH_LIMIT  8
42017 
42018 /* maximum recursion depth for loop detection stacks */
42019 #define DUK__LOOP_STACK_DEPTH  256
42020 
42021 /* must match bytecode defines now; build autogenerate? */
42022 DUK_LOCAL const char * const duk__bc_optab[256] = {
42023 	"LDREG", "STREG", "JUMP", "LDCONST", "LDINT", "LDINTX", "LDTHIS", "LDUNDEF",
42024 	"LDNULL", "LDTRUE", "LDFALSE", "GETVAR", "BNOT", "LNOT", "UNM", "UNP",
42025 	"EQ_RR", "EQ_CR", "EQ_RC", "EQ_CC", "NEQ_RR", "NEQ_CR", "NEQ_RC", "NEQ_CC",
42026 	"SEQ_RR", "SEQ_CR", "SEQ_RC", "SEQ_CC", "SNEQ_RR", "SNEQ_CR", "SNEQ_RC", "SNEQ_CC",
42027 
42028 	"GT_RR", "GT_CR", "GT_RC", "GT_CC", "GE_RR", "GE_CR", "GE_RC", "GE_CC",
42029 	"LT_RR", "LT_CR", "LT_RC", "LT_CC", "LE_RR", "LE_CR", "LE_RC", "LE_CC",
42030 	"IFTRUE_R", "IFTRUE_C", "IFFALSE_R", "IFFALSE_C", "ADD_RR", "ADD_CR", "ADD_RC", "ADD_CC",
42031 	"SUB_RR", "SUB_CR", "SUB_RC", "SUB_CC", "MUL_RR", "MUL_CR", "MUL_RC", "MUL_CC",
42032 
42033 	"DIV_RR", "DIV_CR", "DIV_RC", "DIV_CC", "MOD_RR", "MOD_CR", "MOD_RC", "MOD_CC",
42034 	"EXP_RR", "EXP_CR", "EXP_RC", "EXP_CC", "BAND_RR", "BAND_CR", "BAND_RC", "BAND_CC",
42035 	"BOR_RR", "BOR_CR", "BOR_RC", "BOR_CC", "BXOR_RR", "BXOR_CR", "BXOR_RC", "BXOR_CC",
42036 	"BASL_RR", "BASL_CR", "BASL_RC", "BASL_CC", "BLSR_RR", "BLSR_CR", "BLSR_RC", "BLSR_CC",
42037 
42038 	"BASR_RR", "BASR_CR", "BASR_RC", "BASR_CC", "INSTOF_RR", "INSTOF_CR", "INSTOF_RC", "INSTOF_CC",
42039 	"IN_RR", "IN_CR", "IN_RC", "IN_CC", "GETPROP_RR", "GETPROP_CR", "GETPROP_RC", "GETPROP_CC",
42040 	"PUTPROP_RR", "PUTPROP_CR", "PUTPROP_RC", "PUTPROP_CC", "DELPROP_RR", "DELPROP_CR", "DELPROP_RC", "DELPROP_CC",
42041 	"PREINCR", "PREDECR", "POSTINCR", "POSTDECR", "PREINCV", "PREDECV", "POSTINCV", "POSTDECV",
42042 
42043 	"PREINCP_RR", "PREINCP_CR", "PREINCP_RC", "PREINCP_CC", "PREDECP_RR", "PREDECP_CR", "PREDECP_RC", "PREDECP_CC",
42044 	"POSTINCP_RR", "POSTINCP_CR", "POSTINCP_RC", "POSTINCP_CC", "POSTDECP_RR", "POSTDECP_CR", "POSTDECP_RC", "POSTDECP_CC",
42045 	"DECLVAR_RR", "DECLVAR_CR", "DECLVAR_RC", "DECLVAR_CC", "REGEXP_RR", "REGEXP_RC", "REGEXP_CR", "REGEXP_CC",
42046 	"CLOSURE", "TYPEOF", "TYPEOFID", "PUTVAR", "DELVAR", "RETREG", "RETUNDEF", "RETCONST",
42047 
42048 	"RETCONSTN", "LABEL", "ENDLABEL", "BREAK", "CONTINUE", "TRYCATCH", "ENDTRY", "ENDCATCH",
42049 	"ENDFIN", "THROW", "INVLHS", "CSREG", "CSVAR_RR", "CSVAR_CR", "CSVAR_RC", "CSVAR_CC",
42050 	"CALL0", "CALL1", "CALL2", "CALL3", "CALL4", "CALL5", "CALL6", "CALL7",
42051 	"CALL8", "CALL9", "CALL10", "CALL11", "CALL12", "CALL13", "CALL14", "CALL15",
42052 
42053 	"NEWOBJ", "NEWARR", "MPUTOBJ", "MPUTOBJI", "INITSET", "INITGET", "MPUTARR", "MPUTARRI",
42054 	"SETALEN", "INITENUM", "NEXTENUM", "NEWTARGET", "DEBUGGER", "NOP", "INVALID", "UNUSED207",
42055 	"GETPROPC_RR", "GETPROPC_CR", "GETPROPC_RC", "GETPROPC_CC", "UNUSED212", "UNUSED213", "UNUSED214", "UNUSED215",
42056 	"UNUSED216", "UNUSED217", "UNUSED218", "UNUSED219", "UNUSED220", "UNUSED221", "UNUSED222", "UNUSED223",
42057 
42058 	"UNUSED224", "UNUSED225", "UNUSED226", "UNUSED227", "UNUSED228", "UNUSED229", "UNUSED230", "UNUSED231",
42059 	"UNUSED232", "UNUSED233", "UNUSED234", "UNUSED235", "UNUSED236", "UNUSED237", "UNUSED238", "UNUSED239",
42060 	"UNUSED240", "UNUSED241", "UNUSED242", "UNUSED243", "UNUSED244", "UNUSED245", "UNUSED246", "UNUSED247",
42061 	"UNUSED248", "UNUSED249", "UNUSED250", "UNUSED251", "UNUSED252", "UNUSED253", "UNUSED254", "UNUSED255"
42062 };
42063 
42064 typedef struct duk__dprint_state duk__dprint_state;
42065 struct duk__dprint_state {
42066 	duk_fixedbuffer *fb;
42067 
42068 	/* loop_stack_index could be perhaps be replaced by 'depth', but it's nice
42069 	 * to not couple these two mechanisms unnecessarily.
42070 	 */
42071 	duk_hobject *loop_stack[DUK__LOOP_STACK_DEPTH];
42072 	duk_int_t loop_stack_index;
42073 	duk_int_t loop_stack_limit;
42074 
42075 	duk_int_t depth;
42076 	duk_int_t depth_limit;
42077 
42078 	duk_bool_t pointer;
42079 	duk_bool_t heavy;
42080 	duk_bool_t binary;
42081 	duk_bool_t follow_proto;
42082 	duk_bool_t internal;
42083 	duk_bool_t hexdump;
42084 };
42085 
42086 /* helpers */
42087 DUK_LOCAL_DECL void duk__print_hstring(duk__dprint_state *st, duk_hstring *k, duk_bool_t quotes);
42088 DUK_LOCAL_DECL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h);
42089 DUK_LOCAL_DECL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h);
42090 DUK_LOCAL_DECL void duk__print_tval(duk__dprint_state *st, duk_tval *tv);
42091 DUK_LOCAL_DECL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins);
42092 DUK_LOCAL_DECL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
42093 DUK_LOCAL_DECL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
42094 DUK_LOCAL_DECL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h);
42095 
42096 DUK_LOCAL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
42097 	duk_fixedbuffer *fb = st->fb;
42098 
42099 	if (st->heavy) {
42100 		duk_fb_sprintf(fb, "(%p)", (void *) h);
42101 	}
42102 
42103 	if (!h) {
42104 		return;
42105 	}
42106 
42107 	if (st->binary) {
42108 		duk_size_t i;
42109 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
42110 		for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
42111 			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
42112 		}
42113 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
42114 	}
42115 
42116 #if defined(DUK_USE_REFERENCE_COUNTING)  /* currently implicitly also DUK_USE_DOUBLE_LINKED_HEAP */
42117 	if (st->heavy) {
42118 		duk_fb_sprintf(fb, "[h_next=%p,h_prev=%p,h_refcount=%lu,h_flags=%08lx,type=%ld,"
42119 		               "reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
42120 		               (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
42121 		               (void *) DUK_HEAPHDR_GET_PREV(NULL, h),
42122 		               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(h),
42123 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
42124 		               (long) DUK_HEAPHDR_GET_TYPE(h),
42125 		               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
42126 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
42127 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
42128 		               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
42129 	}
42130 #else
42131 	if (st->heavy) {
42132 		duk_fb_sprintf(fb, "[h_next=%p,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
42133 		               (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
42134 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
42135 		               (long) DUK_HEAPHDR_GET_TYPE(h),
42136 		               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
42137 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
42138 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
42139 		               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
42140 	}
42141 #endif
42142 }
42143 
42144 DUK_LOCAL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h) {
42145 	duk_fixedbuffer *fb = st->fb;
42146 
42147 	if (st->heavy) {
42148 		duk_fb_sprintf(fb, "(%p)", (void *) h);
42149 	}
42150 
42151 	if (!h) {
42152 		return;
42153 	}
42154 
42155 	if (st->binary) {
42156 		duk_size_t i;
42157 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
42158 		for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
42159 			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
42160 		}
42161 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
42162 	}
42163 
42164 #if defined(DUK_USE_REFERENCE_COUNTING)
42165 	if (st->heavy) {
42166 		duk_fb_sprintf(fb, "[h_refcount=%lu,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
42167 		               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h),
42168 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
42169 		               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
42170 		               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
42171 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
42172 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
42173 		               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
42174 	}
42175 #else
42176 	if (st->heavy) {
42177 		duk_fb_sprintf(fb, "[h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
42178 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
42179 		               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
42180 		               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
42181 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
42182 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
42183 		               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
42184 	}
42185 #endif
42186 }
42187 
42188 DUK_LOCAL void duk__print_hstring(duk__dprint_state *st, duk_hstring *h, duk_bool_t quotes) {
42189 	duk_fixedbuffer *fb = st->fb;
42190 	const duk_uint8_t *p;
42191 	const duk_uint8_t *p_end;
42192 
42193 	/* terminal type: no depth check */
42194 
42195 	if (duk_fb_is_full(fb)) {
42196 		return;
42197 	}
42198 
42199 	duk__print_shared_heaphdr_string(st, &h->hdr);
42200 
42201 	if (!h) {
42202 		duk_fb_put_cstring(fb, "NULL");
42203 		return;
42204 	}
42205 
42206 	p = DUK_HSTRING_GET_DATA(h);
42207 	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
42208 
42209 	if (p_end > p && p[0] == DUK_ASC_UNDERSCORE) {
42210 		/* If property key begins with underscore, encode it with
42211 		 * forced quotes (e.g. "_Foo") to distinguish it from encoded
42212 		 * internal properties (e.g. \x82Bar -> _Bar).
42213 		 */
42214 		quotes = 1;
42215 	}
42216 
42217 	if (quotes) {
42218 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
42219 	}
42220 	while (p < p_end) {
42221 		duk_uint8_t ch = *p++;
42222 
42223 		/* two special escapes: '\' and '"', other printables as is */
42224 		if (ch == '\\') {
42225 			duk_fb_sprintf(fb, "\\\\");
42226 		} else if (ch == '"') {
42227 			duk_fb_sprintf(fb, "\\\"");
42228 		} else if (ch >= 0x20 && ch <= 0x7e) {
42229 			duk_fb_put_byte(fb, ch);
42230 		} else if (ch == 0x82 && !quotes) {
42231 			/* encode \x82Bar as _Bar if no quotes are
42232 			 * applied, this is for readable internal keys.
42233 			 */
42234 			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_UNDERSCORE);
42235 		} else {
42236 			duk_fb_sprintf(fb, "\\x%02lx", (unsigned long) ch);
42237 		}
42238 	}
42239 	if (quotes) {
42240 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
42241 	}
42242 #if defined(DUK_USE_REFERENCE_COUNTING)
42243 	/* XXX: limit to quoted strings only, to save keys from being cluttered? */
42244 	duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
42245 #endif
42246 }
42247 
42248 #define DUK__COMMA()  do { \
42249 		if (first) { \
42250 			first = 0; \
42251 		} else { \
42252 			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA); \
42253 		} \
42254 	} while (0)
42255 
42256 DUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) {
42257 	duk_fixedbuffer *fb = st->fb;
42258 	duk_uint_fast32_t i;
42259 	duk_tval *tv;
42260 	duk_hstring *key;
42261 	duk_bool_t first = 1;
42262 	const char *brace1 = "{";
42263 	const char *brace2 = "}";
42264 	duk_bool_t pushed_loopstack = 0;
42265 
42266 	if (duk_fb_is_full(fb)) {
42267 		return;
42268 	}
42269 
42270 	duk__print_shared_heaphdr(st, &h->hdr);
42271 
42272 	if (h && DUK_HOBJECT_HAS_ARRAY_PART(h)) {
42273 		brace1 = "[";
42274 		brace2 = "]";
42275 	}
42276 
42277 	if (!h) {
42278 		duk_fb_put_cstring(fb, "NULL");
42279 		goto finished;
42280 	}
42281 
42282 	if (st->depth >= st->depth_limit) {
42283 		const char *subtype = "generic";
42284 
42285 		if (DUK_HOBJECT_IS_COMPFUNC(h)) {
42286 			subtype = "compfunc";
42287 		} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
42288 			subtype = "natfunc";
42289 		} else if (DUK_HOBJECT_IS_THREAD(h)) {
42290 			subtype = "thread";
42291 		} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
42292 			subtype = "bufobj";
42293 		} else if (DUK_HOBJECT_IS_ARRAY(h)) {
42294 			subtype = "array";
42295 		}
42296 		duk_fb_sprintf(fb, "%sobject/%s %p%s", (const char *) brace1, subtype, (void *) h, (const char *) brace2);
42297 		return;
42298 	}
42299 
42300 	for (i = 0; i < (duk_uint_fast32_t) st->loop_stack_index; i++) {
42301 		if (st->loop_stack[i] == h) {
42302 			duk_fb_sprintf(fb, "%sLOOP:%p%s", (const char *) brace1, (void *) h, (const char *) brace2);
42303 			return;
42304 		}
42305 	}
42306 
42307 	/* after this, return paths should 'goto finished' for decrement */
42308 	st->depth++;
42309 
42310 	if (st->loop_stack_index >= st->loop_stack_limit) {
42311 		duk_fb_sprintf(fb, "%sOUT-OF-LOOP-STACK%s", (const char *) brace1, (const char *) brace2);
42312 		goto finished;
42313 	}
42314 	st->loop_stack[st->loop_stack_index++] = h;
42315 	pushed_loopstack = 1;
42316 
42317 	/*
42318 	 *  Notation: double underscore used for internal properties which are not
42319 	 *  stored in the property allocation (e.g. '__valstack').
42320 	 */
42321 
42322 	duk_fb_put_cstring(fb, brace1);
42323 
42324 	if (DUK_HOBJECT_GET_PROPS(NULL, h)) {
42325 		duk_uint32_t a_limit;
42326 
42327 		a_limit = DUK_HOBJECT_GET_ASIZE(h);
42328 		if (st->internal) {
42329 			/* dump all allocated entries, unused entries print as 'unused',
42330 			 * note that these may extend beyond current 'length' and look
42331 			 * a bit funny.
42332 			 */
42333 		} else {
42334 			/* leave out trailing 'unused' elements */
42335 			while (a_limit > 0) {
42336 				tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, a_limit - 1);
42337 				if (!DUK_TVAL_IS_UNUSED(tv)) {
42338 					break;
42339 				}
42340 				a_limit--;
42341 			}
42342 		}
42343 
42344 		for (i = 0; i < a_limit; i++) {
42345 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, i);
42346 			DUK__COMMA();
42347 			duk__print_tval(st, tv);
42348 		}
42349 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(h); i++) {
42350 			key = DUK_HOBJECT_E_GET_KEY(NULL, h, i);
42351 			if (!key) {
42352 				continue;
42353 			}
42354 			if (!st->internal && DUK_HSTRING_HAS_HIDDEN(key)) {
42355 				continue;
42356 			}
42357 			DUK__COMMA();
42358 			duk__print_hstring(st, key, 0);
42359 			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COLON);
42360 			if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(NULL, h, i)) {
42361 				duk_fb_sprintf(fb, "[get:%p,set:%p]",
42362 				               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.get,
42363 				               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.set);
42364 			} else {
42365 				tv = &DUK_HOBJECT_E_GET_VALUE(NULL, h, i).v;
42366 				duk__print_tval(st, tv);
42367 			}
42368 			if (st->heavy) {
42369 				duk_fb_sprintf(fb, "<%02lx>", (unsigned long) DUK_HOBJECT_E_GET_FLAGS(NULL, h, i));
42370 			}
42371 		}
42372 	}
42373 	if (st->internal) {
42374 		if (DUK_HOBJECT_IS_ARRAY(h)) {
42375 			DUK__COMMA(); duk_fb_sprintf(fb, "__array:true");
42376 		}
42377 		if (DUK_HOBJECT_HAS_EXTENSIBLE(h)) {
42378 			DUK__COMMA(); duk_fb_sprintf(fb, "__extensible:true");
42379 		}
42380 		if (DUK_HOBJECT_HAS_CONSTRUCTABLE(h)) {
42381 			DUK__COMMA(); duk_fb_sprintf(fb, "__constructable:true");
42382 		}
42383 		if (DUK_HOBJECT_HAS_BOUNDFUNC(h)) {
42384 			DUK__COMMA(); duk_fb_sprintf(fb, "__boundfunc:true");
42385 		}
42386 		if (DUK_HOBJECT_HAS_COMPFUNC(h)) {
42387 			DUK__COMMA(); duk_fb_sprintf(fb, "__compfunc:true");
42388 		}
42389 		if (DUK_HOBJECT_HAS_NATFUNC(h)) {
42390 			DUK__COMMA(); duk_fb_sprintf(fb, "__natfunc:true");
42391 		}
42392 		if (DUK_HOBJECT_HAS_BUFOBJ(h)) {
42393 			DUK__COMMA(); duk_fb_sprintf(fb, "__bufobj:true");
42394 		}
42395 		if (DUK_HOBJECT_IS_THREAD(h)) {
42396 			DUK__COMMA(); duk_fb_sprintf(fb, "__thread:true");
42397 		}
42398 		if (DUK_HOBJECT_HAS_ARRAY_PART(h)) {
42399 			DUK__COMMA(); duk_fb_sprintf(fb, "__array_part:true");
42400 		}
42401 		if (DUK_HOBJECT_HAS_STRICT(h)) {
42402 			DUK__COMMA(); duk_fb_sprintf(fb, "__strict:true");
42403 		}
42404 		if (DUK_HOBJECT_HAS_NOTAIL(h)) {
42405 			DUK__COMMA(); duk_fb_sprintf(fb, "__notail:true");
42406 		}
42407 		if (DUK_HOBJECT_HAS_NEWENV(h)) {
42408 			DUK__COMMA(); duk_fb_sprintf(fb, "__newenv:true");
42409 		}
42410 		if (DUK_HOBJECT_HAS_NAMEBINDING(h)) {
42411 			DUK__COMMA(); duk_fb_sprintf(fb, "__namebinding:true");
42412 		}
42413 		if (DUK_HOBJECT_HAS_CREATEARGS(h)) {
42414 			DUK__COMMA(); duk_fb_sprintf(fb, "__createargs:true");
42415 		}
42416 		if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)) {
42417 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_array:true");
42418 		}
42419 		if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)) {
42420 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_stringobj:true");
42421 		}
42422 		if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)) {
42423 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_arguments:true");
42424 		}
42425 		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
42426 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_bufobj:true");
42427 		}
42428 		if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)) {
42429 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_proxyobj:true");
42430 		}
42431 	}
42432 
42433 	if (st->internal && DUK_HOBJECT_IS_ARRAY(h)) {
42434 		duk_harray *a = (duk_harray *) h;
42435 		DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) a->length);
42436 		DUK__COMMA(); duk_fb_sprintf(fb, "__length_nonwritable:%ld", (long) a->length_nonwritable);
42437 	} else if (st->internal && DUK_HOBJECT_IS_COMPFUNC(h)) {
42438 		duk_hcompfunc *f = (duk_hcompfunc *) h;
42439 		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
42440 		duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
42441 		DUK__COMMA(); duk_fb_put_cstring(fb, "__lexenv:"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_LEXENV(NULL, f));
42442 		DUK__COMMA(); duk_fb_put_cstring(fb, "__varenv:"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_VARENV(NULL, f));
42443 		DUK__COMMA(); duk_fb_sprintf(fb, "__nregs:%ld", (long) f->nregs);
42444 		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
42445 #if defined(DUK_USE_DEBUGGER_SUPPORT)
42446 		DUK__COMMA(); duk_fb_sprintf(fb, "__start_line:%ld", (long) f->start_line);
42447 		DUK__COMMA(); duk_fb_sprintf(fb, "__end_line:%ld", (long) f->end_line);
42448 #endif
42449 		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
42450 		duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
42451 	} else if (st->internal && DUK_HOBJECT_IS_NATFUNC(h)) {
42452 		duk_hnatfunc *f = (duk_hnatfunc *) h;
42453 		DUK__COMMA(); duk_fb_sprintf(fb, "__func:");
42454 		duk_fb_put_funcptr(fb, (duk_uint8_t *) &f->func, sizeof(f->func));
42455 		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
42456 		DUK__COMMA(); duk_fb_sprintf(fb, "__magic:%ld", (long) f->magic);
42457 	} else if (st->internal && DUK_HOBJECT_IS_DECENV(h)) {
42458 		duk_hdecenv *e = (duk_hdecenv *) h;
42459 		DUK__COMMA(); duk_fb_sprintf(fb, "__thread:"); duk__print_hobject(st, (duk_hobject *) e->thread);
42460 		DUK__COMMA(); duk_fb_sprintf(fb, "__varmap:"); duk__print_hobject(st, (duk_hobject *) e->varmap);
42461 		DUK__COMMA(); duk_fb_sprintf(fb, "__regbase_byteoff:%ld", (long) e->regbase_byteoff);
42462 	} else if (st->internal && DUK_HOBJECT_IS_OBJENV(h)) {
42463 		duk_hobjenv *e = (duk_hobjenv *) h;
42464 		DUK__COMMA(); duk_fb_sprintf(fb, "__target:"); duk__print_hobject(st, (duk_hobject *) e->target);
42465 		DUK__COMMA(); duk_fb_sprintf(fb, "__has_this:%ld", (long) e->has_this);
42466 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
42467 	} else if (st->internal && DUK_HOBJECT_IS_BUFOBJ(h)) {
42468 		duk_hbufobj *b = (duk_hbufobj *) h;
42469 		DUK__COMMA(); duk_fb_sprintf(fb, "__buf:");
42470 		duk__print_hbuffer(st, (duk_hbuffer *) b->buf);
42471 		DUK__COMMA(); duk_fb_sprintf(fb, "__buf_prop:");
42472 		duk__print_hobject(st, (duk_hobject *) b->buf_prop);
42473 		DUK__COMMA(); duk_fb_sprintf(fb, "__offset:%ld", (long) b->offset);
42474 		DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) b->length);
42475 		DUK__COMMA(); duk_fb_sprintf(fb, "__shift:%ld", (long) b->shift);
42476 		DUK__COMMA(); duk_fb_sprintf(fb, "__elemtype:%ld", (long) b->elem_type);
42477 #endif
42478 	} else if (st->internal && DUK_HOBJECT_IS_PROXY(h)) {
42479 		duk_hproxy *p = (duk_hproxy *) h;
42480 		DUK__COMMA(); duk_fb_sprintf(fb, "__target:");
42481 		duk__print_hobject(st, p->target);
42482 		DUK__COMMA(); duk_fb_sprintf(fb, "__handler:");
42483 		duk__print_hobject(st, p->handler);
42484 	} else if (st->internal && DUK_HOBJECT_IS_THREAD(h)) {
42485 		duk_hthread *t = (duk_hthread *) h;
42486 		DUK__COMMA(); duk_fb_sprintf(fb, "__ptr_curr_pc:%p", (void *) t->ptr_curr_pc);
42487 		DUK__COMMA(); duk_fb_sprintf(fb, "__heap:%p", (void *) t->heap);
42488 		DUK__COMMA(); duk_fb_sprintf(fb, "__strict:%ld", (long) t->strict);
42489 		DUK__COMMA(); duk_fb_sprintf(fb, "__state:%ld", (long) t->state);
42490 		DUK__COMMA(); duk_fb_sprintf(fb, "__unused1:%ld", (long) t->unused1);
42491 		DUK__COMMA(); duk_fb_sprintf(fb, "__unused2:%ld", (long) t->unused2);
42492 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack:%p", (void *) t->valstack);
42493 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_end:%p/%ld", (void *) t->valstack_end, (long) (t->valstack_end - t->valstack));
42494 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_alloc_end:%p/%ld", (void *) t->valstack_alloc_end, (long) (t->valstack_alloc_end - t->valstack));
42495 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_bottom:%p/%ld", (void *) t->valstack_bottom, (long) (t->valstack_bottom - t->valstack));
42496 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_top:%p/%ld", (void *) t->valstack_top, (long) (t->valstack_top - t->valstack));
42497 		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_curr:%p", (void *) t->callstack_curr);
42498 		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_top:%ld", (long) t->callstack_top);
42499 		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_preventcount:%ld", (long) t->callstack_preventcount);
42500 		DUK__COMMA(); duk_fb_sprintf(fb, "__resumer:"); duk__print_hobject(st, (duk_hobject *) t->resumer);
42501 		DUK__COMMA(); duk_fb_sprintf(fb, "__compile_ctx:%p", (void *) t->compile_ctx);
42502 #if defined(DUK_USE_INTERRUPT_COUNTER)
42503 		DUK__COMMA(); duk_fb_sprintf(fb, "__interrupt_counter:%ld", (long) t->interrupt_counter);
42504 		DUK__COMMA(); duk_fb_sprintf(fb, "__interrupt_init:%ld", (long) t->interrupt_init);
42505 #endif
42506 
42507 		/* XXX: print built-ins array? */
42508 
42509 	}
42510 #if defined(DUK_USE_REFERENCE_COUNTING)
42511 	if (st->internal) {
42512 		DUK__COMMA(); duk_fb_sprintf(fb, "__refcount:%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h));
42513 	}
42514 #endif
42515 	if (st->internal) {
42516 		DUK__COMMA(); duk_fb_sprintf(fb, "__class:%ld", (long) DUK_HOBJECT_GET_CLASS_NUMBER(h));
42517 	}
42518 
42519 	DUK__COMMA(); duk_fb_sprintf(fb, "__heapptr:%p", (void *) h);  /* own pointer */
42520 
42521 	/* prototype should be last, for readability */
42522 	if (DUK_HOBJECT_GET_PROTOTYPE(NULL, h)) {
42523 		if (st->follow_proto) {
42524 			DUK__COMMA(); duk_fb_put_cstring(fb, "__prototype:"); duk__print_hobject(st, DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
42525 		} else {
42526 			DUK__COMMA(); duk_fb_sprintf(fb, "__prototype:%p", (void *) DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
42527 		}
42528 	}
42529 
42530 	duk_fb_put_cstring(fb, brace2);
42531 
42532 #if defined(DUK_USE_HOBJECT_HASH_PART)
42533 	if (st->heavy && DUK_HOBJECT_GET_HSIZE(h) > 0) {
42534 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
42535 		for (i = 0; i < DUK_HOBJECT_GET_HSIZE(h); i++) {
42536 			duk_uint_t h_idx = DUK_HOBJECT_H_GET_INDEX(NULL, h, i);
42537 			if (i > 0) {
42538 				duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA);
42539 			}
42540 			if (h_idx == DUK_HOBJECT_HASHIDX_UNUSED) {
42541 				duk_fb_sprintf(fb, "u");
42542 			} else if (h_idx == DUK_HOBJECT_HASHIDX_DELETED) {
42543 				duk_fb_sprintf(fb, "d");
42544 			} else {
42545 				duk_fb_sprintf(fb, "%ld", (long) h_idx);
42546 			}
42547 		}
42548 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
42549 	}
42550 #endif
42551 
42552  finished:
42553 	st->depth--;
42554 	if (pushed_loopstack) {
42555 		st->loop_stack_index--;
42556 		st->loop_stack[st->loop_stack_index] = NULL;
42557 	}
42558 }
42559 
42560 DUK_LOCAL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h) {
42561 	duk_fixedbuffer *fb = st->fb;
42562 	duk_size_t i, n;
42563 	duk_uint8_t *p;
42564 
42565 	if (duk_fb_is_full(fb)) {
42566 		return;
42567 	}
42568 
42569 	/* terminal type: no depth check */
42570 
42571 	if (!h) {
42572 		duk_fb_put_cstring(fb, "NULL");
42573 		return;
42574 	}
42575 
42576 	if (DUK_HBUFFER_HAS_DYNAMIC(h)) {
42577 		if (DUK_HBUFFER_HAS_EXTERNAL(h)) {
42578 			duk_hbuffer_external *g = (duk_hbuffer_external *) h;
42579 			duk_fb_sprintf(fb, "buffer:external:%p:%ld",
42580 			               (void *) DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(NULL, g),
42581 			               (long) DUK_HBUFFER_EXTERNAL_GET_SIZE(g));
42582 		} else {
42583 			duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
42584 			duk_fb_sprintf(fb, "buffer:dynamic:%p:%ld",
42585 			               (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(NULL, g),
42586 			               (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(g));
42587 		}
42588 	} else {
42589 		duk_fb_sprintf(fb, "buffer:fixed:%ld", (long) DUK_HBUFFER_GET_SIZE(h));
42590 	}
42591 
42592 #if defined(DUK_USE_REFERENCE_COUNTING)
42593 	duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
42594 #endif
42595 
42596 	if (st->hexdump) {
42597 		duk_fb_sprintf(fb, "=[");
42598 		n = DUK_HBUFFER_GET_SIZE(h);
42599 		p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(NULL, h);
42600 		for (i = 0; i < n; i++) {
42601 			duk_fb_sprintf(fb, "%02lx", (unsigned long) p[i]);
42602 		}
42603 		duk_fb_sprintf(fb, "]");
42604 	}
42605 }
42606 
42607 DUK_LOCAL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
42608 	duk_fixedbuffer *fb = st->fb;
42609 
42610 	if (duk_fb_is_full(fb)) {
42611 		return;
42612 	}
42613 
42614 	if (!h) {
42615 		duk_fb_put_cstring(fb, "NULL");
42616 		return;
42617 	}
42618 
42619 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
42620 	case DUK_HTYPE_STRING:
42621 		duk__print_hstring(st, (duk_hstring *) h, 1);
42622 		break;
42623 	case DUK_HTYPE_OBJECT:
42624 		duk__print_hobject(st, (duk_hobject *) h);
42625 		break;
42626 	case DUK_HTYPE_BUFFER:
42627 		duk__print_hbuffer(st, (duk_hbuffer *) h);
42628 		break;
42629 	default:
42630 		duk_fb_sprintf(fb, "[unknown htype %ld]", (long) DUK_HEAPHDR_GET_TYPE(h));
42631 		break;
42632 	}
42633 }
42634 
42635 DUK_LOCAL void duk__print_tval(duk__dprint_state *st, duk_tval *tv) {
42636 	duk_fixedbuffer *fb = st->fb;
42637 
42638 	if (duk_fb_is_full(fb)) {
42639 		return;
42640 	}
42641 
42642 	/* depth check is done when printing an actual type */
42643 
42644 	if (st->heavy) {
42645 		duk_fb_sprintf(fb, "(%p)", (void *) tv);
42646 	}
42647 
42648 	if (!tv) {
42649 		duk_fb_put_cstring(fb, "NULL");
42650 		return;
42651 	}
42652 
42653 	if (st->binary) {
42654 		duk_size_t i;
42655 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
42656 		for (i = 0; i < (duk_size_t) sizeof(*tv); i++) {
42657 			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)tv)[i]);
42658 		}
42659 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
42660 	}
42661 
42662 	if (st->heavy) {
42663 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
42664 	}
42665 	switch (DUK_TVAL_GET_TAG(tv)) {
42666 	case DUK_TAG_UNDEFINED: {
42667 		duk_fb_put_cstring(fb, "undefined");
42668 		break;
42669 	}
42670 	case DUK_TAG_UNUSED: {
42671 		duk_fb_put_cstring(fb, "unused");
42672 		break;
42673 	}
42674 	case DUK_TAG_NULL: {
42675 		duk_fb_put_cstring(fb, "null");
42676 		break;
42677 	}
42678 	case DUK_TAG_BOOLEAN: {
42679 		duk_fb_put_cstring(fb, DUK_TVAL_GET_BOOLEAN(tv) ? "true" : "false");
42680 		break;
42681 	}
42682 	case DUK_TAG_STRING: {
42683 		/* Note: string is a terminal heap object, so no depth check here */
42684 		duk__print_hstring(st, DUK_TVAL_GET_STRING(tv), 1);
42685 		break;
42686 	}
42687 	case DUK_TAG_OBJECT: {
42688 		duk__print_hobject(st, DUK_TVAL_GET_OBJECT(tv));
42689 		break;
42690 	}
42691 	case DUK_TAG_BUFFER: {
42692 		duk__print_hbuffer(st, DUK_TVAL_GET_BUFFER(tv));
42693 		break;
42694 	}
42695 	case DUK_TAG_POINTER: {
42696 		duk_fb_sprintf(fb, "pointer:%p", (void *) DUK_TVAL_GET_POINTER(tv));
42697 		break;
42698 	}
42699 	case DUK_TAG_LIGHTFUNC: {
42700 		duk_c_function func;
42701 		duk_small_uint_t lf_flags;
42702 
42703 		DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
42704 		duk_fb_sprintf(fb, "lightfunc:");
42705 		duk_fb_put_funcptr(fb, (duk_uint8_t *) &func, sizeof(func));
42706 		duk_fb_sprintf(fb, ":%04lx", (long) lf_flags);
42707 		break;
42708 	}
42709 #if defined(DUK_USE_FASTINT)
42710 	case DUK_TAG_FASTINT:
42711 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
42712 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
42713 		duk_fb_sprintf(fb, "%.18g_F", (double) DUK_TVAL_GET_NUMBER(tv));
42714 		break;
42715 #endif
42716 	default: {
42717 		/* IEEE double is approximately 16 decimal digits; print a couple extra */
42718 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
42719 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
42720 		duk_fb_sprintf(fb, "%.18g", (double) DUK_TVAL_GET_NUMBER(tv));
42721 		break;
42722 	}
42723 	}
42724 	if (st->heavy) {
42725 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
42726 	}
42727 }
42728 
42729 DUK_LOCAL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins) {
42730 	duk_fixedbuffer *fb = st->fb;
42731 	duk_small_int_t op;
42732 	const char *op_name;
42733 
42734 	op = (duk_small_int_t) DUK_DEC_OP(ins);
42735 	op_name = duk__bc_optab[op];
42736 
42737 	/* XXX: option to fix opcode length so it lines up nicely */
42738 
42739 	if (op == DUK_OP_JUMP) {
42740 		duk_int_t diff1 = (duk_int_t) (DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS);  /* from next pc */
42741 		duk_int_t diff2 = diff1 + 1;                                          /* from curr pc */
42742 
42743 		duk_fb_sprintf(fb, "%s %ld (to pc%c%ld)",
42744 		               (const char *) op_name, (long) diff1,
42745 		               (int) (diff2 >= 0 ? '+' : '-'),  /* char format: use int */
42746 		               (long) (diff2 >= 0 ? diff2 : -diff2));
42747 	} else {
42748 		duk_fb_sprintf(fb, "%s %ld, %ld, %ld",
42749 		               (const char *) op_name, (long) DUK_DEC_A(ins),
42750 		               (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));
42751 	}
42752 }
42753 
42754 DUK_LOCAL void duk__print_opcode(duk__dprint_state *st, duk_small_int_t opcode) {
42755 	duk_fixedbuffer *fb = st->fb;
42756 
42757 	if (opcode < DUK_BC_OP_MIN || opcode > DUK_BC_OP_MAX) {
42758 		duk_fb_sprintf(fb, "?(%ld)", (long) opcode);
42759 	} else {
42760 		duk_fb_sprintf(fb, "%s", (const char *) duk__bc_optab[opcode]);
42761 	}
42762 }
42763 
42764 DUK_LOCAL void duk__print_catcher(duk__dprint_state *st, duk_catcher *cat) {
42765 	duk_fixedbuffer *fb = st->fb;
42766 
42767 	if (duk_fb_is_full(fb)) {
42768 		return;
42769 	}
42770 
42771 	if (!cat) {
42772 		duk_fb_put_cstring(fb, "NULL");
42773 		return;
42774 	}
42775 
42776 	duk_fb_sprintf(fb, "[catcher ptr=%p parent=%p varname=%p pc_base=%p, idx_base=%ld, flags=0x%08lx]",
42777 	               (void *) cat,
42778 	               (void *) cat->parent, (void *) cat->h_varname, (void *) cat->pc_base,
42779 		       (long) cat->idx_base, (unsigned long) cat->flags);
42780 }
42781 
42782 
42783 DUK_LOCAL void duk__print_activation(duk__dprint_state *st, duk_activation *act) {
42784 	duk_fixedbuffer *fb = st->fb;
42785 
42786 	if (duk_fb_is_full(fb)) {
42787 		return;
42788 	}
42789 
42790 	if (!act) {
42791 		duk_fb_put_cstring(fb, "NULL");
42792 		return;
42793 	}
42794 
42795 	/* prev_caller: conditional, omitted on purpose, it's rarely used. */
42796 	/* prev_line: conditional, omitted on purpose (but would be nice). */
42797 	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]",
42798 	               (void *) act,
42799 	               (void *) act->func, (void *) act->parent, (void *) act->var_env,
42800 		       (void *) act->lex_env, (void *) act->cat, (void *) act->curr_pc,
42801 		       (long) act->bottom_byteoff, (long) act->retval_byteoff, (long) act->reserve_byteoff,
42802 		       (long) act->flags);
42803 }
42804 
42805 DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap) {
42806 	duk_fixedbuffer fb;
42807 	const char *p = format;
42808 	const char *p_end = p + DUK_STRLEN(format);
42809 	duk_int_t retval;
42810 
42811 	duk_memzero(&fb, sizeof(fb));
42812 	fb.buffer = (duk_uint8_t *) str;
42813 	fb.length = size;
42814 	fb.offset = 0;
42815 	fb.truncated = 0;
42816 
42817 	while (p < p_end) {
42818 		char ch = *p++;
42819 		const char *p_begfmt = NULL;
42820 		duk_bool_t got_exclamation = 0;
42821 		duk_bool_t got_long = 0;  /* %lf, %ld etc */
42822 		duk__dprint_state st;
42823 
42824 		if (ch != DUK_ASC_PERCENT) {
42825 			duk_fb_put_byte(&fb, (duk_uint8_t) ch);
42826 			continue;
42827 		}
42828 
42829 		/*
42830 		 *  Format tag parsing.  Since we don't understand all the
42831 		 *  possible format tags allowed, we just scan for a terminating
42832 		 *  specifier and keep track of relevant modifiers that we do
42833 		 *  understand.  See man 3 printf.
42834 		 */
42835 
42836 		duk_memzero(&st, sizeof(st));
42837 		st.fb = &fb;
42838 		st.depth = 0;
42839 		st.depth_limit = 1;
42840 		st.loop_stack_index = 0;
42841 		st.loop_stack_limit = DUK__LOOP_STACK_DEPTH;
42842 
42843 		p_begfmt = p - 1;
42844 		while (p < p_end) {
42845 			ch = *p++;
42846 
42847 			if (ch == DUK_ASC_STAR) {
42848 				/* unsupported: would consume multiple args */
42849 				goto format_error;
42850 			} else if (ch == DUK_ASC_PERCENT) {
42851 				duk_fb_put_byte(&fb, (duk_uint8_t) DUK_ASC_PERCENT);
42852 				break;
42853 			} else if (ch == DUK_ASC_EXCLAMATION) {
42854 				got_exclamation = 1;
42855 			} else if (!got_exclamation && ch == DUK_ASC_LC_L) {
42856 				got_long = 1;
42857 			} else if (got_exclamation && ch == DUK_ASC_LC_D) {
42858 				st.depth_limit = DUK__DEEP_DEPTH_LIMIT;
42859 			} else if (got_exclamation && ch == DUK_ASC_LC_P) {
42860 				st.follow_proto = 1;
42861 			} else if (got_exclamation && ch == DUK_ASC_LC_I) {
42862 				st.internal = 1;
42863 			} else if (got_exclamation && ch == DUK_ASC_LC_X) {
42864 				st.hexdump = 1;
42865 			} else if (got_exclamation && ch == DUK_ASC_LC_H) {
42866 				st.heavy = 1;
42867 			} else if (got_exclamation && ch == DUK_ASC_ATSIGN) {
42868 				st.pointer = 1;
42869 			} else if (got_exclamation && ch == DUK_ASC_HASH) {
42870 				st.binary = 1;
42871 			} else if (got_exclamation && ch == DUK_ASC_UC_T) {
42872 				duk_tval *t = va_arg(ap, duk_tval *);
42873 				if (st.pointer && !st.heavy) {
42874 					duk_fb_sprintf(&fb, "(%p)", (void *) t);
42875 				}
42876 				duk__print_tval(&st, t);
42877 				break;
42878 			} else if (got_exclamation && ch == DUK_ASC_UC_O) {
42879 				duk_heaphdr *t = va_arg(ap, duk_heaphdr *);
42880 				if (st.pointer && !st.heavy) {
42881 					duk_fb_sprintf(&fb, "(%p)", (void *) t);
42882 				}
42883 				duk__print_heaphdr(&st, t);
42884 				break;
42885 			} else if (got_exclamation && ch == DUK_ASC_UC_I) {
42886 				duk_instr_t t = va_arg(ap, duk_instr_t);
42887 				duk__print_instr(&st, t);
42888 				break;
42889 			} else if (got_exclamation && ch == DUK_ASC_UC_X) {
42890 				long t = va_arg(ap, long);
42891 				duk__print_opcode(&st, (duk_small_int_t) t);
42892 				break;
42893 			} else if (got_exclamation && ch == DUK_ASC_UC_C) {
42894 				duk_catcher *t = va_arg(ap, duk_catcher *);
42895 				duk__print_catcher(&st, t);
42896 				break;
42897 			} else if (got_exclamation && ch == DUK_ASC_UC_A) {
42898 				duk_activation *t = va_arg(ap, duk_activation *);
42899 				duk__print_activation(&st, t);
42900 				break;
42901 			} else if (!got_exclamation && strchr(DUK__ALLOWED_STANDARD_SPECIFIERS, (int) ch)) {
42902 				char fmtbuf[DUK__MAX_FORMAT_TAG_LENGTH];
42903 				duk_size_t fmtlen;
42904 
42905 				DUK_ASSERT(p >= p_begfmt);
42906 				fmtlen = (duk_size_t) (p - p_begfmt);
42907 				if (fmtlen >= sizeof(fmtbuf)) {
42908 					/* format is too large, abort */
42909 					goto format_error;
42910 				}
42911 				duk_memzero(fmtbuf, sizeof(fmtbuf));
42912 				duk_memcpy(fmtbuf, p_begfmt, fmtlen);
42913 
42914 				/* assume exactly 1 arg, which is why '*' is forbidden; arg size still
42915 				 * depends on type though.
42916 				 */
42917 
42918 				if (ch == DUK_ASC_LC_F || ch == DUK_ASC_LC_G || ch == DUK_ASC_LC_E) {
42919 					/* %f and %lf both consume a 'long' */
42920 					double arg = va_arg(ap, double);
42921 					duk_fb_sprintf(&fb, fmtbuf, arg);
42922 				} else if (ch == DUK_ASC_LC_D && got_long) {
42923 					/* %ld */
42924 					long arg = va_arg(ap, long);
42925 					duk_fb_sprintf(&fb, fmtbuf, arg);
42926 				} else if (ch == DUK_ASC_LC_D) {
42927 					/* %d; only 16 bits are guaranteed */
42928 					int arg = va_arg(ap, int);
42929 					duk_fb_sprintf(&fb, fmtbuf, arg);
42930 				} else if (ch == DUK_ASC_LC_U && got_long) {
42931 					/* %lu */
42932 					unsigned long arg = va_arg(ap, unsigned long);
42933 					duk_fb_sprintf(&fb, fmtbuf, arg);
42934 				} else if (ch == DUK_ASC_LC_U) {
42935 					/* %u; only 16 bits are guaranteed */
42936 					unsigned int arg = va_arg(ap, unsigned int);
42937 					duk_fb_sprintf(&fb, fmtbuf, arg);
42938 				} else if (ch == DUK_ASC_LC_X && got_long) {
42939 					/* %lx */
42940 					unsigned long arg = va_arg(ap, unsigned long);
42941 					duk_fb_sprintf(&fb, fmtbuf, arg);
42942 				} else if (ch == DUK_ASC_LC_X) {
42943 					/* %x; only 16 bits are guaranteed */
42944 					unsigned int arg = va_arg(ap, unsigned int);
42945 					duk_fb_sprintf(&fb, fmtbuf, arg);
42946 				} else if (ch == DUK_ASC_LC_S) {
42947 					/* %s */
42948 					const char *arg = va_arg(ap, const char *);
42949 					if (arg == NULL) {
42950 						/* '%s' and NULL is not portable, so special case
42951 						 * it for debug printing.
42952 						 */
42953 						duk_fb_sprintf(&fb, "NULL");
42954 					} else {
42955 						duk_fb_sprintf(&fb, fmtbuf, arg);
42956 					}
42957 				} else if (ch == DUK_ASC_LC_P) {
42958 					/* %p */
42959 					void *arg = va_arg(ap, void *);
42960 					if (arg == NULL) {
42961 						/* '%p' and NULL is portable, but special case it
42962 						 * anyway to get a standard NULL marker in logs.
42963 						 */
42964 						duk_fb_sprintf(&fb, "NULL");
42965 					} else {
42966 						duk_fb_sprintf(&fb, fmtbuf, arg);
42967 					}
42968 				} else if (ch == DUK_ASC_LC_C) {
42969 					/* '%c', passed concretely as int */
42970 					int arg = va_arg(ap, int);
42971 					duk_fb_sprintf(&fb, fmtbuf, arg);
42972 				} else {
42973 					/* Should not happen. */
42974 					duk_fb_sprintf(&fb, "INVALID-FORMAT(%s)", (const char *) fmtbuf);
42975 				}
42976 				break;
42977 			} else {
42978 				/* ignore */
42979 			}
42980 		}
42981 	}
42982 	goto done;
42983 
42984  format_error:
42985 	duk_fb_put_cstring(&fb, "FMTERR");
42986 	/* fall through */
42987 
42988  done:
42989 	retval = (duk_int_t) fb.offset;
42990 	duk_fb_put_byte(&fb, (duk_uint8_t) 0);
42991 
42992 	/* return total chars written excluding terminator */
42993 	return retval;
42994 }
42995 
42996 #if 0  /*unused*/
42997 DUK_INTERNAL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...) {
42998 	duk_int_t retval;
42999 	va_list ap;
43000 	va_start(ap, format);
43001 	retval = duk_debug_vsnprintf(str, size, format, ap);
43002 	va_end(ap);
43003 	return retval;
43004 }
43005 #endif
43006 
43007 /* Formatting function pointers is tricky: there is no standard pointer for
43008  * function pointers and the size of a function pointer may depend on the
43009  * specific pointer type.  This helper formats a function pointer based on
43010  * its memory layout to get something useful on most platforms.
43011  */
43012 DUK_INTERNAL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size) {
43013 	duk_size_t i;
43014 	duk_uint8_t *p = (duk_uint8_t *) buf;
43015 	duk_uint8_t *p_end = (duk_uint8_t *) (buf + buf_size - 1);
43016 
43017 	DUK_ASSERT(buf != NULL);
43018 	duk_memzero(buf, buf_size);
43019 
43020 	for (i = 0; i < fptr_size; i++) {
43021 		duk_int_t left = (duk_int_t) (p_end - p);
43022 		duk_uint8_t ch;
43023 		if (left <= 0) {
43024 			break;
43025 		}
43026 
43027 		/* Quite approximate but should be useful for little and big endian. */
43028 #if defined(DUK_USE_INTEGER_BE)
43029 		ch = fptr[i];
43030 #else
43031 		ch = fptr[fptr_size - 1 - i];
43032 #endif
43033 		p += DUK_SNPRINTF((char *) p, (duk_size_t) left, "%02lx", (unsigned long) ch);
43034 	}
43035 }
43036 
43037 #endif  /* DUK_USE_DEBUG */
43038 
43039 /* automatic undefs */
43040 #undef DUK__ALLOWED_STANDARD_SPECIFIERS
43041 #undef DUK__COMMA
43042 #undef DUK__DEEP_DEPTH_LIMIT
43043 #undef DUK__LOOP_STACK_DEPTH
43044 #undef DUK__MAX_FORMAT_TAG_LENGTH
43045 /*
43046  *  Duktape debugger
43047  */
43048 
43049 /* #include duk_internal.h -> already included */
43050 
43051 #if defined(DUK_USE_DEBUGGER_SUPPORT)
43052 
43053 /*
43054  *  Assert helpers
43055  */
43056 
43057 #if defined(DUK_USE_ASSERTIONS)
43058 #define DUK__DBG_TPORT_ENTER() do { \
43059 		DUK_ASSERT(heap->dbg_calling_transport == 0); \
43060 		heap->dbg_calling_transport = 1; \
43061 	} while (0)
43062 #define DUK__DBG_TPORT_EXIT() do { \
43063 		DUK_ASSERT(heap->dbg_calling_transport == 1); \
43064 		heap->dbg_calling_transport = 0; \
43065 	} while (0)
43066 #else
43067 #define DUK__DBG_TPORT_ENTER() do {} while (0)
43068 #define DUK__DBG_TPORT_EXIT() do {} while (0)
43069 #endif
43070 
43071 /*
43072  *  Helper structs
43073  */
43074 
43075 typedef union {
43076 	void *p;
43077 	duk_uint_t b[1];
43078 	/* Use b[] to access the size of the union, which is strictly not
43079 	 * correct.  Can't use fixed size unless there's feature detection
43080 	 * for pointer byte size.
43081 	 */
43082 } duk__ptr_union;
43083 
43084 /*
43085  *  Detach handling
43086  */
43087 
43088 #define DUK__SET_CONN_BROKEN(thr,reason) do { \
43089 		/* For now shared handler is fine. */ \
43090 		duk__debug_do_detach1((thr)->heap, (reason)); \
43091 	} while (0)
43092 
43093 DUK_LOCAL void duk__debug_do_detach1(duk_heap *heap, duk_int_t reason) {
43094 	/* Can be called multiple times with no harm.  Mark the transport
43095 	 * bad (dbg_read_cb == NULL) and clear state except for the detached
43096 	 * callback and the udata field.  The detached callback is delayed
43097 	 * to the message loop so that it can be called between messages;
43098 	 * this avoids corner cases related to immediate debugger reattach
43099 	 * inside the detached callback.
43100 	 */
43101 
43102 	if (heap->dbg_detaching) {
43103 		DUK_D(DUK_DPRINT("debugger already detaching, ignore detach1"));
43104 		return;
43105 	}
43106 
43107 	DUK_D(DUK_DPRINT("debugger transport detaching, marking transport broken"));
43108 
43109 	heap->dbg_detaching = 1;  /* prevent multiple in-progress detaches */
43110 
43111 	if (heap->dbg_write_cb != NULL) {
43112 		duk_hthread *thr;
43113 
43114 		thr = heap->heap_thread;
43115 		DUK_ASSERT(thr != NULL);
43116 
43117 		duk_debug_write_notify(thr, DUK_DBG_CMD_DETACHING);
43118 		duk_debug_write_int(thr, reason);
43119 		duk_debug_write_eom(thr);
43120 	}
43121 
43122 	heap->dbg_read_cb = NULL;
43123 	heap->dbg_write_cb = NULL;
43124 	heap->dbg_peek_cb = NULL;
43125 	heap->dbg_read_flush_cb = NULL;
43126 	heap->dbg_write_flush_cb = NULL;
43127 	heap->dbg_request_cb = NULL;
43128 	/* heap->dbg_detached_cb: keep */
43129 	/* heap->dbg_udata: keep */
43130 	/* heap->dbg_processing: keep on purpose to avoid debugger re-entry in detaching state */
43131 	heap->dbg_state_dirty = 0;
43132 	heap->dbg_force_restart = 0;
43133 	heap->dbg_pause_flags = 0;
43134 	heap->dbg_pause_act = NULL;
43135 	heap->dbg_pause_startline = 0;
43136 	heap->dbg_have_next_byte = 0;
43137 	duk_debug_clear_paused(heap);  /* XXX: some overlap with field inits above */
43138 	heap->dbg_state_dirty = 0;     /* XXX: clear_paused sets dirty; rework? */
43139 
43140 	/* Ensure there are no stale active breakpoint pointers.
43141 	 * Breakpoint list is currently kept - we could empty it
43142 	 * here but we'd need to handle refcounts correctly, and
43143 	 * we'd need a 'thr' reference for that.
43144 	 *
43145 	 * XXX: clear breakpoint on either attach or detach?
43146 	 */
43147 	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
43148 }
43149 
43150 DUK_LOCAL void duk__debug_do_detach2(duk_heap *heap) {
43151 	duk_debug_detached_function detached_cb;
43152 	void *detached_udata;
43153 	duk_hthread *thr;
43154 
43155 	thr = heap->heap_thread;
43156 	if (thr == NULL) {
43157 		DUK_ASSERT(heap->dbg_detached_cb == NULL);
43158 		return;
43159 	}
43160 
43161 	/* Safe to call multiple times. */
43162 
43163 	detached_cb = heap->dbg_detached_cb;
43164 	detached_udata = heap->dbg_udata;
43165 	heap->dbg_detached_cb = NULL;
43166 	heap->dbg_udata = NULL;
43167 
43168 	if (detached_cb) {
43169 		/* Careful here: state must be wiped before the call
43170 		 * so that we can cleanly handle a re-attach from
43171 		 * inside the callback.
43172 		 */
43173 		DUK_D(DUK_DPRINT("detached during message loop, delayed call to detached_cb"));
43174 		detached_cb(thr, detached_udata);
43175 	}
43176 
43177 	heap->dbg_detaching = 0;
43178 }
43179 
43180 DUK_INTERNAL void duk_debug_do_detach(duk_heap *heap) {
43181 	duk__debug_do_detach1(heap, 0);
43182 	duk__debug_do_detach2(heap);
43183 }
43184 
43185 /* Called on a read/write error: NULL all callbacks except the detached
43186  * callback so that we never accidentally call them after a read/write
43187  * error has been indicated.  This is especially important for the transport
43188  * I/O callbacks to fulfill guaranteed callback semantics.
43189  */
43190 DUK_LOCAL void duk__debug_null_most_callbacks(duk_hthread *thr) {
43191 	duk_heap *heap;
43192 
43193 	DUK_ASSERT(thr != NULL);
43194 
43195 	heap = thr->heap;
43196 	DUK_D(DUK_DPRINT("transport read/write error, NULL all callbacks expected detached"));
43197 	heap->dbg_read_cb = NULL;
43198 	heap->dbg_write_cb = NULL;  /* this is especially critical to avoid another write call in detach1() */
43199 	heap->dbg_peek_cb = NULL;
43200 	heap->dbg_read_flush_cb = NULL;
43201 	heap->dbg_write_flush_cb = NULL;
43202 	heap->dbg_request_cb = NULL;
43203 	/* keep heap->dbg_detached_cb */
43204 }
43205 
43206 /*
43207  *  Pause handling
43208  */
43209 
43210 DUK_LOCAL void duk__debug_set_pause_state(duk_hthread *thr, duk_heap *heap, duk_small_uint_t pause_flags) {
43211 	duk_uint_fast32_t line;
43212 
43213 	line = duk_debug_curr_line(thr);
43214 	if (line == 0) {
43215 		/* No line info for current function. */
43216 		duk_small_uint_t updated_flags;
43217 
43218 		updated_flags = pause_flags & ~(DUK_PAUSE_FLAG_LINE_CHANGE);
43219 		DUK_D(DUK_DPRINT("no line info for current activation, disable line-based pause flags: 0x%08lx -> 0x%08lx",
43220 		                 (long) pause_flags, (long) updated_flags));
43221 		pause_flags = updated_flags;
43222 	}
43223 
43224 	heap->dbg_pause_flags = pause_flags;
43225 	heap->dbg_pause_act = thr->callstack_curr;
43226 	heap->dbg_pause_startline = (duk_uint32_t) line;
43227 	heap->dbg_state_dirty = 1;
43228 
43229 	DUK_D(DUK_DPRINT("set state for automatic pause triggers, flags=0x%08lx, act=%p, startline=%ld",
43230 	                 (long) heap->dbg_pause_flags, (void *) heap->dbg_pause_act,
43231 	                 (long) heap->dbg_pause_startline));
43232 }
43233 
43234 /*
43235  *  Debug connection peek and flush primitives
43236  */
43237 
43238 DUK_INTERNAL duk_bool_t duk_debug_read_peek(duk_hthread *thr) {
43239 	duk_heap *heap;
43240 	duk_bool_t ret;
43241 
43242 	DUK_ASSERT(thr != NULL);
43243 	heap = thr->heap;
43244 	DUK_ASSERT(heap != NULL);
43245 
43246 	if (heap->dbg_read_cb == NULL) {
43247 		DUK_D(DUK_DPRINT("attempt to peek in detached state, return zero (= no data)"));
43248 		return 0;
43249 	}
43250 	if (heap->dbg_peek_cb == NULL) {
43251 		DUK_DD(DUK_DDPRINT("no peek callback, return zero (= no data)"));
43252 		return 0;
43253 	}
43254 
43255 	DUK__DBG_TPORT_ENTER();
43256 	ret = (duk_bool_t) (heap->dbg_peek_cb(heap->dbg_udata) > 0);
43257 	DUK__DBG_TPORT_EXIT();
43258 	return ret;
43259 }
43260 
43261 DUK_INTERNAL void duk_debug_read_flush(duk_hthread *thr) {
43262 	duk_heap *heap;
43263 
43264 	DUK_ASSERT(thr != NULL);
43265 	heap = thr->heap;
43266 	DUK_ASSERT(heap != NULL);
43267 
43268 	if (heap->dbg_read_cb == NULL) {
43269 		DUK_D(DUK_DPRINT("attempt to read flush in detached state, ignore"));
43270 		return;
43271 	}
43272 	if (heap->dbg_read_flush_cb == NULL) {
43273 		DUK_DD(DUK_DDPRINT("no read flush callback, ignore"));
43274 		return;
43275 	}
43276 
43277 	DUK__DBG_TPORT_ENTER();
43278 	heap->dbg_read_flush_cb(heap->dbg_udata);
43279 	DUK__DBG_TPORT_EXIT();
43280 }
43281 
43282 DUK_INTERNAL void duk_debug_write_flush(duk_hthread *thr) {
43283 	duk_heap *heap;
43284 
43285 	DUK_ASSERT(thr != NULL);
43286 	heap = thr->heap;
43287 	DUK_ASSERT(heap != NULL);
43288 
43289 	if (heap->dbg_read_cb == NULL) {
43290 		DUK_D(DUK_DPRINT("attempt to write flush in detached state, ignore"));
43291 		return;
43292 	}
43293 	if (heap->dbg_write_flush_cb == NULL) {
43294 		DUK_DD(DUK_DDPRINT("no write flush callback, ignore"));
43295 		return;
43296 	}
43297 
43298 	DUK__DBG_TPORT_ENTER();
43299 	heap->dbg_write_flush_cb(heap->dbg_udata);
43300 	DUK__DBG_TPORT_EXIT();
43301 }
43302 
43303 /*
43304  *  Debug connection skip primitives
43305  */
43306 
43307 /* Skip fully. */
43308 DUK_INTERNAL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length) {
43309 	duk_uint8_t dummy[64];
43310 	duk_size_t now;
43311 
43312 	DUK_ASSERT(thr != NULL);
43313 
43314 	while (length > 0) {
43315 		now = (length > sizeof(dummy) ? sizeof(dummy) : length);
43316 		duk_debug_read_bytes(thr, dummy, now);
43317 		length -= now;
43318 	}
43319 }
43320 
43321 DUK_INTERNAL void duk_debug_skip_byte(duk_hthread *thr) {
43322 	DUK_ASSERT(thr != NULL);
43323 
43324 	(void) duk_debug_read_byte(thr);
43325 }
43326 
43327 /*
43328  *  Debug connection read primitives
43329  */
43330 
43331 /* Peek ahead in the stream one byte. */
43332 DUK_INTERNAL uint8_t duk_debug_peek_byte(duk_hthread *thr) {
43333 	/* It is important not to call this if the last byte read was an EOM.
43334 	 * Reading ahead in this scenario would cause unnecessary blocking if
43335 	 * another message is not available.
43336 	 */
43337 
43338 	duk_uint8_t x;
43339 
43340 	x = duk_debug_read_byte(thr);
43341 	thr->heap->dbg_have_next_byte = 1;
43342 	thr->heap->dbg_next_byte = x;
43343 	return x;
43344 }
43345 
43346 /* Read fully. */
43347 DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length) {
43348 	duk_heap *heap;
43349 	duk_uint8_t *p;
43350 	duk_size_t left;
43351 	duk_size_t got;
43352 
43353 	DUK_ASSERT(thr != NULL);
43354 	heap = thr->heap;
43355 	DUK_ASSERT(heap != NULL);
43356 	DUK_ASSERT(data != NULL);
43357 
43358 	if (heap->dbg_read_cb == NULL) {
43359 		DUK_D(DUK_DPRINT("attempt to read %ld bytes in detached state, return zero data", (long) length));
43360 		goto fail;
43361 	}
43362 
43363 	/* NOTE: length may be zero */
43364 	p = data;
43365 	if (length >= 1 && heap->dbg_have_next_byte) {
43366 		heap->dbg_have_next_byte = 0;
43367 		*p++ = heap->dbg_next_byte;
43368 	}
43369 	for (;;) {
43370 		left = (duk_size_t) ((data + length) - p);
43371 		if (left == 0) {
43372 			break;
43373 		}
43374 		DUK_ASSERT(heap->dbg_read_cb != NULL);
43375 		DUK_ASSERT(left >= 1);
43376 #if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
43377 		left = 1;
43378 #endif
43379 		DUK__DBG_TPORT_ENTER();
43380 		got = heap->dbg_read_cb(heap->dbg_udata, (char *) p, left);
43381 		DUK__DBG_TPORT_EXIT();
43382 
43383 		if (got == 0 || got > left) {
43384 			DUK_D(DUK_DPRINT("connection error during read, return zero data"));
43385 			duk__debug_null_most_callbacks(thr);  /* avoid calling write callback in detach1() */
43386 			DUK__SET_CONN_BROKEN(thr, 1);
43387 			goto fail;
43388 		}
43389 		p += got;
43390 	}
43391 	return;
43392 
43393  fail:
43394 	duk_memzero((void *) data, (size_t) length);
43395 }
43396 
43397 DUK_INTERNAL duk_uint8_t duk_debug_read_byte(duk_hthread *thr) {
43398 	duk_uint8_t x;
43399 
43400 	x = 0;  /* just in case callback is broken and won't write 'x' */
43401 	duk_debug_read_bytes(thr, &x, 1);
43402 	return x;
43403 }
43404 
43405 DUK_LOCAL duk_uint32_t duk__debug_read_uint32_raw(duk_hthread *thr) {
43406 	duk_uint8_t buf[4];
43407 
43408 	DUK_ASSERT(thr != NULL);
43409 
43410 	duk_debug_read_bytes(thr, buf, 4);
43411 	return ((duk_uint32_t) buf[0] << 24) |
43412 	       ((duk_uint32_t) buf[1] << 16) |
43413 	       ((duk_uint32_t) buf[2] << 8) |
43414 	       (duk_uint32_t) buf[3];
43415 }
43416 
43417 DUK_LOCAL duk_int32_t duk__debug_read_int32_raw(duk_hthread *thr) {
43418 	return (duk_int32_t) duk__debug_read_uint32_raw(thr);
43419 }
43420 
43421 DUK_LOCAL duk_uint16_t duk__debug_read_uint16_raw(duk_hthread *thr) {
43422 	duk_uint8_t buf[2];
43423 
43424 	DUK_ASSERT(thr != NULL);
43425 
43426 	duk_debug_read_bytes(thr, buf, 2);
43427 	return ((duk_uint16_t) buf[0] << 8) |
43428 	       (duk_uint16_t) buf[1];
43429 }
43430 
43431 DUK_INTERNAL duk_int32_t duk_debug_read_int(duk_hthread *thr) {
43432 	duk_small_uint_t x;
43433 	duk_small_uint_t t;
43434 
43435 	DUK_ASSERT(thr != NULL);
43436 
43437 	x = duk_debug_read_byte(thr);
43438 	if (x >= 0xc0) {
43439 		t = duk_debug_read_byte(thr);
43440 		return (duk_int32_t) (((x - 0xc0) << 8) + t);
43441 	} else if (x >= 0x80) {
43442 		return (duk_int32_t) (x - 0x80);
43443 	} else if (x == DUK_DBG_IB_INT4) {
43444 		return (duk_int32_t) duk__debug_read_uint32_raw(thr);
43445 	}
43446 
43447 	DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
43448 	DUK__SET_CONN_BROKEN(thr, 1);
43449 	return 0;
43450 }
43451 
43452 DUK_LOCAL duk_hstring *duk__debug_read_hstring_raw(duk_hthread *thr, duk_uint32_t len) {
43453 	duk_uint8_t buf[31];
43454 	duk_uint8_t *p;
43455 
43456 	if (len <= sizeof(buf)) {
43457 		duk_debug_read_bytes(thr, buf, (duk_size_t) len);
43458 		duk_push_lstring(thr, (const char *) buf, (duk_size_t) len);
43459 	} else {
43460 		p = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len);  /* zero for paranoia */
43461 		DUK_ASSERT(p != NULL);
43462 		duk_debug_read_bytes(thr, p, (duk_size_t) len);
43463 		(void) duk_buffer_to_string(thr, -1);  /* Safety relies on debug client, which is OK. */
43464 	}
43465 
43466 	return duk_require_hstring(thr, -1);
43467 }
43468 
43469 DUK_INTERNAL duk_hstring *duk_debug_read_hstring(duk_hthread *thr) {
43470 	duk_small_uint_t x;
43471 	duk_uint32_t len;
43472 
43473 	DUK_ASSERT(thr != NULL);
43474 
43475 	x = duk_debug_read_byte(thr);
43476 	if (x >= 0x60 && x <= 0x7f) {
43477 		/* For short strings, use a fixed temp buffer. */
43478 		len = (duk_uint32_t) (x - 0x60);
43479 	} else if (x == DUK_DBG_IB_STR2) {
43480 		len = (duk_uint32_t) duk__debug_read_uint16_raw(thr);
43481 	} else if (x == DUK_DBG_IB_STR4) {
43482 		len = (duk_uint32_t) duk__debug_read_uint32_raw(thr);
43483 	} else {
43484 		goto fail;
43485 	}
43486 
43487 	return duk__debug_read_hstring_raw(thr, len);
43488 
43489  fail:
43490 	DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
43491 	DUK__SET_CONN_BROKEN(thr, 1);
43492 	duk_push_hstring_empty(thr);  /* always push some string */
43493 	return duk_require_hstring(thr, -1);
43494 }
43495 
43496 DUK_LOCAL duk_hbuffer *duk__debug_read_hbuffer_raw(duk_hthread *thr, duk_uint32_t len) {
43497 	duk_uint8_t *p;
43498 
43499 	p = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len);  /* zero for paranoia */
43500 	DUK_ASSERT(p != NULL);
43501 	duk_debug_read_bytes(thr, p, (duk_size_t) len);
43502 
43503 	return duk_require_hbuffer(thr, -1);
43504 }
43505 
43506 DUK_LOCAL void *duk__debug_read_pointer_raw(duk_hthread *thr) {
43507 	duk_small_uint_t x;
43508 	duk__ptr_union pu;
43509 
43510 	DUK_ASSERT(thr != NULL);
43511 
43512 	x = duk_debug_read_byte(thr);
43513 	if (x != sizeof(pu)) {
43514 		goto fail;
43515 	}
43516 	duk_debug_read_bytes(thr, (duk_uint8_t *) &pu.p, sizeof(pu));
43517 #if defined(DUK_USE_INTEGER_LE)
43518 	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
43519 #endif
43520 	return (void *) pu.p;
43521 
43522  fail:
43523 	DUK_D(DUK_DPRINT("debug connection error: failed to decode pointer"));
43524 	DUK__SET_CONN_BROKEN(thr, 1);
43525 	return (void *) NULL;
43526 }
43527 
43528 DUK_LOCAL duk_double_t duk__debug_read_double_raw(duk_hthread *thr) {
43529 	duk_double_union du;
43530 
43531 	DUK_ASSERT(sizeof(du.uc) == 8);
43532 	duk_debug_read_bytes(thr, (duk_uint8_t *) du.uc, sizeof(du.uc));
43533 	DUK_DBLUNION_DOUBLE_NTOH(&du);
43534 	return du.d;
43535 }
43536 
43537 #if 0
43538 DUK_INTERNAL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr) {
43539 	duk_small_uint_t x;
43540 
43541 	DUK_ASSERT(thr != NULL);
43542 
43543 	x = duk_debug_read_byte(thr);
43544 	if (x != DUK_DBG_IB_HEAPPTR) {
43545 		goto fail;
43546 	}
43547 
43548 	return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
43549 
43550  fail:
43551 	DUK_D(DUK_DPRINT("debug connection error: failed to decode heapptr"));
43552 	DUK__SET_CONN_BROKEN(thr, 1);
43553 	return NULL;
43554 }
43555 #endif
43556 
43557 DUK_INTERNAL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr) {
43558 	duk_small_uint_t x;
43559 
43560 	DUK_ASSERT(thr != NULL);
43561 
43562 	x = duk_debug_read_byte(thr);
43563 	switch (x) {
43564 	case DUK_DBG_IB_OBJECT:
43565 	case DUK_DBG_IB_POINTER:
43566 	case DUK_DBG_IB_HEAPPTR:
43567 		/* Accept any pointer-like value; for 'object' dvalue, read
43568 		 * and ignore the class number.
43569 		 */
43570 		if (x == DUK_DBG_IB_OBJECT) {
43571 			duk_debug_skip_byte(thr);
43572 		}
43573 		break;
43574 	default:
43575 		goto fail;
43576 	}
43577 
43578 	return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
43579 
43580  fail:
43581 	DUK_D(DUK_DPRINT("debug connection error: failed to decode any pointer (object, pointer, heapptr)"));
43582 	DUK__SET_CONN_BROKEN(thr, 1);
43583 	return NULL;
43584 }
43585 
43586 DUK_INTERNAL duk_tval *duk_debug_read_tval(duk_hthread *thr) {
43587 	duk_uint8_t x;
43588 	duk_uint_t t;
43589 	duk_uint32_t len;
43590 
43591 	DUK_ASSERT(thr != NULL);
43592 
43593 	x = duk_debug_read_byte(thr);
43594 
43595 	if (x >= 0xc0) {
43596 		t = (duk_uint_t) (x - 0xc0);
43597 		t = (t << 8) + duk_debug_read_byte(thr);
43598 		duk_push_uint(thr, (duk_uint_t) t);
43599 		goto return_ptr;
43600 	}
43601 	if (x >= 0x80) {
43602 		duk_push_uint(thr, (duk_uint_t) (x - 0x80));
43603 		goto return_ptr;
43604 	}
43605 	if (x >= 0x60) {
43606 		len = (duk_uint32_t) (x - 0x60);
43607 		duk__debug_read_hstring_raw(thr, len);
43608 		goto return_ptr;
43609 	}
43610 
43611 	switch (x) {
43612 	case DUK_DBG_IB_INT4: {
43613 		duk_int32_t i = duk__debug_read_int32_raw(thr);
43614 		duk_push_i32(thr, i);
43615 		break;
43616 	}
43617 	case DUK_DBG_IB_STR4: {
43618 		len = duk__debug_read_uint32_raw(thr);
43619 		duk__debug_read_hstring_raw(thr, len);
43620 		break;
43621 	}
43622 	case DUK_DBG_IB_STR2: {
43623 		len = duk__debug_read_uint16_raw(thr);
43624 		duk__debug_read_hstring_raw(thr, len);
43625 		break;
43626 	}
43627 	case DUK_DBG_IB_BUF4: {
43628 		len = duk__debug_read_uint32_raw(thr);
43629 		duk__debug_read_hbuffer_raw(thr, len);
43630 		break;
43631 	}
43632 	case DUK_DBG_IB_BUF2: {
43633 		len = duk__debug_read_uint16_raw(thr);
43634 		duk__debug_read_hbuffer_raw(thr, len);
43635 		break;
43636 	}
43637 	case DUK_DBG_IB_UNDEFINED: {
43638 		duk_push_undefined(thr);
43639 		break;
43640 	}
43641 	case DUK_DBG_IB_NULL: {
43642 		duk_push_null(thr);
43643 		break;
43644 	}
43645 	case DUK_DBG_IB_TRUE: {
43646 		duk_push_true(thr);
43647 		break;
43648 	}
43649 	case DUK_DBG_IB_FALSE: {
43650 		duk_push_false(thr);
43651 		break;
43652 	}
43653 	case DUK_DBG_IB_NUMBER: {
43654 		duk_double_t d;
43655 		d = duk__debug_read_double_raw(thr);
43656 		duk_push_number(thr, d);
43657 		break;
43658 	}
43659 	case DUK_DBG_IB_OBJECT: {
43660 		duk_heaphdr *h;
43661 		duk_debug_skip_byte(thr);
43662 		h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
43663 		duk_push_heapptr(thr, (void *) h);
43664 		break;
43665 	}
43666 	case DUK_DBG_IB_POINTER: {
43667 		void *ptr;
43668 		ptr = duk__debug_read_pointer_raw(thr);
43669 		duk_push_pointer(thr, ptr);
43670 		break;
43671 	}
43672 	case DUK_DBG_IB_LIGHTFUNC: {
43673 		/* XXX: Not needed for now, so not implemented.  Note that
43674 		 * function pointers may have different size/layout than
43675 		 * a void pointer.
43676 		 */
43677 		DUK_D(DUK_DPRINT("reading lightfunc values unimplemented"));
43678 		goto fail;
43679 	}
43680 	case DUK_DBG_IB_HEAPPTR: {
43681 		duk_heaphdr *h;
43682 		h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
43683 		duk_push_heapptr(thr, (void *) h);
43684 		break;
43685 	}
43686 	case DUK_DBG_IB_UNUSED:  /* unused: not accepted in inbound messages */
43687 	default:
43688 		goto fail;
43689 	}
43690 
43691  return_ptr:
43692 	return DUK_GET_TVAL_NEGIDX(thr, -1);
43693 
43694  fail:
43695 	DUK_D(DUK_DPRINT("debug connection error: failed to decode tval"));
43696 	DUK__SET_CONN_BROKEN(thr, 1);
43697 	return NULL;
43698 }
43699 
43700 /*
43701  *  Debug connection write primitives
43702  */
43703 
43704 /* Write fully. */
43705 DUK_INTERNAL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length) {
43706 	duk_heap *heap;
43707 	const duk_uint8_t *p;
43708 	duk_size_t left;
43709 	duk_size_t got;
43710 
43711 	DUK_ASSERT(thr != NULL);
43712 	DUK_ASSERT(length == 0 || data != NULL);
43713 	heap = thr->heap;
43714 	DUK_ASSERT(heap != NULL);
43715 
43716 	if (heap->dbg_write_cb == NULL) {
43717 		DUK_D(DUK_DPRINT("attempt to write %ld bytes in detached state, ignore", (long) length));
43718 		return;
43719 	}
43720 	if (length == 0) {
43721 		/* Avoid doing an actual write callback with length == 0,
43722 		 * because that's reserved for a write flush.
43723 		 */
43724 		return;
43725 	}
43726 	DUK_ASSERT(data != NULL);
43727 
43728 	p = data;
43729 	for (;;) {
43730 		left = (duk_size_t) ((data + length) - p);
43731 		if (left == 0) {
43732 			break;
43733 		}
43734 		DUK_ASSERT(heap->dbg_write_cb != NULL);
43735 		DUK_ASSERT(left >= 1);
43736 #if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
43737 		left = 1;
43738 #endif
43739 		DUK__DBG_TPORT_ENTER();
43740 		got = heap->dbg_write_cb(heap->dbg_udata, (const char *) p, left);
43741 		DUK__DBG_TPORT_EXIT();
43742 
43743 		if (got == 0 || got > left) {
43744 			duk__debug_null_most_callbacks(thr);  /* avoid calling write callback in detach1() */
43745 			DUK_D(DUK_DPRINT("connection error during write"));
43746 			DUK__SET_CONN_BROKEN(thr, 1);
43747 			return;
43748 		}
43749 		p += got;
43750 	}
43751 }
43752 
43753 DUK_INTERNAL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x) {
43754 	duk_debug_write_bytes(thr, (const duk_uint8_t *) &x, 1);
43755 }
43756 
43757 DUK_INTERNAL void duk_debug_write_unused(duk_hthread *thr) {
43758 	duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
43759 }
43760 
43761 DUK_INTERNAL void duk_debug_write_undefined(duk_hthread *thr) {
43762 	duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
43763 }
43764 
43765 #if defined(DUK_USE_DEBUGGER_INSPECT)
43766 DUK_INTERNAL void duk_debug_write_null(duk_hthread *thr) {
43767 	duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
43768 }
43769 #endif
43770 
43771 DUK_INTERNAL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val) {
43772 	duk_debug_write_byte(thr, val ? DUK_DBG_IB_TRUE : DUK_DBG_IB_FALSE);
43773 }
43774 
43775 /* Write signed 32-bit integer. */
43776 DUK_INTERNAL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x) {
43777 	duk_uint8_t buf[5];
43778 	duk_size_t len;
43779 
43780 	DUK_ASSERT(thr != NULL);
43781 
43782 	if (x >= 0 && x <= 0x3fL) {
43783 		buf[0] = (duk_uint8_t) (0x80 + x);
43784 		len = 1;
43785 	} else if (x >= 0 && x <= 0x3fffL) {
43786 		buf[0] = (duk_uint8_t) (0xc0 + (x >> 8));
43787 		buf[1] = (duk_uint8_t) (x & 0xff);
43788 		len = 2;
43789 	} else {
43790 		/* Signed integers always map to 4 bytes now. */
43791 		buf[0] = (duk_uint8_t) DUK_DBG_IB_INT4;
43792 		buf[1] = (duk_uint8_t) ((x >> 24) & 0xff);
43793 		buf[2] = (duk_uint8_t) ((x >> 16) & 0xff);
43794 		buf[3] = (duk_uint8_t) ((x >> 8) & 0xff);
43795 		buf[4] = (duk_uint8_t) (x & 0xff);
43796 		len = 5;
43797 	}
43798 	duk_debug_write_bytes(thr, buf, len);
43799 }
43800 
43801 /* Write unsigned 32-bit integer. */
43802 DUK_INTERNAL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x) {
43803 	/* The debugger protocol doesn't support a plain integer encoding for
43804 	 * the full 32-bit unsigned range (only 32-bit signed).  For now,
43805 	 * unsigned 32-bit values simply written as signed ones.  This is not
43806 	 * a concrete issue except for 32-bit heaphdr fields.  Proper solutions
43807 	 * would be to (a) write such integers as IEEE doubles or (b) add an
43808 	 * unsigned 32-bit dvalue.
43809 	 */
43810 	if (x >= 0x80000000UL) {
43811 		DUK_D(DUK_DPRINT("writing unsigned integer 0x%08lx as signed integer",
43812 		                 (long) x));
43813 	}
43814 	duk_debug_write_int(thr, (duk_int32_t) x);
43815 }
43816 
43817 DUK_INTERNAL void duk_debug_write_strbuf(duk_hthread *thr, const char *data, duk_size_t length, duk_uint8_t marker_base) {
43818 	duk_uint8_t buf[5];
43819 	duk_size_t buflen;
43820 
43821 	DUK_ASSERT(thr != NULL);
43822 	DUK_ASSERT(length == 0 || data != NULL);
43823 
43824 	if (length <= 0x1fUL && marker_base == DUK_DBG_IB_STR4) {
43825 		/* For strings, special form for short lengths. */
43826 		buf[0] = (duk_uint8_t) (0x60 + length);
43827 		buflen = 1;
43828 	} else if (length <= 0xffffUL) {
43829 		buf[0] = (duk_uint8_t) (marker_base + 1);
43830 		buf[1] = (duk_uint8_t) (length >> 8);
43831 		buf[2] = (duk_uint8_t) (length & 0xff);
43832 		buflen = 3;
43833 	} else {
43834 		buf[0] = (duk_uint8_t) marker_base;
43835 		buf[1] = (duk_uint8_t) (length >> 24);
43836 		buf[2] = (duk_uint8_t) ((length >> 16) & 0xff);
43837 		buf[3] = (duk_uint8_t) ((length >> 8) & 0xff);
43838 		buf[4] = (duk_uint8_t) (length & 0xff);
43839 		buflen = 5;
43840 	}
43841 
43842 	duk_debug_write_bytes(thr, (const duk_uint8_t *) buf, buflen);
43843 	duk_debug_write_bytes(thr, (const duk_uint8_t *) data, length);
43844 }
43845 
43846 DUK_INTERNAL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length) {
43847 	duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_STR4);
43848 }
43849 
43850 DUK_INTERNAL void duk_debug_write_cstring(duk_hthread *thr, const char *data) {
43851 	DUK_ASSERT(thr != NULL);
43852 
43853 	duk_debug_write_string(thr,
43854 	                       data,
43855 	                       data ? DUK_STRLEN(data) : 0);
43856 }
43857 
43858 DUK_INTERNAL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h) {
43859 	DUK_ASSERT(thr != NULL);
43860 
43861 	/* XXX: differentiate null pointer from empty string? */
43862 	duk_debug_write_string(thr,
43863 	                       (h != NULL ? (const char *) DUK_HSTRING_GET_DATA(h) : NULL),
43864 	                       (h != NULL ? (duk_size_t) DUK_HSTRING_GET_BYTELEN(h) : 0));
43865 }
43866 
43867 DUK_LOCAL void duk__debug_write_hstring_safe_top(duk_hthread *thr) {
43868 	duk_debug_write_hstring(thr, duk_safe_to_hstring(thr, -1));
43869 }
43870 
43871 DUK_INTERNAL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length) {
43872 	duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_BUF4);
43873 }
43874 
43875 DUK_INTERNAL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
43876 	DUK_ASSERT(thr != NULL);
43877 
43878 	duk_debug_write_buffer(thr,
43879 	                       (h != NULL ? (const char *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h) : NULL),
43880 	                       (h != NULL ? (duk_size_t) DUK_HBUFFER_GET_SIZE(h) : 0));
43881 }
43882 
43883 DUK_LOCAL void duk__debug_write_pointer_raw(duk_hthread *thr, void *ptr, duk_uint8_t ibyte) {
43884 	duk_uint8_t buf[2];
43885 	duk__ptr_union pu;
43886 
43887 	DUK_ASSERT(thr != NULL);
43888 	DUK_ASSERT(sizeof(ptr) >= 1 && sizeof(ptr) <= 16);
43889 	/* ptr may be NULL */
43890 
43891 	buf[0] = ibyte;
43892 	buf[1] = sizeof(pu);
43893 	duk_debug_write_bytes(thr, buf, 2);
43894 	pu.p = (void *) ptr;
43895 #if defined(DUK_USE_INTEGER_LE)
43896 	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
43897 #endif
43898 	duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
43899 }
43900 
43901 DUK_INTERNAL void duk_debug_write_pointer(duk_hthread *thr, void *ptr) {
43902 	duk__debug_write_pointer_raw(thr, ptr, DUK_DBG_IB_POINTER);
43903 }
43904 
43905 #if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
43906 DUK_INTERNAL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h) {
43907 	duk__debug_write_pointer_raw(thr, (void *) h, DUK_DBG_IB_HEAPPTR);
43908 }
43909 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP || DUK_USE_DEBUGGER_INSPECT */
43910 
43911 DUK_INTERNAL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj) {
43912 	duk_uint8_t buf[3];
43913 	duk__ptr_union pu;
43914 
43915 	DUK_ASSERT(thr != NULL);
43916 	DUK_ASSERT(sizeof(obj) >= 1 && sizeof(obj) <= 16);
43917 	DUK_ASSERT(obj != NULL);
43918 
43919 	buf[0] = DUK_DBG_IB_OBJECT;
43920 	buf[1] = (duk_uint8_t) DUK_HOBJECT_GET_CLASS_NUMBER(obj);
43921 	buf[2] = sizeof(pu);
43922 	duk_debug_write_bytes(thr, buf, 3);
43923 	pu.p = (void *) obj;
43924 #if defined(DUK_USE_INTEGER_LE)
43925 	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
43926 #endif
43927 	duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
43928 }
43929 
43930 DUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) {
43931 	duk_c_function lf_func;
43932 	duk_small_uint_t lf_flags;
43933 	duk_uint8_t buf[4];
43934 	duk_double_union du1;
43935 	duk_double_union du2;
43936 	duk_int32_t i32;
43937 
43938 	DUK_ASSERT(thr != NULL);
43939 	DUK_ASSERT(tv != NULL);
43940 
43941 	switch (DUK_TVAL_GET_TAG(tv)) {
43942 	case DUK_TAG_UNDEFINED:
43943 		duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
43944 		break;
43945 	case DUK_TAG_UNUSED:
43946 		duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
43947 		break;
43948 	case DUK_TAG_NULL:
43949 		duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
43950 		break;
43951 	case DUK_TAG_BOOLEAN:
43952 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 ||
43953 		           DUK_TVAL_GET_BOOLEAN(tv) == 1);
43954 		duk_debug_write_boolean(thr, DUK_TVAL_GET_BOOLEAN(tv));
43955 		break;
43956 	case DUK_TAG_POINTER:
43957 		duk_debug_write_pointer(thr, (void *) DUK_TVAL_GET_POINTER(tv));
43958 		break;
43959 	case DUK_TAG_LIGHTFUNC:
43960 		DUK_TVAL_GET_LIGHTFUNC(tv, lf_func, lf_flags);
43961 		buf[0] = DUK_DBG_IB_LIGHTFUNC;
43962 		buf[1] = (duk_uint8_t) (lf_flags >> 8);
43963 		buf[2] = (duk_uint8_t) (lf_flags & 0xff);
43964 		buf[3] = sizeof(lf_func);
43965 		duk_debug_write_bytes(thr, buf, 4);
43966 		duk_debug_write_bytes(thr, (const duk_uint8_t *) &lf_func, sizeof(lf_func));
43967 		break;
43968 	case DUK_TAG_STRING:
43969 		duk_debug_write_hstring(thr, DUK_TVAL_GET_STRING(tv));
43970 		break;
43971 	case DUK_TAG_OBJECT:
43972 		duk_debug_write_hobject(thr, DUK_TVAL_GET_OBJECT(tv));
43973 		break;
43974 	case DUK_TAG_BUFFER:
43975 		duk_debug_write_hbuffer(thr, DUK_TVAL_GET_BUFFER(tv));
43976 		break;
43977 #if defined(DUK_USE_FASTINT)
43978 	case DUK_TAG_FASTINT:
43979 #endif
43980 	default:
43981 		/* Numbers are normalized to big (network) endian.  We can
43982 		 * (but are not required) to use integer dvalues when there's
43983 		 * no loss of precision.
43984 		 *
43985 		 * XXX: share check with other code; this check is slow but
43986 		 * reliable and doesn't require careful exponent/mantissa
43987 		 * mask tricks as in the fastint downgrade code.
43988 		 */
43989 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
43990 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
43991 		du1.d = DUK_TVAL_GET_NUMBER(tv);
43992 		i32 = (duk_int32_t) du1.d;
43993 		du2.d = (duk_double_t) i32;
43994 
43995 		DUK_DD(DUK_DDPRINT("i32=%ld du1=%02x%02x%02x%02x%02x%02x%02x%02x "
43996 		                   "du2=%02x%02x%02x%02x%02x%02x%02x%02x",
43997 		                   (long) i32,
43998 		                   (unsigned int) du1.uc[0], (unsigned int) du1.uc[1],
43999 		                   (unsigned int) du1.uc[2], (unsigned int) du1.uc[3],
44000 		                   (unsigned int) du1.uc[4], (unsigned int) du1.uc[5],
44001 		                   (unsigned int) du1.uc[6], (unsigned int) du1.uc[7],
44002 		                   (unsigned int) du2.uc[0], (unsigned int) du2.uc[1],
44003 		                   (unsigned int) du2.uc[2], (unsigned int) du2.uc[3],
44004 		                   (unsigned int) du2.uc[4], (unsigned int) du2.uc[5],
44005 		                   (unsigned int) du2.uc[6], (unsigned int) du2.uc[7]));
44006 
44007 		if (duk_memcmp((const void *) du1.uc, (const void *) du2.uc, sizeof(du1.uc)) == 0) {
44008 			duk_debug_write_int(thr, i32);
44009 		} else {
44010 			DUK_DBLUNION_DOUBLE_HTON(&du1);
44011 			duk_debug_write_byte(thr, DUK_DBG_IB_NUMBER);
44012 			duk_debug_write_bytes(thr, (const duk_uint8_t *) du1.uc, sizeof(du1.uc));
44013 		}
44014 	}
44015 }
44016 
44017 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
44018 /* Variant for writing duk_tvals so that any heap allocated values are
44019  * written out as tagged heap pointers.
44020  */
44021 DUK_LOCAL void duk__debug_write_tval_heapptr(duk_hthread *thr, duk_tval *tv) {
44022 	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
44023 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
44024 		duk_debug_write_heapptr(thr, h);
44025 	} else {
44026 		duk_debug_write_tval(thr, tv);
44027 	}
44028 }
44029 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
44030 
44031 /*
44032  *  Debug connection message write helpers
44033  */
44034 
44035 #if 0  /* unused */
44036 DUK_INTERNAL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command) {
44037 	duk_debug_write_byte(thr, DUK_DBG_IB_REQUEST);
44038 	duk_debug_write_int(thr, command);
44039 }
44040 #endif
44041 
44042 DUK_INTERNAL void duk_debug_write_reply(duk_hthread *thr) {
44043 	duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
44044 }
44045 
44046 DUK_INTERNAL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg) {
44047 	/* Allow NULL 'msg' */
44048 	duk_debug_write_byte(thr, DUK_DBG_IB_ERROR);
44049 	duk_debug_write_int(thr, (duk_int32_t) err_code);
44050 	duk_debug_write_cstring(thr, msg);
44051 	duk_debug_write_eom(thr);
44052 }
44053 
44054 DUK_INTERNAL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command) {
44055 	duk_debug_write_byte(thr, DUK_DBG_IB_NOTIFY);
44056 	duk_debug_write_int(thr, (duk_int32_t) command);
44057 }
44058 
44059 DUK_INTERNAL void duk_debug_write_eom(duk_hthread *thr) {
44060 	duk_debug_write_byte(thr, DUK_DBG_IB_EOM);
44061 
44062 	/* As an initial implementation, write flush after every EOM (and the
44063 	 * version identifier).  A better implementation would flush only when
44064 	 * Duktape is finished processing messages so that a flush only happens
44065 	 * after all outbound messages are finished on that occasion.
44066 	 */
44067 	duk_debug_write_flush(thr);
44068 }
44069 
44070 /*
44071  *  Status message and helpers
44072  */
44073 
44074 DUK_INTERNAL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr) {
44075 	duk_activation *act;
44076 	duk_uint_fast32_t line;
44077 	duk_uint_fast32_t pc;
44078 
44079 	act = thr->callstack_curr;
44080 	if (act == NULL) {
44081 		return 0;
44082 	}
44083 
44084 	/* We're conceptually between two opcodes; act->pc indicates the next
44085 	 * instruction to be executed.  This is usually the correct pc/line to
44086 	 * indicate in Status.  (For the 'debugger' statement this now reports
44087 	 * the pc/line after the debugger statement because the debugger opcode
44088 	 * has already been executed.)
44089 	 */
44090 
44091 	pc = duk_hthread_get_act_curr_pc(thr, act);
44092 
44093 	/* XXX: this should be optimized to be a raw query and avoid valstack
44094 	 * operations if possible.
44095 	 */
44096 	duk_push_tval(thr, &act->tv_func);
44097 	line = duk_hobject_pc2line_query(thr, -1, pc);
44098 	duk_pop(thr);
44099 	return line;
44100 }
44101 
44102 DUK_INTERNAL void duk_debug_send_status(duk_hthread *thr) {
44103 	duk_activation *act;
44104 
44105 	duk_debug_write_notify(thr, DUK_DBG_CMD_STATUS);
44106 	duk_debug_write_int(thr, (DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ? 1 : 0));
44107 
44108 	act = thr->callstack_curr;
44109 	if (act == NULL) {
44110 		duk_debug_write_undefined(thr);
44111 		duk_debug_write_undefined(thr);
44112 		duk_debug_write_int(thr, 0);
44113 		duk_debug_write_int(thr, 0);
44114 	} else {
44115 		duk_push_tval(thr, &act->tv_func);
44116 		duk_get_prop_literal(thr, -1, "fileName");
44117 		duk__debug_write_hstring_safe_top(thr);
44118 		duk_get_prop_literal(thr, -2, "name");
44119 		duk__debug_write_hstring_safe_top(thr);
44120 		duk_pop_3(thr);
44121 		/* Report next pc/line to be executed. */
44122 		duk_debug_write_uint(thr, (duk_uint32_t) duk_debug_curr_line(thr));
44123 		duk_debug_write_uint(thr, (duk_uint32_t) duk_hthread_get_act_curr_pc(thr, act));
44124 	}
44125 
44126 	duk_debug_write_eom(thr);
44127 }
44128 
44129 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
44130 DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {
44131 	/*
44132 	 *  NFY <int: 5> <int: fatal> <str: msg> <str: filename> <int: linenumber> EOM
44133 	 */
44134 
44135 	duk_activation *act;
44136 	duk_uint32_t pc;
44137 
44138 	DUK_ASSERT(thr->valstack_top > thr->valstack);  /* At least: ... [err] */
44139 
44140 	duk_debug_write_notify(thr, DUK_DBG_CMD_THROW);
44141 	duk_debug_write_int(thr, (duk_int32_t) fatal);
44142 
44143 	/* Report thrown value to client coerced to string */
44144 	duk_dup_top(thr);
44145 	duk__debug_write_hstring_safe_top(thr);
44146 	duk_pop(thr);
44147 
44148 	if (duk_is_error(thr, -1)) {
44149 		/* Error instance, use augmented error data directly */
44150 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);
44151 		duk__debug_write_hstring_safe_top(thr);
44152 		duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_LINE_NUMBER);
44153 		duk_debug_write_uint(thr, duk_get_uint(thr, -1));
44154 		duk_pop_2(thr);
44155 	} else {
44156 		/* For anything other than an Error instance, we calculate the
44157 		 * error location directly from the current activation if one
44158 		 * exists.
44159 		 */
44160 		act = thr->callstack_curr;
44161 		if (act != NULL) {
44162 			duk_push_tval(thr, &act->tv_func);
44163 			duk_get_prop_literal(thr, -1, "fileName");
44164 			duk__debug_write_hstring_safe_top(thr);
44165 			pc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr, act);
44166 			duk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(thr, -2, pc));
44167 			duk_pop_2(thr);
44168 		} else {
44169 			/* Can happen if duk_throw() is called on an empty
44170 			 * callstack.
44171 			 */
44172 			duk_debug_write_cstring(thr, "");
44173 			duk_debug_write_uint(thr, 0);
44174 		}
44175 	}
44176 
44177 	duk_debug_write_eom(thr);
44178 }
44179 #endif  /* DUK_USE_DEBUGGER_THROW_NOTIFY */
44180 
44181 /*
44182  *  Debug message processing
44183  */
44184 
44185 /* Skip dvalue. */
44186 DUK_LOCAL duk_bool_t duk__debug_skip_dvalue(duk_hthread *thr) {
44187 	duk_uint8_t x;
44188 	duk_uint32_t len;
44189 
44190 	x = duk_debug_read_byte(thr);
44191 
44192 	if (x >= 0xc0) {
44193 		duk_debug_skip_byte(thr);
44194 		return 0;
44195 	}
44196 	if (x >= 0x80) {
44197 		return 0;
44198 	}
44199 	if (x >= 0x60) {
44200 		duk_debug_skip_bytes(thr, (duk_size_t) (x - 0x60));
44201 		return 0;
44202 	}
44203 	switch(x) {
44204 	case DUK_DBG_IB_EOM:
44205 		return 1;  /* Return 1: got EOM */
44206 	case DUK_DBG_IB_REQUEST:
44207 	case DUK_DBG_IB_REPLY:
44208 	case DUK_DBG_IB_ERROR:
44209 	case DUK_DBG_IB_NOTIFY:
44210 		break;
44211 	case DUK_DBG_IB_INT4:
44212 		(void) duk__debug_read_uint32_raw(thr);
44213 		break;
44214 	case DUK_DBG_IB_STR4:
44215 	case DUK_DBG_IB_BUF4:
44216 		len = duk__debug_read_uint32_raw(thr);
44217 		duk_debug_skip_bytes(thr, len);
44218 		break;
44219 	case DUK_DBG_IB_STR2:
44220 	case DUK_DBG_IB_BUF2:
44221 		len = duk__debug_read_uint16_raw(thr);
44222 		duk_debug_skip_bytes(thr, len);
44223 		break;
44224 	case DUK_DBG_IB_UNUSED:
44225 	case DUK_DBG_IB_UNDEFINED:
44226 	case DUK_DBG_IB_NULL:
44227 	case DUK_DBG_IB_TRUE:
44228 	case DUK_DBG_IB_FALSE:
44229 		break;
44230 	case DUK_DBG_IB_NUMBER:
44231 		duk_debug_skip_bytes(thr, 8);
44232 		break;
44233 	case DUK_DBG_IB_OBJECT:
44234 		duk_debug_skip_byte(thr);
44235 		len = duk_debug_read_byte(thr);
44236 		duk_debug_skip_bytes(thr, len);
44237 		break;
44238 	case DUK_DBG_IB_POINTER:
44239 	case DUK_DBG_IB_HEAPPTR:
44240 		len = duk_debug_read_byte(thr);
44241 		duk_debug_skip_bytes(thr, len);
44242 		break;
44243 	case DUK_DBG_IB_LIGHTFUNC:
44244 		duk_debug_skip_bytes(thr, 2);
44245 		len = duk_debug_read_byte(thr);
44246 		duk_debug_skip_bytes(thr, len);
44247 		break;
44248 	default:
44249 		goto fail;
44250 	}
44251 
44252 	return 0;
44253 
44254  fail:
44255 	DUK__SET_CONN_BROKEN(thr, 1);
44256 	return 1;  /* Pretend like we got EOM */
44257 }
44258 
44259 /* Skip dvalues to EOM. */
44260 DUK_LOCAL void duk__debug_skip_to_eom(duk_hthread *thr) {
44261 	for (;;) {
44262 		if (duk__debug_skip_dvalue(thr)) {
44263 			break;
44264 		}
44265 	}
44266 }
44267 
44268 /* Read and validate a call stack index.  If index is invalid, write out an
44269  * error message and return zero.
44270  */
44271 DUK_LOCAL duk_int32_t duk__debug_read_validate_csindex(duk_hthread *thr) {
44272 	duk_int32_t level;
44273 	level = duk_debug_read_int(thr);
44274 	if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
44275 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
44276 		return 0;  /* zero indicates failure */
44277 	}
44278 	return level;
44279 }
44280 
44281 /* Read a call stack index and lookup the corresponding duk_activation.
44282  * If index is invalid, write out an error message and return NULL.
44283  */
44284 DUK_LOCAL duk_activation *duk__debug_read_level_get_activation(duk_hthread *thr) {
44285 	duk_activation *act;
44286 	duk_int32_t level;
44287 
44288 	level = duk_debug_read_int(thr);
44289 	act = duk_hthread_get_activation_for_level(thr, level);
44290 	if (act == NULL) {
44291 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
44292 	}
44293 	return act;
44294 }
44295 
44296 /*
44297  *  Simple commands
44298  */
44299 
44300 DUK_LOCAL void duk__debug_handle_basic_info(duk_hthread *thr, duk_heap *heap) {
44301 	DUK_UNREF(heap);
44302 	DUK_D(DUK_DPRINT("debug command Version"));
44303 
44304 	duk_debug_write_reply(thr);
44305 	duk_debug_write_int(thr, DUK_VERSION);
44306 	duk_debug_write_cstring(thr, DUK_GIT_DESCRIBE);
44307 	duk_debug_write_cstring(thr, DUK_USE_TARGET_INFO);
44308 #if defined(DUK_USE_DOUBLE_LE)
44309 	duk_debug_write_int(thr, 1);
44310 #elif defined(DUK_USE_DOUBLE_ME)
44311 	duk_debug_write_int(thr, 2);
44312 #elif defined(DUK_USE_DOUBLE_BE)
44313 	duk_debug_write_int(thr, 3);
44314 #else
44315 	duk_debug_write_int(thr, 0);
44316 #endif
44317 	duk_debug_write_int(thr, (duk_int_t) sizeof(void *));
44318 	duk_debug_write_eom(thr);
44319 }
44320 
44321 DUK_LOCAL void duk__debug_handle_trigger_status(duk_hthread *thr, duk_heap *heap) {
44322 	DUK_UNREF(heap);
44323 	DUK_D(DUK_DPRINT("debug command TriggerStatus"));
44324 
44325 	duk_debug_write_reply(thr);
44326 	duk_debug_write_eom(thr);
44327 	heap->dbg_state_dirty = 1;
44328 }
44329 
44330 DUK_LOCAL void duk__debug_handle_pause(duk_hthread *thr, duk_heap *heap) {
44331 	DUK_D(DUK_DPRINT("debug command Pause"));
44332 	duk_debug_set_paused(heap);
44333 	duk_debug_write_reply(thr);
44334 	duk_debug_write_eom(thr);
44335 }
44336 
44337 DUK_LOCAL void duk__debug_handle_resume(duk_hthread *thr, duk_heap *heap) {
44338 	duk_small_uint_t pause_flags;
44339 
44340 	DUK_D(DUK_DPRINT("debug command Resume"));
44341 
44342 	duk_debug_clear_paused(heap);
44343 
44344 	pause_flags = 0;
44345 #if 0  /* manual testing */
44346 	pause_flags |= DUK_PAUSE_FLAG_ONE_OPCODE;
44347 	pause_flags |= DUK_PAUSE_FLAG_CAUGHT_ERROR;
44348 	pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
44349 #endif
44350 #if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
44351 	pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
44352 #endif
44353 
44354 	duk__debug_set_pause_state(thr, heap, pause_flags);
44355 
44356 	duk_debug_write_reply(thr);
44357 	duk_debug_write_eom(thr);
44358 }
44359 
44360 DUK_LOCAL void duk__debug_handle_step(duk_hthread *thr, duk_heap *heap, duk_int32_t cmd) {
44361 	duk_small_uint_t pause_flags;
44362 
44363 	DUK_D(DUK_DPRINT("debug command StepInto/StepOver/StepOut: %d", (int) cmd));
44364 
44365 	if (cmd == DUK_DBG_CMD_STEPINTO) {
44366 		pause_flags = DUK_PAUSE_FLAG_LINE_CHANGE |
44367 		              DUK_PAUSE_FLAG_FUNC_ENTRY |
44368 		              DUK_PAUSE_FLAG_FUNC_EXIT;
44369 	} else if (cmd == DUK_DBG_CMD_STEPOVER) {
44370 		pause_flags = DUK_PAUSE_FLAG_LINE_CHANGE |
44371 		              DUK_PAUSE_FLAG_FUNC_EXIT;
44372 	} else {
44373 		DUK_ASSERT(cmd == DUK_DBG_CMD_STEPOUT);
44374 		pause_flags = DUK_PAUSE_FLAG_FUNC_EXIT;
44375 	}
44376 #if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
44377 	pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
44378 #endif
44379 
44380 	/* If current activation doesn't have line information, line-based
44381 	 * pause flags are automatically disabled.  As a result, e.g.
44382 	 * StepInto will then pause on (native) function entry or exit.
44383 	 */
44384 	duk_debug_clear_paused(heap);
44385 	duk__debug_set_pause_state(thr, heap, pause_flags);
44386 
44387 	duk_debug_write_reply(thr);
44388 	duk_debug_write_eom(thr);
44389 }
44390 
44391 DUK_LOCAL void duk__debug_handle_list_break(duk_hthread *thr, duk_heap *heap) {
44392 	duk_small_int_t i;
44393 
44394 	DUK_D(DUK_DPRINT("debug command ListBreak"));
44395 	duk_debug_write_reply(thr);
44396 	for (i = 0; i < (duk_small_int_t) heap->dbg_breakpoint_count; i++) {
44397 		duk_debug_write_hstring(thr, heap->dbg_breakpoints[i].filename);
44398 		duk_debug_write_uint(thr, (duk_uint32_t) heap->dbg_breakpoints[i].line);
44399 	}
44400 	duk_debug_write_eom(thr);
44401 }
44402 
44403 DUK_LOCAL void duk__debug_handle_add_break(duk_hthread *thr, duk_heap *heap) {
44404 	duk_hstring *filename;
44405 	duk_uint32_t linenumber;
44406 	duk_small_int_t idx;
44407 
44408 	DUK_UNREF(heap);
44409 
44410 	filename = duk_debug_read_hstring(thr);
44411 	linenumber = (duk_uint32_t) duk_debug_read_int(thr);
44412 	DUK_D(DUK_DPRINT("debug command AddBreak: %!O:%ld", (duk_hobject *) filename, (long) linenumber));
44413 	idx = duk_debug_add_breakpoint(thr, filename, linenumber);
44414 	if (idx >= 0) {
44415 		duk_debug_write_reply(thr);
44416 		duk_debug_write_int(thr, (duk_int32_t) idx);
44417 		duk_debug_write_eom(thr);
44418 	} else {
44419 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_TOOMANY, "no space for breakpoint");
44420 	}
44421 }
44422 
44423 DUK_LOCAL void duk__debug_handle_del_break(duk_hthread *thr, duk_heap *heap) {
44424 	duk_small_uint_t idx;
44425 
44426 	DUK_UNREF(heap);
44427 
44428 	DUK_D(DUK_DPRINT("debug command DelBreak"));
44429 	idx = (duk_small_uint_t) duk_debug_read_int(thr);
44430 	if (duk_debug_remove_breakpoint(thr, idx)) {
44431 		duk_debug_write_reply(thr);
44432 		duk_debug_write_eom(thr);
44433 	} else {
44434 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid breakpoint index");
44435 	}
44436 }
44437 
44438 DUK_LOCAL void duk__debug_handle_get_var(duk_hthread *thr, duk_heap *heap) {
44439 	duk_activation *act;
44440 	duk_hstring *str;
44441 	duk_bool_t rc;
44442 
44443 	DUK_UNREF(heap);
44444 	DUK_D(DUK_DPRINT("debug command GetVar"));
44445 
44446 	act = duk__debug_read_level_get_activation(thr);
44447 	if (act == NULL) {
44448 		return;
44449 	}
44450 	str = duk_debug_read_hstring(thr);  /* push to stack */
44451 	DUK_ASSERT(str != NULL);
44452 
44453 	rc = duk_js_getvar_activation(thr, act, str, 0);
44454 
44455 	duk_debug_write_reply(thr);
44456 	if (rc) {
44457 		duk_debug_write_int(thr, 1);
44458 		DUK_ASSERT(duk_get_tval(thr, -2) != NULL);
44459 		duk_debug_write_tval(thr, duk_get_tval(thr, -2));
44460 	} else {
44461 		duk_debug_write_int(thr, 0);
44462 		duk_debug_write_unused(thr);
44463 	}
44464 	duk_debug_write_eom(thr);
44465 }
44466 
44467 DUK_LOCAL void duk__debug_handle_put_var(duk_hthread *thr, duk_heap *heap) {
44468 	duk_activation *act;
44469 	duk_hstring *str;
44470 	duk_tval *tv;
44471 
44472 	DUK_UNREF(heap);
44473 	DUK_D(DUK_DPRINT("debug command PutVar"));
44474 
44475 	act = duk__debug_read_level_get_activation(thr);
44476 	if (act == NULL) {
44477 		return;
44478 	}
44479 	str = duk_debug_read_hstring(thr);  /* push to stack */
44480 	DUK_ASSERT(str != NULL);
44481 	tv = duk_debug_read_tval(thr);
44482 	if (tv == NULL) {
44483 		/* detached */
44484 		return;
44485 	}
44486 
44487 	duk_js_putvar_activation(thr, act, str, tv, 0);
44488 
44489 	/* XXX: Current putvar implementation doesn't have a success flag,
44490 	 * add one and send to debug client?
44491 	 */
44492 	duk_debug_write_reply(thr);
44493 	duk_debug_write_eom(thr);
44494 }
44495 
44496 DUK_LOCAL void duk__debug_handle_get_call_stack(duk_hthread *thr, duk_heap *heap) {
44497 	duk_hthread *curr_thr = thr;
44498 	duk_activation *curr_act;
44499 	duk_uint_fast32_t pc;
44500 	duk_uint_fast32_t line;
44501 
44502 	DUK_ASSERT(thr != NULL);
44503 	DUK_UNREF(heap);
44504 
44505 	duk_debug_write_reply(thr);
44506 	while (curr_thr != NULL) {
44507 		for (curr_act = curr_thr->callstack_curr; curr_act != NULL; curr_act = curr_act->parent) {
44508 			/* PC/line semantics here are:
44509 			 *   - For callstack top we're conceptually between two
44510 			 *     opcodes and current PC indicates next line to
44511 			 *     execute, so report that (matches Status).
44512 			 *   - For other activations we're conceptually still
44513 			 *     executing the instruction at PC-1, so report that
44514 			 *     (matches error stacktrace behavior).
44515 			 *   - See: https://github.com/svaarala/duktape/issues/281
44516 			 */
44517 
44518 			/* XXX: optimize to use direct reads, i.e. avoid
44519 			 * value stack operations.
44520 			 */
44521 			duk_push_tval(thr, &curr_act->tv_func);
44522 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);
44523 			duk__debug_write_hstring_safe_top(thr);
44524 			duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
44525 			duk__debug_write_hstring_safe_top(thr);
44526 			pc = duk_hthread_get_act_curr_pc(thr, curr_act);
44527 			if (curr_act != curr_thr->callstack_curr && pc > 0) {
44528 				pc--;
44529 			}
44530 			line = duk_hobject_pc2line_query(thr, -3, pc);
44531 			duk_debug_write_uint(thr, (duk_uint32_t) line);
44532 			duk_debug_write_uint(thr, (duk_uint32_t) pc);
44533 			duk_pop_3(thr);
44534 		}
44535 		curr_thr = curr_thr->resumer;
44536 	}
44537 	/* SCANBUILD: warning about 'thr' potentially being NULL here,
44538 	 * warning is incorrect because thr != NULL always here.
44539 	 */
44540 	duk_debug_write_eom(thr);
44541 }
44542 
44543 DUK_LOCAL void duk__debug_handle_get_locals(duk_hthread *thr, duk_heap *heap) {
44544 	duk_activation *act;
44545 	duk_hstring *varname;
44546 
44547 	DUK_UNREF(heap);
44548 
44549 	act = duk__debug_read_level_get_activation(thr);
44550 	if (act == NULL) {
44551 		return;
44552 	}
44553 
44554 	duk_debug_write_reply(thr);
44555 
44556 	/* XXX: several nice-to-have improvements here:
44557 	 *   - Use direct reads avoiding value stack operations
44558 	 *   - Avoid triggering getters, indicate getter values to debug client
44559 	 *   - If side effects are possible, add error catching
44560 	 */
44561 
44562 	if (DUK_TVAL_IS_OBJECT(&act->tv_func)) {
44563 		duk_hobject *h_func = DUK_TVAL_GET_OBJECT(&act->tv_func);
44564 		duk_hobject *h_varmap;
44565 
44566 		h_varmap = duk_hobject_get_varmap(thr, h_func);
44567 		if (h_varmap != NULL) {
44568 			duk_push_hobject(thr, h_varmap);
44569 			duk_enum(thr, -1, 0 /*enum_flags*/);
44570 			while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
44571 				varname = duk_known_hstring(thr, -1);
44572 
44573 				duk_js_getvar_activation(thr, act, varname, 0 /*throw_flag*/);
44574 				/* [ ... func varmap enum key value this ] */
44575 				duk_debug_write_hstring(thr, duk_get_hstring(thr, -3));
44576 				duk_debug_write_tval(thr, duk_get_tval(thr, -2));
44577 				duk_pop_3(thr);  /* -> [ ... func varmap enum ] */
44578 			}
44579 		} else {
44580 			DUK_D(DUK_DPRINT("varmap missing in GetLocals, ignore"));
44581 		}
44582 	} else {
44583 		DUK_D(DUK_DPRINT("varmap is not an object in GetLocals, ignore"));
44584 	}
44585 
44586 	duk_debug_write_eom(thr);
44587 }
44588 
44589 DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {
44590 	duk_small_uint_t call_flags;
44591 	duk_int_t call_ret;
44592 	duk_small_int_t eval_err;
44593 	duk_bool_t direct_eval;
44594 	duk_int32_t level;
44595 	duk_idx_t idx_func;
44596 
44597 	DUK_UNREF(heap);
44598 
44599 	DUK_D(DUK_DPRINT("debug command Eval"));
44600 
44601 	/* The eval code is executed within the lexical environment of a specified
44602 	 * activation.  For now, use global object eval() function, with the eval
44603 	 * considered a 'direct call to eval'.
44604 	 *
44605 	 * Callstack index for debug commands only affects scope -- the callstack
44606 	 * as seen by, e.g. Duktape.act() will be the same regardless.
44607 	 */
44608 
44609 	/* nargs == 2 so we can pass a callstack index to eval(). */
44610 	idx_func = duk_get_top(thr);
44611 	duk_push_c_function(thr, duk_bi_global_object_eval, 2 /*nargs*/);
44612 	duk_push_undefined(thr);  /* 'this' binding shouldn't matter here */
44613 
44614 	/* Read callstack index, if non-null. */
44615 	if (duk_debug_peek_byte(thr) == DUK_DBG_IB_NULL) {
44616 		direct_eval = 0;
44617 		level = -1;  /* Not needed, but silences warning. */
44618 		(void) duk_debug_read_byte(thr);
44619 	} else {
44620 		direct_eval = 1;
44621 		level = duk__debug_read_validate_csindex(thr);
44622 		if (level == 0) {
44623 			return;
44624 		}
44625 	}
44626 
44627 	DUK_ASSERT(!direct_eval ||
44628 	           (level < 0 && -level <= (duk_int32_t) thr->callstack_top));
44629 
44630 	(void) duk_debug_read_hstring(thr);
44631 	if (direct_eval) {
44632 		duk_push_int(thr, level - 1);  /* compensate for eval() call */
44633 	}
44634 
44635 	/* [ ... eval "eval" eval_input level? ] */
44636 
44637 	call_flags = 0;
44638 	if (direct_eval) {
44639 		duk_activation *act;
44640 		duk_hobject *fun;
44641 
44642 		act = duk_hthread_get_activation_for_level(thr, level);
44643 		if (act != NULL) {
44644 			fun = DUK_ACT_GET_FUNC(act);
44645 			if (fun != NULL && DUK_HOBJECT_IS_COMPFUNC(fun)) {
44646 				/* Direct eval requires that there's a current
44647 				 * activation and it is an ECMAScript function.
44648 				 * When Eval is executed from e.g. cooperate API
44649 				 * call we'll need to do an indirect eval instead.
44650 				 */
44651 				call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
44652 			}
44653 		}
44654 	}
44655 
44656 	call_ret = duk_pcall_method_flags(thr, duk_get_top(thr) - (idx_func + 2), call_flags);
44657 
44658 	if (call_ret == DUK_EXEC_SUCCESS) {
44659 		eval_err = 0;
44660 		/* Use result value as is. */
44661 	} else {
44662 		/* For errors a string coerced result is most informative
44663 		 * right now, as the debug client doesn't have the capability
44664 		 * to traverse the error object.
44665 		 */
44666 		eval_err = 1;
44667 		duk_safe_to_string(thr, -1);
44668 	}
44669 
44670 	/* [ ... result ] */
44671 
44672 	duk_debug_write_reply(thr);
44673 	duk_debug_write_int(thr, (duk_int32_t) eval_err);
44674 	DUK_ASSERT(duk_get_tval(thr, -1) != NULL);
44675 	duk_debug_write_tval(thr, duk_get_tval(thr, -1));
44676 	duk_debug_write_eom(thr);
44677 }
44678 
44679 DUK_LOCAL void duk__debug_handle_detach(duk_hthread *thr, duk_heap *heap) {
44680 	DUK_UNREF(heap);
44681 	DUK_D(DUK_DPRINT("debug command Detach"));
44682 
44683 	duk_debug_write_reply(thr);
44684 	duk_debug_write_eom(thr);
44685 
44686 	DUK_D(DUK_DPRINT("debug connection detached, mark broken"));
44687 	DUK__SET_CONN_BROKEN(thr, 0);  /* not an error */
44688 }
44689 
44690 DUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {
44691 	duk_idx_t old_top;
44692 
44693 	DUK_D(DUK_DPRINT("debug command AppRequest"));
44694 
44695 	old_top = duk_get_top(thr);  /* save stack top */
44696 
44697 	if (heap->dbg_request_cb != NULL) {
44698 		duk_idx_t nrets;
44699 		duk_idx_t nvalues = 0;
44700 		duk_idx_t top, idx;
44701 
44702 		/* Read tvals from the message and push them onto the valstack,
44703 		 * then call the request callback to process the request.
44704 		 */
44705 		while (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
44706 			duk_tval *tv;
44707 			if (!duk_check_stack(thr, 1)) {
44708 				DUK_D(DUK_DPRINT("failed to allocate space for request dvalue(s)"));
44709 				goto fail;
44710 			}
44711 			tv = duk_debug_read_tval(thr);  /* push to stack */
44712 			if (tv == NULL) {
44713 				/* detached */
44714 				return;
44715 			}
44716 			nvalues++;
44717 		}
44718 		DUK_ASSERT(duk_get_top(thr) == old_top + nvalues);
44719 
44720 		/* Request callback should push values for reply to client onto valstack */
44721 		DUK_D(DUK_DPRINT("calling into AppRequest request_cb with nvalues=%ld, old_top=%ld, top=%ld",
44722 		                 (long) nvalues, (long) old_top, (long) duk_get_top(thr)));
44723 		nrets = heap->dbg_request_cb(thr, heap->dbg_udata, nvalues);
44724 		DUK_D(DUK_DPRINT("returned from AppRequest request_cb; nvalues=%ld -> nrets=%ld, old_top=%ld, top=%ld",
44725 		                 (long) nvalues, (long) nrets, (long) old_top, (long) duk_get_top(thr)));
44726 		if (nrets >= 0) {
44727 			DUK_ASSERT(duk_get_top(thr) >= old_top + nrets);
44728 			if (duk_get_top(thr) < old_top + nrets) {
44729 				DUK_D(DUK_DPRINT("AppRequest callback doesn't match value stack configuration, "
44730 				                 "top=%ld < old_top=%ld + nrets=%ld; "
44731 				                 "this might mean it's unsafe to continue!",
44732 				                 (long) duk_get_top(thr), (long) old_top, (long) nrets));
44733 				goto fail;
44734 			}
44735 
44736 			/* Reply with tvals pushed by request callback */
44737 			duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
44738 			top = duk_get_top(thr);
44739 			for (idx = top - nrets; idx < top; idx++) {
44740 				duk_debug_write_tval(thr, DUK_GET_TVAL_POSIDX(thr, idx));
44741 			}
44742 			duk_debug_write_eom(thr);
44743 		} else {
44744 			DUK_ASSERT(duk_get_top(thr) >= old_top + 1);
44745 			if (duk_get_top(thr) < old_top + 1) {
44746 				DUK_D(DUK_DPRINT("request callback return value doesn't match value stack configuration"));
44747 				goto fail;
44748 			}
44749 			duk_debug_write_error_eom(thr, DUK_DBG_ERR_APPLICATION, duk_get_string(thr, -1));
44750 		}
44751 
44752 		duk_set_top(thr, old_top);  /* restore stack top */
44753 	} else {
44754 		DUK_D(DUK_DPRINT("no request callback, treat AppRequest as unsupported"));
44755 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "AppRequest unsupported by target");
44756 	}
44757 
44758 	return;
44759 
44760  fail:
44761 	duk_set_top(thr, old_top);  /* restore stack top */
44762 	DUK__SET_CONN_BROKEN(thr, 1);
44763 }
44764 
44765 /*
44766  *  DumpHeap command
44767  */
44768 
44769 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
44770 /* XXX: this has some overlap with object inspection; remove this and make
44771  * DumpHeap return lists of heapptrs instead?
44772  */
44773 DUK_LOCAL void duk__debug_dump_heaphdr(duk_hthread *thr, duk_heap *heap, duk_heaphdr *hdr) {
44774 	DUK_UNREF(heap);
44775 
44776 	duk_debug_write_heapptr(thr, hdr);
44777 	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_TYPE(hdr));
44778 	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_FLAGS_RAW(hdr));
44779 #if defined(DUK_USE_REFERENCE_COUNTING)
44780 	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_REFCOUNT(hdr));
44781 #else
44782 	duk_debug_write_int(thr, (duk_int32_t) -1);
44783 #endif
44784 
44785 	switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
44786 	case DUK_HTYPE_STRING: {
44787 		duk_hstring *h = (duk_hstring *) hdr;
44788 
44789 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_BYTELEN(h));
44790 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_CHARLEN(h));
44791 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
44792 		duk_debug_write_hstring(thr, h);
44793 		break;
44794 	}
44795 	case DUK_HTYPE_OBJECT: {
44796 		duk_hobject *h = (duk_hobject *) hdr;
44797 		duk_hstring *k;
44798 		duk_uint_fast32_t i;
44799 
44800 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_CLASS_NUMBER(h));
44801 		duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
44802 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ESIZE(h));
44803 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ENEXT(h));
44804 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ASIZE(h));
44805 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_HSIZE(h));
44806 
44807 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
44808 			duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_E_GET_FLAGS(heap, h, i));
44809 			k = DUK_HOBJECT_E_GET_KEY(heap, h, i);
44810 			duk_debug_write_heapptr(thr, (duk_heaphdr *) k);
44811 			if (k == NULL) {
44812 				duk_debug_write_int(thr, 0);  /* isAccessor */
44813 				duk_debug_write_unused(thr);
44814 				continue;
44815 			}
44816 			if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
44817 				duk_debug_write_int(thr, 1);  /* isAccessor */
44818 				duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
44819 				duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
44820 			} else {
44821 				duk_debug_write_int(thr, 0);  /* isAccessor */
44822 
44823 				duk__debug_write_tval_heapptr(thr, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
44824 			}
44825 		}
44826 
44827 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
44828 			/* Note: array dump will include elements beyond
44829 			 * 'length'.
44830 			 */
44831 			duk__debug_write_tval_heapptr(thr, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
44832 		}
44833 		break;
44834 	}
44835 	case DUK_HTYPE_BUFFER: {
44836 		duk_hbuffer *h = (duk_hbuffer *) hdr;
44837 
44838 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HBUFFER_GET_SIZE(h));
44839 		duk_debug_write_buffer(thr, (const char *) DUK_HBUFFER_GET_DATA_PTR(heap, h), (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
44840 		break;
44841 	}
44842 	default: {
44843 		DUK_D(DUK_DPRINT("invalid htype: %d", (int) DUK_HEAPHDR_GET_TYPE(hdr)));
44844 	}
44845 	}
44846 }
44847 
44848 DUK_LOCAL void duk__debug_dump_heap_allocated(duk_hthread *thr, duk_heap *heap) {
44849 	duk_heaphdr *hdr;
44850 
44851 	hdr = heap->heap_allocated;
44852 	while (hdr != NULL) {
44853 		duk__debug_dump_heaphdr(thr, heap, hdr);
44854 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
44855 	}
44856 }
44857 
44858 DUK_LOCAL void duk__debug_dump_strtab(duk_hthread *thr, duk_heap *heap) {
44859 	duk_uint32_t i;
44860 	duk_hstring *h;
44861 
44862 	for (i = 0; i < heap->st_size; i++) {
44863 #if defined(DUK_USE_STRTAB_PTRCOMP)
44864 		h = DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, heap->strtable16[i]);
44865 #else
44866 		h = heap->strtable[i];
44867 #endif
44868 		while (h != NULL) {
44869 			duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
44870 			h = h->hdr.h_next;
44871 		}
44872 	}
44873 }
44874 
44875 DUK_LOCAL void duk__debug_handle_dump_heap(duk_hthread *thr, duk_heap *heap) {
44876 	DUK_D(DUK_DPRINT("debug command DumpHeap"));
44877 
44878 	duk_debug_write_reply(thr);
44879 	duk__debug_dump_heap_allocated(thr, heap);
44880 	duk__debug_dump_strtab(thr, heap);
44881 	duk_debug_write_eom(thr);
44882 }
44883 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
44884 
44885 DUK_LOCAL void duk__debug_handle_get_bytecode(duk_hthread *thr, duk_heap *heap) {
44886 	duk_activation *act;
44887 	duk_hcompfunc *fun = NULL;
44888 	duk_size_t i, n;
44889 	duk_tval *tv;
44890 	duk_hobject **fn;
44891 	duk_int32_t level = -1;
44892 	duk_uint8_t ibyte;
44893 
44894 	DUK_UNREF(heap);
44895 
44896 	DUK_D(DUK_DPRINT("debug command GetBytecode"));
44897 
44898 	ibyte = duk_debug_peek_byte(thr);
44899 	if (ibyte != DUK_DBG_IB_EOM) {
44900 		tv = duk_debug_read_tval(thr);
44901 		if (tv == NULL) {
44902 			/* detached */
44903 			return;
44904 		}
44905 		if (DUK_TVAL_IS_OBJECT(tv)) {
44906 			/* tentative, checked later */
44907 			fun = (duk_hcompfunc *) DUK_TVAL_GET_OBJECT(tv);
44908 			DUK_ASSERT(fun != NULL);
44909 		} else if (DUK_TVAL_IS_NUMBER(tv)) {
44910 			level = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv);
44911 		} else {
44912 			DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!T", tv));
44913 			goto fail_args;
44914 		}
44915 	}
44916 
44917 	if (fun == NULL) {
44918 		act = duk_hthread_get_activation_for_level(thr, level);
44919 		if (act == NULL) {
44920 			goto fail_index;
44921 		}
44922 		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
44923 	}
44924 
44925 	if (fun == NULL || !DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)) {
44926 		DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!O", fun));
44927 		goto fail_args;
44928 	}
44929 	DUK_ASSERT(fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun));
44930 
44931 	duk_debug_write_reply(thr);
44932 	n = DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap, fun);
44933 	duk_debug_write_int(thr, (duk_int32_t) n);
44934 	tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, fun);
44935 	for (i = 0; i < n; i++) {
44936 		duk_debug_write_tval(thr, tv);
44937 		tv++;
44938 	}
44939 	n = DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap, fun);
44940 	duk_debug_write_int(thr, (duk_int32_t) n);
44941 	fn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, fun);
44942 	for (i = 0; i < n; i++) {
44943 		duk_debug_write_hobject(thr, *fn);
44944 		fn++;
44945 	}
44946 	duk_debug_write_string(thr,
44947 	                       (const char *) DUK_HCOMPFUNC_GET_CODE_BASE(heap, fun),
44948 	                       (duk_size_t) DUK_HCOMPFUNC_GET_CODE_SIZE(heap, fun));
44949 	duk_debug_write_eom(thr);
44950 	return;
44951 
44952  fail_args:
44953 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid argument");
44954 	return;
44955 
44956  fail_index:
44957 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
44958 	return;
44959 }
44960 
44961 /*
44962  *  Object inspection commands: GetHeapObjInfo, GetObjPropDesc,
44963  *  GetObjPropDescRange
44964  */
44965 
44966 #if defined(DUK_USE_DEBUGGER_INSPECT)
44967 
44968 #if 0 /* pruned */
44969 DUK_LOCAL const char * const duk__debug_getinfo_heaphdr_keys[] = {
44970 	"reachable",
44971 	"temproot",
44972 	"finalizable",
44973 	"finalized",
44974 	"readonly"
44975 	/* NULL not needed here */
44976 };
44977 DUK_LOCAL duk_uint_t duk__debug_getinfo_heaphdr_masks[] = {
44978 	DUK_HEAPHDR_FLAG_REACHABLE,
44979 	DUK_HEAPHDR_FLAG_TEMPROOT,
44980 	DUK_HEAPHDR_FLAG_FINALIZABLE,
44981 	DUK_HEAPHDR_FLAG_FINALIZED,
44982 	DUK_HEAPHDR_FLAG_READONLY,
44983 	0  /* terminator */
44984 };
44985 #endif
44986 DUK_LOCAL const char * const duk__debug_getinfo_hstring_keys[] = {
44987 #if 0
44988 	"arridx",
44989 	"symbol",
44990 	"hidden",
44991 	"reserved_word",
44992 	"strict_reserved_word",
44993 	"eval_or_arguments",
44994 #endif
44995 	"extdata"
44996 	/* NULL not needed here */
44997 };
44998 DUK_LOCAL duk_uint_t duk__debug_getinfo_hstring_masks[] = {
44999 #if 0
45000 	DUK_HSTRING_FLAG_ARRIDX,
45001 	DUK_HSTRING_FLAG_SYMBOL,
45002 	DUK_HSTRING_FLAG_HIDDEN,
45003 	DUK_HSTRING_FLAG_RESERVED_WORD,
45004 	DUK_HSTRING_FLAG_STRICT_RESERVED_WORD,
45005 	DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS,
45006 #endif
45007 	DUK_HSTRING_FLAG_EXTDATA,
45008 	0  /* terminator */
45009 };
45010 DUK_LOCAL const char * const duk__debug_getinfo_hobject_keys[] = {
45011 	"extensible",
45012 	"constructable",
45013 	"callable",
45014 	"boundfunc",
45015 	"compfunc",
45016 	"natfunc",
45017 	"bufobj",
45018 	"fastrefs",
45019 	"array_part",
45020 	"strict",
45021 	"notail",
45022 	"newenv",
45023 	"namebinding",
45024 	"createargs",
45025 	"have_finalizer",
45026 	"exotic_array",
45027 	"exotic_stringobj",
45028 	"exotic_arguments",
45029 	"exotic_proxyobj",
45030 	"special_call"
45031 	/* NULL not needed here */
45032 };
45033 DUK_LOCAL duk_uint_t duk__debug_getinfo_hobject_masks[] = {
45034 	DUK_HOBJECT_FLAG_EXTENSIBLE,
45035 	DUK_HOBJECT_FLAG_CONSTRUCTABLE,
45036 	DUK_HOBJECT_FLAG_CALLABLE,
45037 	DUK_HOBJECT_FLAG_BOUNDFUNC,
45038 	DUK_HOBJECT_FLAG_COMPFUNC,
45039 	DUK_HOBJECT_FLAG_NATFUNC,
45040 	DUK_HOBJECT_FLAG_BUFOBJ,
45041 	DUK_HOBJECT_FLAG_FASTREFS,
45042 	DUK_HOBJECT_FLAG_ARRAY_PART,
45043 	DUK_HOBJECT_FLAG_STRICT,
45044 	DUK_HOBJECT_FLAG_NOTAIL,
45045 	DUK_HOBJECT_FLAG_NEWENV,
45046 	DUK_HOBJECT_FLAG_NAMEBINDING,
45047 	DUK_HOBJECT_FLAG_CREATEARGS,
45048 	DUK_HOBJECT_FLAG_HAVE_FINALIZER,
45049 	DUK_HOBJECT_FLAG_EXOTIC_ARRAY,
45050 	DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ,
45051 	DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS,
45052 	DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ,
45053 	DUK_HOBJECT_FLAG_SPECIAL_CALL,
45054 	0  /* terminator */
45055 };
45056 DUK_LOCAL const char * const duk__debug_getinfo_hbuffer_keys[] = {
45057 	"dynamic",
45058 	"external"
45059 	/* NULL not needed here */
45060 };
45061 DUK_LOCAL duk_uint_t duk__debug_getinfo_hbuffer_masks[] = {
45062 	DUK_HBUFFER_FLAG_DYNAMIC,
45063 	DUK_HBUFFER_FLAG_EXTERNAL,
45064 	0  /* terminator */
45065 };
45066 
45067 DUK_LOCAL void duk__debug_getinfo_flags_key(duk_hthread *thr, const char *key) {
45068 	duk_debug_write_uint(thr, 0);
45069 	duk_debug_write_cstring(thr, key);
45070 }
45071 
45072 DUK_LOCAL void duk__debug_getinfo_prop_uint(duk_hthread *thr, const char *key, duk_uint_t val) {
45073 	duk_debug_write_uint(thr, 0);
45074 	duk_debug_write_cstring(thr, key);
45075 	duk_debug_write_uint(thr, val);
45076 }
45077 
45078 DUK_LOCAL void duk__debug_getinfo_prop_int(duk_hthread *thr, const char *key, duk_int_t val) {
45079 	duk_debug_write_uint(thr, 0);
45080 	duk_debug_write_cstring(thr, key);
45081 	duk_debug_write_int(thr, val);
45082 }
45083 
45084 DUK_LOCAL void duk__debug_getinfo_prop_bool(duk_hthread *thr, const char *key, duk_bool_t val) {
45085 	duk_debug_write_uint(thr, 0);
45086 	duk_debug_write_cstring(thr, key);
45087 	duk_debug_write_boolean(thr, val);
45088 }
45089 
45090 DUK_LOCAL void duk__debug_getinfo_bitmask(duk_hthread *thr, const char * const * keys, duk_uint_t *masks, duk_uint_t flags) {
45091 	const char *key;
45092 	duk_uint_t mask;
45093 
45094 	for (;;) {
45095 		mask = *masks++;
45096 		if (mask == 0) {
45097 			break;
45098 		}
45099 		key = *keys++;
45100 		DUK_ASSERT(key != NULL);
45101 
45102 		DUK_DD(DUK_DDPRINT("inspect bitmask: key=%s, mask=0x%08lx, flags=0x%08lx", key, (unsigned long) mask, (unsigned long) flags));
45103 		duk__debug_getinfo_prop_bool(thr, key, flags & mask);
45104 	}
45105 }
45106 
45107 /* Inspect a property using a virtual index into a conceptual property list
45108  * consisting of (1) all array part items from [0,a_size[ (even when above
45109  * .length) and (2) all entry part items from [0,e_next[.  Unused slots are
45110  * indicated using dvalue 'unused'.
45111  */
45112 DUK_LOCAL duk_bool_t duk__debug_getprop_index(duk_hthread *thr, duk_heap *heap, duk_hobject *h_obj, duk_uint_t idx) {
45113 	duk_uint_t a_size;
45114 	duk_tval *tv;
45115 	duk_hstring *h_key;
45116 	duk_hobject *h_getset;
45117 	duk_uint_t flags;
45118 
45119 	DUK_UNREF(heap);
45120 
45121 	a_size = DUK_HOBJECT_GET_ASIZE(h_obj);
45122 	if (idx < a_size) {
45123 		duk_debug_write_uint(thr, DUK_PROPDESC_FLAGS_WEC);
45124 		duk_debug_write_uint(thr, idx);
45125 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, h_obj, idx);
45126 		duk_debug_write_tval(thr, tv);
45127 		return 1;
45128 	}
45129 
45130 	idx -= a_size;
45131 	if (idx >= DUK_HOBJECT_GET_ENEXT(h_obj)) {
45132 		return 0;
45133 	}
45134 
45135 	h_key = DUK_HOBJECT_E_GET_KEY(heap, h_obj, idx);
45136 	if (h_key == NULL) {
45137 		duk_debug_write_uint(thr, 0);
45138 		duk_debug_write_null(thr);
45139 		duk_debug_write_unused(thr);
45140 		return 1;
45141 	}
45142 
45143 	flags = DUK_HOBJECT_E_GET_FLAGS(heap, h_obj, idx);
45144 	if (DUK_HSTRING_HAS_SYMBOL(h_key)) {
45145 		flags |= DUK_DBG_PROPFLAG_SYMBOL;
45146 	}
45147 	if (DUK_HSTRING_HAS_HIDDEN(h_key)) {
45148 		flags |= DUK_DBG_PROPFLAG_HIDDEN;
45149 	}
45150 	duk_debug_write_uint(thr, flags);
45151 	duk_debug_write_hstring(thr, h_key);
45152 	if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
45153 		h_getset = DUK_HOBJECT_E_GET_VALUE_GETTER(heap, h_obj, idx);
45154 		if (h_getset) {
45155 			duk_debug_write_hobject(thr, h_getset);
45156 		} else {
45157 			duk_debug_write_null(thr);
45158 		}
45159 		h_getset = DUK_HOBJECT_E_GET_VALUE_SETTER(heap, h_obj, idx);
45160 		if (h_getset) {
45161 			duk_debug_write_hobject(thr, h_getset);
45162 		} else {
45163 			duk_debug_write_null(thr);
45164 		}
45165 	} else {
45166 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, h_obj, idx);
45167 		duk_debug_write_tval(thr, tv);
45168 	}
45169 	return 1;
45170 }
45171 
45172 DUK_LOCAL void duk__debug_handle_get_heap_obj_info(duk_hthread *thr, duk_heap *heap) {
45173 	duk_heaphdr *h;
45174 
45175 	DUK_D(DUK_DPRINT("debug command GetHeapObjInfo"));
45176 	DUK_UNREF(heap);
45177 
45178 	DUK_ASSERT(sizeof(duk__debug_getinfo_hstring_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hstring_masks) / sizeof(duk_uint_t) - 1);
45179 	DUK_ASSERT(sizeof(duk__debug_getinfo_hobject_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hobject_masks) / sizeof(duk_uint_t) - 1);
45180 	DUK_ASSERT(sizeof(duk__debug_getinfo_hbuffer_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hbuffer_masks) / sizeof(duk_uint_t) - 1);
45181 
45182 	h = duk_debug_read_any_ptr(thr);
45183 	if (!h) {
45184 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
45185 		return;
45186 	}
45187 
45188 	duk_debug_write_reply(thr);
45189 
45190 	/* As with all inspection code, we rely on the debug client providing
45191 	 * a valid, non-stale pointer: there's no portable way to safely
45192 	 * validate the pointer here.
45193 	 */
45194 
45195 	duk__debug_getinfo_flags_key(thr, "heapptr");
45196 	duk_debug_write_heapptr(thr, h);
45197 
45198 	/* XXX: comes out as signed now */
45199 	duk__debug_getinfo_prop_uint(thr, "heaphdr_flags", (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
45200 	duk__debug_getinfo_prop_uint(thr, "heaphdr_type", (duk_uint_t) DUK_HEAPHDR_GET_TYPE(h));
45201 #if defined(DUK_USE_REFERENCE_COUNTING)
45202 	duk__debug_getinfo_prop_uint(thr, "refcount", (duk_uint_t) DUK_HEAPHDR_GET_REFCOUNT(h));
45203 #endif
45204 #if 0 /* pruned */
45205 	duk__debug_getinfo_bitmask(thr,
45206 	                           duk__debug_getinfo_heaphdr_keys,
45207 	                           duk__debug_getinfo_heaphdr_masks,
45208 	                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
45209 #endif
45210 
45211 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
45212 	case DUK_HTYPE_STRING: {
45213 		duk_hstring *h_str;
45214 
45215 		h_str = (duk_hstring *) h;
45216 		duk__debug_getinfo_bitmask(thr,
45217 		                           duk__debug_getinfo_hstring_keys,
45218 		                           duk__debug_getinfo_hstring_masks,
45219 		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
45220 		duk__debug_getinfo_prop_uint(thr, "bytelen", (duk_uint_t) DUK_HSTRING_GET_BYTELEN(h_str));
45221 		duk__debug_getinfo_prop_uint(thr, "charlen", (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_str));
45222 		duk__debug_getinfo_prop_uint(thr, "hash", (duk_uint_t) DUK_HSTRING_GET_HASH(h_str));
45223 		duk__debug_getinfo_flags_key(thr, "data");
45224 		duk_debug_write_hstring(thr, h_str);
45225 		break;
45226 	}
45227 	case DUK_HTYPE_OBJECT: {
45228 		duk_hobject *h_obj;
45229 		duk_hobject *h_proto;
45230 
45231 		h_obj = (duk_hobject *) h;
45232 		h_proto = DUK_HOBJECT_GET_PROTOTYPE(heap, h_obj);
45233 
45234 		/* duk_hobject specific fields. */
45235 		duk__debug_getinfo_bitmask(thr,
45236 		                           duk__debug_getinfo_hobject_keys,
45237 		                           duk__debug_getinfo_hobject_masks,
45238 		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
45239 		duk__debug_getinfo_prop_uint(thr, "class_number", DUK_HOBJECT_GET_CLASS_NUMBER(h_obj));
45240 		duk__debug_getinfo_flags_key(thr, "class_name");
45241 		duk_debug_write_hstring(thr, DUK_HOBJECT_GET_CLASS_STRING(heap, h_obj));
45242 		duk__debug_getinfo_flags_key(thr, "prototype");
45243 		if (h_proto != NULL) {
45244 			duk_debug_write_hobject(thr, h_proto);
45245 		} else {
45246 			duk_debug_write_null(thr);
45247 		}
45248 		duk__debug_getinfo_flags_key(thr, "props");
45249 		duk_debug_write_pointer(thr, (void *) DUK_HOBJECT_GET_PROPS(heap, h_obj));
45250 		duk__debug_getinfo_prop_uint(thr, "e_size", (duk_uint_t) DUK_HOBJECT_GET_ESIZE(h_obj));
45251 		duk__debug_getinfo_prop_uint(thr, "e_next", (duk_uint_t) DUK_HOBJECT_GET_ENEXT(h_obj));
45252 		duk__debug_getinfo_prop_uint(thr, "a_size", (duk_uint_t) DUK_HOBJECT_GET_ASIZE(h_obj));
45253 		duk__debug_getinfo_prop_uint(thr, "h_size", (duk_uint_t) DUK_HOBJECT_GET_HSIZE(h_obj));
45254 
45255 		if (DUK_HOBJECT_IS_ARRAY(h_obj)) {
45256 			duk_harray *h_arr;
45257 			h_arr = (duk_harray *) h_obj;
45258 
45259 			duk__debug_getinfo_prop_uint(thr, "length", (duk_uint_t) h_arr->length);
45260 			duk__debug_getinfo_prop_bool(thr, "length_nonwritable", h_arr->length_nonwritable);
45261 		}
45262 
45263 		if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
45264 			duk_hnatfunc *h_fun;
45265 			h_fun = (duk_hnatfunc *) h_obj;
45266 
45267 			duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
45268 			duk__debug_getinfo_prop_int(thr, "magic", h_fun->magic);
45269 			duk__debug_getinfo_prop_bool(thr, "varargs", h_fun->magic == DUK_HNATFUNC_NARGS_VARARGS);
45270 			/* Native function pointer may be different from a void pointer,
45271 			 * and we serialize it from memory directly now (no byte swapping etc).
45272 			 */
45273 			duk__debug_getinfo_flags_key(thr, "funcptr");
45274 			duk_debug_write_buffer(thr, (const char *) &h_fun->func, sizeof(h_fun->func));
45275 		}
45276 
45277 		if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
45278 			duk_hcompfunc *h_fun;
45279 			duk_hbuffer *h_buf;
45280 			duk_hobject *h_lexenv;
45281 			duk_hobject *h_varenv;
45282 			h_fun = (duk_hcompfunc *) h_obj;
45283 
45284 			duk__debug_getinfo_prop_int(thr, "nregs", h_fun->nregs);
45285 			duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
45286 
45287 			duk__debug_getinfo_flags_key(thr, "lex_env");
45288 			h_lexenv = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, h_fun);
45289 			if (h_lexenv != NULL) {
45290 				duk_debug_write_hobject(thr, h_lexenv);
45291 			} else {
45292 				duk_debug_write_null(thr);
45293 			}
45294 			duk__debug_getinfo_flags_key(thr, "var_env");
45295 			h_varenv = DUK_HCOMPFUNC_GET_VARENV(thr->heap, h_fun);
45296 			if (h_varenv != NULL) {
45297 				duk_debug_write_hobject(thr, h_varenv);
45298 			} else {
45299 				duk_debug_write_null(thr);
45300 			}
45301 
45302 			duk__debug_getinfo_prop_uint(thr, "start_line", h_fun->start_line);
45303 			duk__debug_getinfo_prop_uint(thr, "end_line", h_fun->end_line);
45304 			h_buf = (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, h_fun);
45305 			if (h_buf != NULL) {
45306 				duk__debug_getinfo_flags_key(thr, "data");
45307 				duk_debug_write_heapptr(thr, (duk_heaphdr *) h_buf);
45308 			}
45309 		}
45310 
45311 		if (DUK_HOBJECT_IS_BOUNDFUNC(h_obj)) {
45312 			duk_hboundfunc *h_bfun;
45313 			h_bfun = (duk_hboundfunc *) (void *) h_obj;
45314 
45315 			duk__debug_getinfo_flags_key(thr, "target");
45316 			duk_debug_write_tval(thr, &h_bfun->target);
45317 			duk__debug_getinfo_flags_key(thr, "this_binding");
45318 			duk_debug_write_tval(thr, &h_bfun->this_binding);
45319 			duk__debug_getinfo_flags_key(thr, "nargs");
45320 			duk_debug_write_int(thr, h_bfun->nargs);
45321 			/* h_bfun->args not exposed now */
45322 		}
45323 
45324 		if (DUK_HOBJECT_IS_THREAD(h_obj)) {
45325 			/* XXX: Currently no inspection of threads, e.g. value stack, call
45326 			 * stack, catch stack, etc.
45327 			 */
45328 			duk_hthread *h_thr;
45329 			h_thr = (duk_hthread *) h_obj;
45330 			DUK_UNREF(h_thr);
45331 		}
45332 
45333 		if (DUK_HOBJECT_IS_DECENV(h_obj)) {
45334 			duk_hdecenv *h_env;
45335 			h_env = (duk_hdecenv *) h_obj;
45336 
45337 			duk__debug_getinfo_flags_key(thr, "thread");
45338 			duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->thread));
45339 			duk__debug_getinfo_flags_key(thr, "varmap");
45340 			duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->varmap));
45341 			duk__debug_getinfo_prop_uint(thr, "regbase", (duk_uint_t) h_env->regbase_byteoff);
45342 		}
45343 
45344 		if (DUK_HOBJECT_IS_OBJENV(h_obj)) {
45345 			duk_hobjenv *h_env;
45346 			h_env = (duk_hobjenv *) h_obj;
45347 
45348 			duk__debug_getinfo_flags_key(thr, "target");
45349 			duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->target));
45350 			duk__debug_getinfo_prop_bool(thr, "has_this", h_env->has_this);
45351 		}
45352 
45353 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
45354 		if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
45355 			duk_hbufobj *h_bufobj;
45356 			h_bufobj = (duk_hbufobj *) h_obj;
45357 
45358 			duk__debug_getinfo_prop_uint(thr, "slice_offset", h_bufobj->offset);
45359 			duk__debug_getinfo_prop_uint(thr, "slice_length", h_bufobj->length);
45360 			duk__debug_getinfo_prop_uint(thr, "elem_shift", (duk_uint_t) h_bufobj->shift);
45361 			duk__debug_getinfo_prop_uint(thr, "elem_type", (duk_uint_t) h_bufobj->elem_type);
45362 			duk__debug_getinfo_prop_bool(thr, "is_typedarray", (duk_uint_t) h_bufobj->is_typedarray);
45363 			if (h_bufobj->buf != NULL) {
45364 				duk__debug_getinfo_flags_key(thr, "buffer");
45365 				duk_debug_write_heapptr(thr, (duk_heaphdr *) h_bufobj->buf);
45366 			}
45367 		}
45368 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
45369 		break;
45370 	}
45371 	case DUK_HTYPE_BUFFER: {
45372 		duk_hbuffer *h_buf;
45373 
45374 		h_buf = (duk_hbuffer *) h;
45375 		duk__debug_getinfo_bitmask(thr,
45376 		                           duk__debug_getinfo_hbuffer_keys,
45377 		                           duk__debug_getinfo_hbuffer_masks,
45378 		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
45379 		duk__debug_getinfo_prop_uint(thr, "size", (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
45380 		duk__debug_getinfo_flags_key(thr, "dataptr");
45381 		duk_debug_write_pointer(thr, (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf));
45382 		duk__debug_getinfo_flags_key(thr, "data");
45383 		duk_debug_write_hbuffer(thr, h_buf);  /* tolerates NULL h_buf */
45384 		break;
45385 	}
45386 	default: {
45387 		/* Since we already started writing the reply, just emit nothing. */
45388 		DUK_D(DUK_DPRINT("inspect target pointer has invalid heaphdr type"));
45389 	}
45390 	}
45391 
45392 	duk_debug_write_eom(thr);
45393 }
45394 
45395 DUK_LOCAL void duk__debug_handle_get_obj_prop_desc(duk_hthread *thr, duk_heap *heap) {
45396 	duk_heaphdr *h;
45397 	duk_hobject *h_obj;
45398 	duk_hstring *h_key;
45399 	duk_propdesc desc;
45400 
45401 	DUK_D(DUK_DPRINT("debug command GetObjPropDesc"));
45402 	DUK_UNREF(heap);
45403 
45404 	h = duk_debug_read_any_ptr(thr);
45405 	if (!h) {
45406 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
45407 		return;
45408 	}
45409 	h_key = duk_debug_read_hstring(thr);
45410 	if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT || h_key == NULL) {
45411 		goto fail_args;
45412 	}
45413 	h_obj = (duk_hobject *) h;
45414 
45415 	if (duk_hobject_get_own_propdesc(thr, h_obj, h_key, &desc, 0 /*flags*/)) {
45416 		duk_int_t virtual_idx;
45417 		duk_bool_t rc;
45418 
45419 		/* To use the shared helper need the virtual index. */
45420 		DUK_ASSERT(desc.e_idx >= 0 || desc.a_idx >= 0);
45421 		virtual_idx = (desc.a_idx >= 0 ? desc.a_idx :
45422 		               (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj) + desc.e_idx);
45423 
45424 		duk_debug_write_reply(thr);
45425 		rc = duk__debug_getprop_index(thr, heap, h_obj, (duk_uint_t) virtual_idx);
45426 		DUK_ASSERT(rc == 1);
45427 		DUK_UNREF(rc);
45428 		duk_debug_write_eom(thr);
45429 	} else {
45430 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "not found");
45431 	}
45432 	return;
45433 
45434  fail_args:
45435 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
45436 }
45437 
45438 DUK_LOCAL void duk__debug_handle_get_obj_prop_desc_range(duk_hthread *thr, duk_heap *heap) {
45439 	duk_heaphdr *h;
45440 	duk_hobject *h_obj;
45441 	duk_uint_t idx, idx_start, idx_end;
45442 
45443 	DUK_D(DUK_DPRINT("debug command GetObjPropDescRange"));
45444 	DUK_UNREF(heap);
45445 
45446 	h = duk_debug_read_any_ptr(thr);
45447 	idx_start = (duk_uint_t) duk_debug_read_int(thr);
45448 	idx_end = (duk_uint_t) duk_debug_read_int(thr);
45449 	if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT) {
45450 		goto fail_args;
45451 	}
45452 	h_obj = (duk_hobject *) h;
45453 
45454 	/* The index range space is conceptually the array part followed by the
45455 	 * entry part.  Unlike normal enumeration all slots are exposed here as
45456 	 * is and return 'unused' if the slots are not in active use.  In particular
45457 	 * the array part is included for the full a_size regardless of what the
45458 	 * array .length is.
45459 	 */
45460 
45461 	duk_debug_write_reply(thr);
45462 	for (idx = idx_start; idx < idx_end; idx++) {
45463 		if (!duk__debug_getprop_index(thr, heap, h_obj, idx)) {
45464 			break;
45465 		}
45466 	}
45467 	duk_debug_write_eom(thr);
45468 	return;
45469 
45470  fail_args:
45471 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
45472 }
45473 
45474 #endif  /* DUK_USE_DEBUGGER_INSPECT */
45475 
45476 /*
45477  *  Process incoming debug requests
45478  *
45479  *  Individual request handlers can push temporaries on the value stack and
45480  *  rely on duk__debug_process_message() to restore the value stack top
45481  *  automatically.
45482  */
45483 
45484 /* Process one debug message.  Automatically restore value stack top to its
45485  * entry value, so that individual message handlers don't need exact value
45486  * stack handling which is convenient.
45487  */
45488 DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
45489 	duk_heap *heap;
45490 	duk_uint8_t x;
45491 	duk_int32_t cmd;
45492 	duk_idx_t entry_top;
45493 
45494 	DUK_ASSERT(thr != NULL);
45495 	heap = thr->heap;
45496 	DUK_ASSERT(heap != NULL);
45497 
45498 	entry_top = duk_get_top(thr);
45499 
45500 	x = duk_debug_read_byte(thr);
45501 	switch (x) {
45502 	case DUK_DBG_IB_REQUEST: {
45503 		cmd = duk_debug_read_int(thr);
45504 		switch (cmd) {
45505 		case DUK_DBG_CMD_BASICINFO: {
45506 			duk__debug_handle_basic_info(thr, heap);
45507 			break;
45508 		}
45509 		case DUK_DBG_CMD_TRIGGERSTATUS: {
45510 			duk__debug_handle_trigger_status(thr, heap);
45511 			break;
45512 		}
45513 		case DUK_DBG_CMD_PAUSE: {
45514 			duk__debug_handle_pause(thr, heap);
45515 			break;
45516 		}
45517 		case DUK_DBG_CMD_RESUME: {
45518 			duk__debug_handle_resume(thr, heap);
45519 			break;
45520 		}
45521 		case DUK_DBG_CMD_STEPINTO:
45522 		case DUK_DBG_CMD_STEPOVER:
45523 		case DUK_DBG_CMD_STEPOUT: {
45524 			duk__debug_handle_step(thr, heap, cmd);
45525 			break;
45526 		}
45527 		case DUK_DBG_CMD_LISTBREAK: {
45528 			duk__debug_handle_list_break(thr, heap);
45529 			break;
45530 		}
45531 		case DUK_DBG_CMD_ADDBREAK: {
45532 			duk__debug_handle_add_break(thr, heap);
45533 			break;
45534 		}
45535 		case DUK_DBG_CMD_DELBREAK: {
45536 			duk__debug_handle_del_break(thr, heap);
45537 			break;
45538 		}
45539 		case DUK_DBG_CMD_GETVAR: {
45540 			duk__debug_handle_get_var(thr, heap);
45541 			break;
45542 		}
45543 		case DUK_DBG_CMD_PUTVAR: {
45544 			duk__debug_handle_put_var(thr, heap);
45545 			break;
45546 		}
45547 		case DUK_DBG_CMD_GETCALLSTACK: {
45548 			duk__debug_handle_get_call_stack(thr, heap);
45549 			break;
45550 		}
45551 		case DUK_DBG_CMD_GETLOCALS: {
45552 			duk__debug_handle_get_locals(thr, heap);
45553 			break;
45554 		}
45555 		case DUK_DBG_CMD_EVAL: {
45556 			duk__debug_handle_eval(thr, heap);
45557 			break;
45558 		}
45559 		case DUK_DBG_CMD_DETACH: {
45560 			/* The actual detached_cb call is postponed to message loop so
45561 			 * we don't need any special precautions here (just skip to EOM
45562 			 * on the already closed connection).
45563 			 */
45564 			duk__debug_handle_detach(thr, heap);
45565 			break;
45566 		}
45567 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
45568 		case DUK_DBG_CMD_DUMPHEAP: {
45569 			duk__debug_handle_dump_heap(thr, heap);
45570 			break;
45571 		}
45572 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
45573 		case DUK_DBG_CMD_GETBYTECODE: {
45574 			duk__debug_handle_get_bytecode(thr, heap);
45575 			break;
45576 		}
45577 		case DUK_DBG_CMD_APPREQUEST: {
45578 			duk__debug_handle_apprequest(thr, heap);
45579 			break;
45580 		}
45581 #if defined(DUK_USE_DEBUGGER_INSPECT)
45582 		case DUK_DBG_CMD_GETHEAPOBJINFO: {
45583 			duk__debug_handle_get_heap_obj_info(thr, heap);
45584 			break;
45585 		}
45586 		case DUK_DBG_CMD_GETOBJPROPDESC: {
45587 			duk__debug_handle_get_obj_prop_desc(thr, heap);
45588 			break;
45589 		}
45590 		case DUK_DBG_CMD_GETOBJPROPDESCRANGE: {
45591 			duk__debug_handle_get_obj_prop_desc_range(thr, heap);
45592 			break;
45593 		}
45594 #endif  /* DUK_USE_DEBUGGER_INSPECT */
45595 		default: {
45596 			DUK_D(DUK_DPRINT("debug command unsupported: %d", (int) cmd));
45597 			duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "unsupported command");
45598 		}
45599 		}  /* switch cmd */
45600 		break;
45601 	}
45602 	case DUK_DBG_IB_REPLY: {
45603 		DUK_D(DUK_DPRINT("debug reply, skipping"));
45604 		break;
45605 	}
45606 	case DUK_DBG_IB_ERROR: {
45607 		DUK_D(DUK_DPRINT("debug error, skipping"));
45608 		break;
45609 	}
45610 	case DUK_DBG_IB_NOTIFY: {
45611 		DUK_D(DUK_DPRINT("debug notify, skipping"));
45612 		break;
45613 	}
45614 	default: {
45615 		DUK_D(DUK_DPRINT("invalid initial byte, drop connection: %d", (int) x));
45616 		goto fail;
45617 	}
45618 	}  /* switch initial byte */
45619 
45620 	DUK_ASSERT(duk_get_top(thr) >= entry_top);
45621 	duk_set_top(thr, entry_top);
45622 	duk__debug_skip_to_eom(thr);
45623 	return;
45624 
45625  fail:
45626 	DUK_ASSERT(duk_get_top(thr) >= entry_top);
45627 	duk_set_top(thr, entry_top);
45628 	DUK__SET_CONN_BROKEN(thr, 1);
45629 	return;
45630 }
45631 
45632 DUK_LOCAL void duk__check_resend_status(duk_hthread *thr) {
45633 	if (thr->heap->dbg_read_cb != NULL && thr->heap->dbg_state_dirty) {
45634 		duk_debug_send_status(thr);
45635 		thr->heap->dbg_state_dirty = 0;
45636 	}
45637 }
45638 
45639 DUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block) {
45640 #if defined(DUK_USE_ASSERTIONS)
45641 	duk_idx_t entry_top;
45642 #endif
45643 	duk_bool_t retval = 0;
45644 
45645 	DUK_ASSERT(thr != NULL);
45646 	DUK_ASSERT(thr->heap != NULL);
45647 #if defined(DUK_USE_ASSERTIONS)
45648 	entry_top = duk_get_top(thr);
45649 #endif
45650 
45651 	DUK_D(DUK_DPRINT("process debug messages: read_cb=%s, no_block=%ld, detaching=%ld, processing=%ld",
45652 	                 thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) no_block,
45653 	                 (long) thr->heap->dbg_detaching, (long) thr->heap->dbg_processing));
45654 	DUK_DD(DUK_DDPRINT("top at entry: %ld", (long) duk_get_top(thr)));
45655 
45656 	/* thr->heap->dbg_detaching may be != 0 if a debugger write outside
45657 	 * the message loop caused a transport error and detach1() to run.
45658 	 */
45659 	DUK_ASSERT(thr->heap->dbg_detaching == 0 || thr->heap->dbg_detaching == 1);
45660 	DUK_ASSERT(thr->heap->dbg_processing == 0);
45661 	thr->heap->dbg_processing = 1;
45662 
45663 	/* Ensure dirty state causes a Status even if never process any
45664 	 * messages.  This is expected by the bytecode executor when in
45665 	 * the running state.
45666 	 */
45667 	duk__check_resend_status(thr);
45668 
45669 	for (;;) {
45670 		/* Process messages until we're no longer paused or we peek
45671 		 * and see there's nothing to read right now.
45672 		 */
45673 		DUK_DD(DUK_DDPRINT("top at loop top: %ld", (long) duk_get_top(thr)));
45674 		DUK_ASSERT(thr->heap->dbg_processing == 1);
45675 
45676 		while (thr->heap->dbg_read_cb == NULL && thr->heap->dbg_detaching) {
45677 			/* Detach is pending; can be triggered from outside the
45678 			 * debugger loop (e.g. Status notify write error) or by
45679 			 * previous message handling.  Call detached callback
45680 			 * here, in a controlled state, to ensure a possible
45681 			 * reattach inside the detached_cb is handled correctly.
45682 			 *
45683 			 * Recheck for detach in a while loop: an immediate
45684 			 * reattach involves a call to duk_debugger_attach()
45685 			 * which writes a debugger handshake line immediately
45686 			 * inside the API call.  If the transport write fails
45687 			 * for that handshake, we can immediately end up in a
45688 			 * "transport broken, detaching" case several times here.
45689 			 * Loop back until we're either cleanly attached or
45690 			 * fully detached.
45691 			 *
45692 			 * NOTE: Reset dbg_processing = 1 forcibly, in case we
45693 			 * re-attached; duk_debugger_attach() sets dbg_processing
45694 			 * to 0 at the moment.
45695 			 */
45696 
45697 			DUK_D(DUK_DPRINT("detach pending (dbg_read_cb == NULL, dbg_detaching != 0), call detach2"));
45698 
45699 			duk__debug_do_detach2(thr->heap);
45700 			thr->heap->dbg_processing = 1;  /* may be set to 0 by duk_debugger_attach() inside callback */
45701 
45702 			DUK_D(DUK_DPRINT("after detach2 (and possible reattach): dbg_read_cb=%s, dbg_detaching=%ld",
45703 			                 thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) thr->heap->dbg_detaching));
45704 		}
45705 		DUK_ASSERT(thr->heap->dbg_detaching == 0);  /* true even with reattach */
45706 		DUK_ASSERT(thr->heap->dbg_processing == 1);  /* even after a detach and possible reattach */
45707 
45708 		if (thr->heap->dbg_read_cb == NULL) {
45709 			DUK_D(DUK_DPRINT("debug connection broken (and not detaching), stop processing messages"));
45710 			break;
45711 		}
45712 
45713 		if (!DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || no_block) {
45714 			if (!duk_debug_read_peek(thr)) {
45715 				/* Note: peek cannot currently trigger a detach
45716 				 * so the dbg_detaching == 0 assert outside the
45717 				 * loop is correct.
45718 				 */
45719 				DUK_D(DUK_DPRINT("processing debug message, peek indicated no data, stop processing messages"));
45720 				break;
45721 			}
45722 			DUK_D(DUK_DPRINT("processing debug message, peek indicated there is data, handle it"));
45723 		} else {
45724 			DUK_D(DUK_DPRINT("paused, process debug message, blocking if necessary"));
45725 		}
45726 
45727 		duk__check_resend_status(thr);
45728 		duk__debug_process_message(thr);
45729 		duk__check_resend_status(thr);
45730 
45731 		retval = 1;  /* processed one or more messages */
45732 	}
45733 
45734 	DUK_ASSERT(thr->heap->dbg_detaching == 0);
45735 	DUK_ASSERT(thr->heap->dbg_processing == 1);
45736 	thr->heap->dbg_processing = 0;
45737 
45738 	/* As an initial implementation, read flush after exiting the message
45739 	 * loop.  If transport is broken, this is a no-op (with debug logs).
45740 	 */
45741 	duk_debug_read_flush(thr);  /* this cannot initiate a detach */
45742 	DUK_ASSERT(thr->heap->dbg_detaching == 0);
45743 
45744 	DUK_DD(DUK_DDPRINT("top at exit: %ld", (long) duk_get_top(thr)));
45745 
45746 #if defined(DUK_USE_ASSERTIONS)
45747 	/* Easy to get wrong, so assert for it. */
45748 	DUK_ASSERT(entry_top == duk_get_top(thr));
45749 #endif
45750 
45751 	return retval;
45752 }
45753 
45754 /*
45755  *  Halt execution helper
45756  */
45757 
45758 /* Halt execution and enter a debugger message loop until execution is resumed
45759  * by the client.  PC for the current activation may be temporarily decremented
45760  * so that the "current" instruction will be shown by the client.  This helper
45761  * is callable from anywhere, also outside bytecode executor.
45762  */
45763 
45764 DUK_INTERNAL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc) {
45765 	duk_activation *act;
45766 	duk_hcompfunc *fun;
45767 	duk_instr_t *old_pc = NULL;
45768 
45769 	DUK_ASSERT(thr != NULL);
45770 	DUK_ASSERT(thr->heap != NULL);
45771 	DUK_ASSERT(duk_debug_is_attached(thr->heap));
45772 	DUK_ASSERT(thr->heap->dbg_processing == 0);
45773 	DUK_ASSERT(!duk_debug_is_paused(thr->heap));
45774 
45775 	duk_debug_set_paused(thr->heap);
45776 
45777 	act = thr->callstack_curr;
45778 
45779 	/* NOTE: act may be NULL if an error is thrown outside of any activation,
45780 	 * which may happen in the case of, e.g. syntax errors.
45781 	 */
45782 
45783 	/* Decrement PC if that was requested, this requires a PC sync. */
45784 	if (act != NULL) {
45785 		duk_hthread_sync_currpc(thr);
45786 		old_pc = act->curr_pc;
45787 		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
45788 
45789 		/* Short circuit if is safe: if act->curr_pc != NULL, 'fun' is
45790 		 * guaranteed to be a non-NULL ECMAScript function.
45791 		 */
45792 		DUK_ASSERT(act->curr_pc == NULL ||
45793 		           (fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)));
45794 		if (use_prev_pc &&
45795 		    act->curr_pc != NULL &&
45796 		    act->curr_pc > DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, fun)) {
45797 			act->curr_pc--;
45798 		}
45799 	}
45800 
45801 	/* Process debug messages until we are no longer paused. */
45802 
45803 	/* NOTE: This is a bit fragile.  It's important to ensure that
45804 	 * duk_debug_process_messages() never throws an error or
45805 	 * act->curr_pc will never be reset.
45806 	 */
45807 
45808 	thr->heap->dbg_state_dirty = 1;
45809 	while (DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {
45810 		DUK_ASSERT(duk_debug_is_attached(thr->heap));
45811 		DUK_ASSERT(thr->heap->dbg_processing == 0);
45812 		duk_debug_process_messages(thr, 0 /*no_block*/);
45813 	}
45814 
45815 	/* XXX: Decrementing and restoring act->curr_pc works now, but if the
45816 	 * debugger message loop gains the ability to adjust the current PC
45817 	 * (e.g. a forced jump) restoring the PC here will break.  Another
45818 	 * approach would be to use a state flag for the "decrement 1 from
45819 	 * topmost activation's PC" and take it into account whenever dealing
45820 	 * with PC values.
45821 	 */
45822 	if (act != NULL) {
45823 		act->curr_pc = old_pc;  /* restore PC */
45824 	}
45825 }
45826 
45827 /*
45828  *  Breakpoint management
45829  */
45830 
45831 DUK_INTERNAL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line) {
45832 	duk_heap *heap;
45833 	duk_breakpoint *b;
45834 
45835 	/* Caller must trigger recomputation of active breakpoint list.  To
45836 	 * ensure stale values are not used if that doesn't happen, clear the
45837 	 * active breakpoint list here.
45838 	 */
45839 
45840 	DUK_ASSERT(thr != NULL);
45841 	DUK_ASSERT(filename != NULL);
45842 	heap = thr->heap;
45843 	DUK_ASSERT(heap != NULL);
45844 
45845 	if (heap->dbg_breakpoint_count >= DUK_HEAP_MAX_BREAKPOINTS) {
45846 		DUK_D(DUK_DPRINT("failed to add breakpoint for %O:%ld, all breakpoint slots used",
45847 		                 (duk_heaphdr *) filename, (long) line));
45848 		return -1;
45849 	}
45850 	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
45851 	b = heap->dbg_breakpoints + (heap->dbg_breakpoint_count++);
45852 	b->filename = filename;
45853 	b->line = line;
45854 	DUK_HSTRING_INCREF(thr, filename);
45855 
45856 	return (duk_small_int_t) (heap->dbg_breakpoint_count - 1);  /* index */
45857 }
45858 
45859 DUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index) {
45860 	duk_heap *heap;
45861 	duk_hstring *h;
45862 	duk_breakpoint *b;
45863 	duk_size_t move_size;
45864 
45865 	/* Caller must trigger recomputation of active breakpoint list.  To
45866 	 * ensure stale values are not used if that doesn't happen, clear the
45867 	 * active breakpoint list here.
45868 	 */
45869 
45870 	DUK_ASSERT(thr != NULL);
45871 	heap = thr->heap;
45872 	DUK_ASSERT(heap != NULL);
45873 	DUK_ASSERT(duk_debug_is_attached(thr->heap));
45874 	DUK_ASSERT_DISABLE(breakpoint_index >= 0);  /* unsigned */
45875 
45876 	if (breakpoint_index >= heap->dbg_breakpoint_count) {
45877 		DUK_D(DUK_DPRINT("invalid breakpoint index: %ld", (long) breakpoint_index));
45878 		return 0;
45879 	}
45880 	b = heap->dbg_breakpoints + breakpoint_index;
45881 
45882 	h = b->filename;
45883 	DUK_ASSERT(h != NULL);
45884 
45885 	move_size = sizeof(duk_breakpoint) * (heap->dbg_breakpoint_count - breakpoint_index - 1);
45886 	duk_memmove((void *) b,
45887 	            (const void *) (b + 1),
45888 	            (size_t) move_size);
45889 
45890 	heap->dbg_breakpoint_count--;
45891 	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
45892 
45893 	DUK_HSTRING_DECREF(thr, h);  /* side effects */
45894 	DUK_UNREF(h);  /* w/o refcounting */
45895 
45896 	/* Breakpoint entries above the used area are left as garbage. */
45897 
45898 	return 1;
45899 }
45900 
45901 /*
45902  *  Misc state management
45903  */
45904 
45905 DUK_INTERNAL duk_bool_t duk_debug_is_attached(duk_heap *heap) {
45906 	return (heap->dbg_read_cb != NULL);
45907 }
45908 
45909 DUK_INTERNAL duk_bool_t duk_debug_is_paused(duk_heap *heap) {
45910 	return (DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) != 0);
45911 }
45912 
45913 DUK_INTERNAL void duk_debug_set_paused(duk_heap *heap) {
45914 	if (duk_debug_is_paused(heap)) {
45915 		DUK_D(DUK_DPRINT("trying to set paused state when already paused, ignoring"));
45916 	} else {
45917 		DUK_HEAP_SET_DEBUGGER_PAUSED(heap);
45918 		heap->dbg_state_dirty = 1;
45919 		duk_debug_clear_pause_state(heap);
45920 		DUK_ASSERT(heap->ms_running == 0);  /* debugger can't be triggered within mark-and-sweep */
45921 		heap->ms_running = 2;  /* prevent mark-and-sweep, prevent refzero queueing */
45922 		heap->ms_prevent_count++;
45923 		DUK_ASSERT(heap->ms_prevent_count != 0);  /* Wrap. */
45924 		DUK_ASSERT(heap->heap_thread != NULL);
45925 	}
45926 }
45927 
45928 DUK_INTERNAL void duk_debug_clear_paused(duk_heap *heap) {
45929 	if (duk_debug_is_paused(heap)) {
45930 		DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap);
45931 		heap->dbg_state_dirty = 1;
45932 		duk_debug_clear_pause_state(heap);
45933 		DUK_ASSERT(heap->ms_running == 2);
45934 		DUK_ASSERT(heap->ms_prevent_count > 0);
45935 		heap->ms_prevent_count--;
45936 		heap->ms_running = 0;
45937 		DUK_ASSERT(heap->heap_thread != NULL);
45938 	} else {
45939 		DUK_D(DUK_DPRINT("trying to clear paused state when not paused, ignoring"));
45940 	}
45941 }
45942 
45943 DUK_INTERNAL void duk_debug_clear_pause_state(duk_heap *heap) {
45944 	heap->dbg_pause_flags = 0;
45945 	heap->dbg_pause_act = NULL;
45946 	heap->dbg_pause_startline = 0;
45947 }
45948 
45949 #else  /* DUK_USE_DEBUGGER_SUPPORT */
45950 
45951 /* No debugger support. */
45952 
45953 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
45954 
45955 /* automatic undefs */
45956 #undef DUK__DBG_TPORT_ENTER
45957 #undef DUK__DBG_TPORT_EXIT
45958 #undef DUK__SET_CONN_BROKEN
45959 /*
45960  *  Augmenting errors at their creation site and their throw site.
45961  *
45962  *  When errors are created, traceback data is added by built-in code
45963  *  and a user error handler (if defined) can process or replace the
45964  *  error.  Similarly, when errors are thrown, a user error handler
45965  *  (if defined) can process or replace the error.
45966  *
45967  *  Augmentation and other processing at error creation time is nice
45968  *  because an error is only created once, but it may be thrown and
45969  *  rethrown multiple times.  User error handler registered for processing
45970  *  an error at its throw site must be careful to handle rethrowing in
45971  *  a useful manner.
45972  *
45973  *  Error augmentation may throw an internal error (e.g. alloc error).
45974  *
45975  *  ECMAScript allows throwing any values, so all values cannot be
45976  *  augmented.  Currently, the built-in augmentation at error creation
45977  *  only augments error values which are Error instances (= have the
45978  *  built-in Error.prototype in their prototype chain) and are also
45979  *  extensible.  User error handlers have no limitations in this respect.
45980  */
45981 
45982 /* #include duk_internal.h -> already included */
45983 
45984 /*
45985  *  Helper for calling a user error handler.
45986  *
45987  *  'thr' must be the currently active thread; the error handler is called
45988  *  in its context.  The valstack of 'thr' must have the error value on
45989  *  top, and will be replaced by another error value based on the return
45990  *  value of the error handler.
45991  *
45992  *  The helper calls duk_handle_call() recursively in protected mode.
45993  *  Before that call happens, no longjmps should happen; as a consequence,
45994  *  we must assume that the valstack contains enough temporary space for
45995  *  arguments and such.
45996  *
45997  *  While the error handler runs, any errors thrown will not trigger a
45998  *  recursive error handler call (this is implemented using a heap level
45999  *  flag which will "follow" through any coroutines resumed inside the
46000  *  error handler).  If the error handler is not callable or throws an
46001  *  error, the resulting error replaces the original error (for Duktape
46002  *  internal errors, duk_error_throw.c further substitutes this error with
46003  *  a DoubleError which is not ideal).  This would be easy to change and
46004  *  even signal to the caller.
46005  *
46006  *  The user error handler is stored in 'Duktape.errCreate' or
46007  *  'Duktape.errThrow' depending on whether we're augmenting the error at
46008  *  creation or throw time.  There are several alternatives to this approach,
46009  *  see doc/error-objects.rst for discussion.
46010  *
46011  *  Note: since further longjmp()s may occur while calling the error handler
46012  *  (for many reasons, e.g. a labeled 'break' inside the handler), the
46013  *  caller can make no assumptions on the thr->heap->lj state after the
46014  *  call (this affects especially duk_error_throw.c).  This is not an issue
46015  *  as long as the caller writes to the lj state only after the error handler
46016  *  finishes.
46017  */
46018 
46019 #if defined(DUK_USE_ERRTHROW) || defined(DUK_USE_ERRCREATE)
46020 DUK_LOCAL void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_cb) {
46021 	duk_tval *tv_hnd;
46022 	duk_int_t rc;
46023 
46024 	DUK_ASSERT(thr != NULL);
46025 	DUK_ASSERT(thr->heap != NULL);
46026 	DUK_ASSERT_STRIDX_VALID(stridx_cb);
46027 
46028 	if (thr->heap->augmenting_error) {
46029 		DUK_D(DUK_DPRINT("recursive call to error augmentation, ignore"));
46030 		return;
46031 	}
46032 
46033 	/*
46034 	 *  Check whether or not we have an error handler.
46035 	 *
46036 	 *  We must be careful of not triggering an error when looking up the
46037 	 *  property.  For instance, if the property is a getter, we don't want
46038 	 *  to call it, only plain values are allowed.  The value, if it exists,
46039 	 *  is not checked.  If the value is not a function, a TypeError happens
46040 	 *  when it is called and that error replaces the original one.
46041 	 */
46042 
46043 	DUK_ASSERT_VALSTACK_SPACE(thr, 4);  /* 3 entries actually needed below */
46044 
46045 	/* [ ... errval ] */
46046 
46047 	if (thr->builtins[DUK_BIDX_DUKTAPE] == NULL) {
46048 		/* When creating built-ins, some of the built-ins may not be set
46049 		 * and we want to tolerate that when throwing errors.
46050 		 */
46051 		DUK_DD(DUK_DDPRINT("error occurred when DUK_BIDX_DUKTAPE is NULL, ignoring"));
46052 		return;
46053 	}
46054 	tv_hnd = duk_hobject_find_entry_tval_ptr_stridx(thr->heap,
46055 	                                                thr->builtins[DUK_BIDX_DUKTAPE],
46056 	                                                stridx_cb);
46057 	if (tv_hnd == NULL) {
46058 		DUK_DD(DUK_DDPRINT("error handler does not exist or is not a plain value: %!T",
46059 		                   (duk_tval *) tv_hnd));
46060 		return;
46061 	}
46062 	DUK_DDD(DUK_DDDPRINT("error handler dump (callability not checked): %!T",
46063 	                     (duk_tval *) tv_hnd));
46064 	duk_push_tval(thr, tv_hnd);
46065 
46066 	/* [ ... errval errhandler ] */
46067 
46068 	duk_insert(thr, -2);  /* -> [ ... errhandler errval ] */
46069 	duk_push_undefined(thr);
46070 	duk_insert(thr, -2);  /* -> [ ... errhandler undefined(= this) errval ] */
46071 
46072 	/* [ ... errhandler undefined errval ] */
46073 
46074 	/*
46075 	 *  heap->augmenting_error prevents recursive re-entry and also causes
46076 	 *  call handling to use a larger (but not unbounded) call stack limit
46077 	 *  for the duration of error augmentation.
46078 	 *
46079 	 *  We ignore errors now: a success return and an error value both
46080 	 *  replace the original error value.  (This would be easy to change.)
46081 	 */
46082 
46083 	DUK_ASSERT(thr->heap->augmenting_error == 0);
46084 	thr->heap->augmenting_error = 1;
46085 
46086 	rc = duk_pcall_method(thr, 1);
46087 	DUK_UNREF(rc);  /* no need to check now: both success and error are OK */
46088 
46089 	DUK_ASSERT(thr->heap->augmenting_error == 1);
46090 	thr->heap->augmenting_error = 0;
46091 
46092 	/* [ ... errval ] */
46093 }
46094 #endif  /* DUK_USE_ERRTHROW || DUK_USE_ERRCREATE */
46095 
46096 /*
46097  *  Add ._Tracedata to an error on the stack top.
46098  */
46099 
46100 #if defined(DUK_USE_TRACEBACKS)
46101 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) {
46102 	duk_activation *act;
46103 	duk_int_t depth;
46104 	duk_int_t arr_size;
46105 	duk_tval *tv;
46106 	duk_hstring *s;
46107 	duk_uint32_t u32;
46108 	duk_double_t d;
46109 
46110 	DUK_ASSERT(thr != NULL);
46111 	DUK_ASSERT(thr_callstack != NULL);
46112 
46113 	/* [ ... error ] */
46114 
46115 	/*
46116 	 *  The traceback format is pretty arcane in an attempt to keep it compact
46117 	 *  and cheap to create.  It may change arbitrarily from version to version.
46118 	 *  It should be decoded/accessed through version specific accessors only.
46119 	 *
46120 	 *  See doc/error-objects.rst.
46121 	 */
46122 
46123 	DUK_DDD(DUK_DDDPRINT("adding traceback to object: %!T",
46124 	                     (duk_tval *) duk_get_tval(thr, -1)));
46125 
46126 	/* Preallocate array to correct size, so that we can just write out
46127 	 * the _Tracedata values into the array part.
46128 	 */
46129 	act = thr->callstack_curr;
46130 	depth = DUK_USE_TRACEBACK_DEPTH;
46131 	DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX);  /* callstack limits */
46132 	if (depth > (duk_int_t) thr_callstack->callstack_top) {
46133 		depth = (duk_int_t) thr_callstack->callstack_top;
46134 	}
46135 	if (depth > 0) {
46136 		if (flags & DUK_AUGMENT_FLAG_SKIP_ONE) {
46137 			DUK_ASSERT(act != NULL);
46138 			act = act->parent;
46139 			depth--;
46140 		}
46141 	}
46142 	arr_size = depth * 2;
46143 	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
46144 		arr_size += 2;
46145 	}
46146 	if (c_filename) {
46147 		/* We need the C filename to be interned before getting the
46148 		 * array part pointer to avoid any GC interference while the
46149 		 * array part is populated.
46150 		 */
46151 		duk_push_string(thr, c_filename);
46152 		arr_size += 2;
46153 	}
46154 
46155 	/* XXX: Uninitialized would be OK.  Maybe add internal primitive to
46156 	 * push bare duk_harray with size?
46157 	 */
46158 	DUK_D(DUK_DPRINT("preallocated _Tracedata to %ld items", (long) arr_size));
46159 	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) arr_size);
46160 	duk_clear_prototype(thr, -1);
46161 	DUK_ASSERT(duk_is_bare_object(thr, -1));
46162 	DUK_ASSERT(arr_size == 0 || tv != NULL);
46163 
46164 	/* Compiler SyntaxErrors (and other errors) come first, and are
46165 	 * blamed by default (not flagged "noblame").
46166 	 */
46167 	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
46168 		s = thr->compile_ctx->h_filename;
46169 		DUK_TVAL_SET_STRING(tv, s);
46170 		DUK_HSTRING_INCREF(thr, s);
46171 		tv++;
46172 
46173 		u32 = (duk_uint32_t) thr->compile_ctx->curr_token.start_line;  /* (flags<<32) + (line), flags = 0 */
46174 		DUK_TVAL_SET_U32(tv, u32);
46175 		tv++;
46176 	}
46177 
46178 	/* Filename/line from C macros (__FILE__, __LINE__) are added as an
46179 	 * entry with a special format: (string, number).  The number contains
46180 	 * the line and flags.
46181 	 */
46182 
46183 	/* [ ... error c_filename? arr ] */
46184 
46185 	if (c_filename) {
46186 		DUK_ASSERT(DUK_TVAL_IS_STRING(thr->valstack_top - 2));
46187 		s = DUK_TVAL_GET_STRING(thr->valstack_top - 2);  /* interned c_filename */
46188 		DUK_ASSERT(s != NULL);
46189 		DUK_TVAL_SET_STRING(tv, s);
46190 		DUK_HSTRING_INCREF(thr, s);
46191 		tv++;
46192 
46193 		d = ((flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE) ? ((duk_double_t) DUK_TB_FLAG_NOBLAME_FILELINE) * DUK_DOUBLE_2TO32 : 0.0) +
46194 		    (duk_double_t) c_line;
46195 		DUK_TVAL_SET_DOUBLE(tv, d);
46196 		tv++;
46197 	}
46198 
46199 	/* Traceback depth doesn't take into account the filename/line
46200 	 * special handling above (intentional).
46201 	 */
46202 	for (; depth-- > 0; act = act->parent) {
46203 		duk_uint32_t pc;
46204 		duk_tval *tv_src;
46205 
46206 		/* [... arr] */
46207 
46208 		DUK_ASSERT(act != NULL);  /* depth check above, assumes book-keeping is correct */
46209 		DUK_ASSERT_DISABLE(act->pc >= 0);  /* unsigned */
46210 
46211 		/* Add function object. */
46212 		tv_src = &act->tv_func;  /* object (function) or lightfunc */
46213 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_src) || DUK_TVAL_IS_LIGHTFUNC(tv_src));
46214 		DUK_TVAL_SET_TVAL(tv, tv_src);
46215 		DUK_TVAL_INCREF(thr, tv);
46216 		tv++;
46217 
46218 		/* Add a number containing: pc, activation flags.
46219 		 *
46220 		 * PC points to next instruction, find offending PC.  Note that
46221 		 * PC == 0 for native code.
46222 		 */
46223 		pc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr_callstack, act);
46224 		DUK_ASSERT_DISABLE(pc >= 0);  /* unsigned */
46225 		DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32);  /* assume PC is at most 32 bits and non-negative */
46226 		d = ((duk_double_t) act->flags) * DUK_DOUBLE_2TO32 + (duk_double_t) pc;
46227 		DUK_TVAL_SET_DOUBLE(tv, d);
46228 		tv++;
46229 	}
46230 
46231 #if defined(DUK_USE_ASSERTIONS)
46232 	{
46233 		duk_harray *a;
46234 		a = (duk_harray *) duk_known_hobject(thr, -1);
46235 		DUK_ASSERT(a != NULL);
46236 		DUK_ASSERT((duk_uint32_t) (tv - DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a)) == a->length);
46237 		DUK_ASSERT(a->length == (duk_uint32_t) arr_size);
46238 		DUK_ASSERT(duk_is_bare_object(thr, -1));
46239 	}
46240 #endif
46241 
46242 	/* [ ... error c_filename? arr ] */
46243 
46244 	if (c_filename) {
46245 		duk_remove_m2(thr);
46246 	}
46247 
46248 	/* [ ... error arr ] */
46249 
46250 	duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INT_TRACEDATA);  /* -> [ ... error ] */
46251 }
46252 #endif  /* DUK_USE_TRACEBACKS */
46253 
46254 /*
46255  *  Add .fileName and .lineNumber to an error on the stack top.
46256  */
46257 
46258 #if defined(DUK_USE_AUGMENT_ERROR_CREATE) && !defined(DUK_USE_TRACEBACKS)
46259 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) {
46260 #if defined(DUK_USE_ASSERTIONS)
46261 	duk_int_t entry_top;
46262 #endif
46263 
46264 #if defined(DUK_USE_ASSERTIONS)
46265 	entry_top = duk_get_top(thr);
46266 #endif
46267 
46268 	/*
46269 	 *  If tracebacks are disabled, 'fileName' and 'lineNumber' are added
46270 	 *  as plain own properties.  Since Error.prototype has accessors of
46271 	 *  the same name, we need to define own properties directly (cannot
46272 	 *  just use e.g. duk_put_prop_stridx).  Existing properties are not
46273 	 *  overwritten in case they already exist.
46274 	 */
46275 
46276 	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
46277 		/* Compiler SyntaxError (or other error) gets the primary blame.
46278 		 * Currently no flag to prevent blaming.
46279 		 */
46280 		duk_push_uint(thr, (duk_uint_t) thr->compile_ctx->curr_token.start_line);
46281 		duk_push_hstring(thr, thr->compile_ctx->h_filename);
46282 	} else if (c_filename && (flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE) == 0) {
46283 		/* C call site gets blamed next, unless flagged not to do so.
46284 		 * XXX: file/line is disabled in minimal builds, so disable this
46285 		 * too when appropriate.
46286 		 */
46287 		duk_push_int(thr, c_line);
46288 		duk_push_string(thr, c_filename);
46289 	} else {
46290 		/* Finally, blame the innermost callstack entry which has a
46291 		 * .fileName property.
46292 		 */
46293 		duk_small_uint_t depth;
46294 		duk_uint32_t ecma_line;
46295 		duk_activation *act;
46296 
46297 		DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX);  /* callstack limits */
46298 		depth = DUK_USE_TRACEBACK_DEPTH;
46299 		if (depth > thr_callstack->callstack_top) {
46300 			depth = thr_callstack->callstack_top;
46301 		}
46302 		for (act = thr_callstack->callstack_curr; depth-- > 0; act = act->parent) {
46303 			duk_hobject *func;
46304 			duk_uint32_t pc;
46305 
46306 			DUK_ASSERT(act != NULL);
46307 			func = DUK_ACT_GET_FUNC(act);
46308 			if (func == NULL) {
46309 				/* Lightfunc, not blamed now. */
46310 				continue;
46311 			}
46312 
46313 			/* PC points to next instruction, find offending PC,
46314 			 * PC == 0 for native code.
46315 			 */
46316 			pc = duk_hthread_get_act_prev_pc(thr, act);  /* thr argument only used for thr->heap, so specific thread doesn't matter */
46317 			DUK_UNREF(pc);
46318 			DUK_ASSERT_DISABLE(pc >= 0);  /* unsigned */
46319 			DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32);  /* assume PC is at most 32 bits and non-negative */
46320 
46321 			duk_push_hobject(thr, func);
46322 
46323 			/* [ ... error func ] */
46324 
46325 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);
46326 			if (!duk_is_string_notsymbol(thr, -1)) {
46327 				duk_pop_2(thr);
46328 				continue;
46329 			}
46330 
46331 			/* [ ... error func fileName ] */
46332 
46333 			ecma_line = 0;
46334 #if defined(DUK_USE_PC2LINE)
46335 			if (DUK_HOBJECT_IS_COMPFUNC(func)) {
46336 				ecma_line = duk_hobject_pc2line_query(thr, -2, (duk_uint_fast32_t) pc);
46337 			} else {
46338 				/* Native function, no relevant lineNumber. */
46339 			}
46340 #endif  /* DUK_USE_PC2LINE */
46341 			duk_push_u32(thr, ecma_line);
46342 
46343 			/* [ ... error func fileName lineNumber ] */
46344 
46345 			duk_replace(thr, -3);
46346 
46347 			/* [ ... error lineNumber fileName ] */
46348 			goto define_props;
46349 		}
46350 
46351 		/* No activation matches, use undefined for both .fileName and
46352 		 * .lineNumber (matches what we do with a _Tracedata based
46353 		 * no-match lookup.
46354 		 */
46355 		duk_push_undefined(thr);
46356 		duk_push_undefined(thr);
46357 	}
46358 
46359  define_props:
46360 	/* [ ... error lineNumber fileName ] */
46361 #if defined(DUK_USE_ASSERTIONS)
46362 	DUK_ASSERT(duk_get_top(thr) == entry_top + 2);
46363 #endif
46364 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C | DUK_PROPDESC_FLAG_NO_OVERWRITE);
46365 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LINE_NUMBER, DUK_PROPDESC_FLAGS_C | DUK_PROPDESC_FLAG_NO_OVERWRITE);
46366 }
46367 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE && !DUK_USE_TRACEBACKS */
46368 
46369 /*
46370  *  Add line number to a compiler error.
46371  */
46372 
46373 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
46374 DUK_LOCAL void duk__add_compiler_error_line(duk_hthread *thr) {
46375 
46376 	/* Append a "(line NNN)" to the "message" property of any error
46377 	 * thrown during compilation.  Usually compilation errors are
46378 	 * SyntaxErrors but they can also be out-of-memory errors and
46379 	 * the like.
46380 	 */
46381 
46382 	/* [ ... error ] */
46383 
46384 	DUK_ASSERT(duk_is_object(thr, -1));
46385 
46386 	if (!(thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL)) {
46387 		return;
46388 	}
46389 
46390 	DUK_DDD(DUK_DDDPRINT("compile error, before adding line info: %!T",
46391 	                     (duk_tval *) duk_get_tval(thr, -1)));
46392 
46393 	if (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_MESSAGE)) {
46394 		duk_push_sprintf(thr, " (line %ld)", (long) thr->compile_ctx->curr_token.start_line);
46395 		duk_concat(thr, 2);
46396 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE);
46397 	} else {
46398 		duk_pop(thr);
46399 	}
46400 
46401 	DUK_DDD(DUK_DDDPRINT("compile error, after adding line info: %!T",
46402 	                     (duk_tval *) duk_get_tval(thr, -1)));
46403 }
46404 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE */
46405 
46406 /*
46407  *  Augment an error being created using Duktape specific properties
46408  *  like _Tracedata or .fileName/.lineNumber.
46409  */
46410 
46411 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
46412 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) {
46413 #if defined(DUK_USE_ASSERTIONS)
46414 	duk_int_t entry_top;
46415 #endif
46416 
46417 #if defined(DUK_USE_ASSERTIONS)
46418 	entry_top = duk_get_top(thr);
46419 #endif
46420 	DUK_ASSERT(obj != NULL);
46421 
46422 	DUK_UNREF(obj);  /* unreferenced w/o tracebacks */
46423 
46424 	duk__add_compiler_error_line(thr);
46425 
46426 #if defined(DUK_USE_TRACEBACKS)
46427 	/* If tracebacks are enabled, the '_Tracedata' property is the only
46428 	 * thing we need: 'fileName' and 'lineNumber' are virtual properties
46429 	 * which use '_Tracedata'.  (Check _Tracedata only as own property.)
46430 	 */
46431 	if (duk_hobject_find_entry_tval_ptr_stridx(thr->heap, obj, DUK_STRIDX_INT_TRACEDATA) != NULL) {
46432 		DUK_DDD(DUK_DDDPRINT("error value already has a '_Tracedata' property, not modifying it"));
46433 	} else {
46434 		duk__add_traceback(thr, thr_callstack, c_filename, c_line, flags);
46435 	}
46436 #else
46437 	/* Without tracebacks the concrete .fileName and .lineNumber need
46438 	 * to be added directly.
46439 	 */
46440 	duk__add_fileline(thr, thr_callstack, c_filename, c_line, flags);
46441 #endif
46442 
46443 #if defined(DUK_USE_ASSERTIONS)
46444 	DUK_ASSERT(duk_get_top(thr) == entry_top);
46445 #endif
46446 }
46447 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE */
46448 
46449 /*
46450  *  Augment an error at creation time with _Tracedata/fileName/lineNumber
46451  *  and allow a user error handler (if defined) to process/replace the error.
46452  *  The error to be augmented is at the stack top.
46453  *
46454  *  thr: thread containing the error value
46455  *  thr_callstack: thread which should be used for generating callstack etc.
46456  *  c_filename: C __FILE__ related to the error
46457  *  c_line: C __LINE__ related to the error
46458  *  flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE:
46459  *      if true, don't fileName/line as error source, otherwise use traceback
46460  *      (needed because user code filename/line are reported but internal ones
46461  *      are not)
46462  */
46463 
46464 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
46465 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) {
46466 	duk_hobject *obj;
46467 
46468 	DUK_ASSERT(thr != NULL);
46469 	DUK_ASSERT(thr_callstack != NULL);
46470 
46471 	/* [ ... error ] */
46472 
46473 	/*
46474 	 *  Criteria for augmenting:
46475 	 *
46476 	 *   - augmentation enabled in build (naturally)
46477 	 *   - error value internal prototype chain contains the built-in
46478 	 *     Error prototype object (i.e. 'val instanceof Error')
46479 	 *
46480 	 *  Additional criteria for built-in augmenting:
46481 	 *
46482 	 *   - error value is an extensible object
46483 	 */
46484 
46485 	obj = duk_get_hobject(thr, -1);
46486 	if (!obj) {
46487 		DUK_DDD(DUK_DDDPRINT("value is not an object, skip both built-in and user augment"));
46488 		return;
46489 	}
46490 	if (!duk_hobject_prototype_chain_contains(thr, obj, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
46491 		/* If the value has a prototype loop, it's critical not to
46492 		 * throw here.  Instead, assume the value is not to be
46493 		 * augmented.
46494 		 */
46495 		DUK_DDD(DUK_DDDPRINT("value is not an error instance, skip both built-in and user augment"));
46496 		return;
46497 	}
46498 	if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
46499 		DUK_DDD(DUK_DDDPRINT("error meets criteria, built-in augment"));
46500 		duk__err_augment_builtin_create(thr, thr_callstack, c_filename, c_line, obj, flags);
46501 	} else {
46502 		DUK_DDD(DUK_DDDPRINT("error does not meet criteria, no built-in augment"));
46503 	}
46504 
46505 	/* [ ... error ] */
46506 
46507 #if defined(DUK_USE_ERRCREATE)
46508 	duk__err_augment_user(thr, DUK_STRIDX_ERR_CREATE);
46509 #endif
46510 }
46511 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE */
46512 
46513 /*
46514  *  Augment an error at throw time; allow a user error handler (if defined)
46515  *  to process/replace the error.  The error to be augmented is at the
46516  *  stack top.
46517  */
46518 
46519 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
46520 DUK_INTERNAL void duk_err_augment_error_throw(duk_hthread *thr) {
46521 #if defined(DUK_USE_ERRTHROW)
46522 	duk__err_augment_user(thr, DUK_STRIDX_ERR_THROW);
46523 #endif  /* DUK_USE_ERRTHROW */
46524 }
46525 #endif  /* DUK_USE_AUGMENT_ERROR_THROW */
46526 /*
46527  *  Do a longjmp call, calling the fatal error handler if no
46528  *  catchpoint exists.
46529  */
46530 
46531 /* #include duk_internal.h -> already included */
46532 
46533 #if defined(DUK_USE_PREFER_SIZE)
46534 DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_minimal(duk_hthread *thr));
46535 DUK_LOCAL void duk__uncaught_minimal(duk_hthread *thr) {
46536 	(void) duk_fatal(thr, "uncaught error");
46537 	DUK_WO_NORETURN(return;);
46538 }
46539 #endif
46540 
46541 #if 0
46542 DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_readable(duk_hthread *thr));
46543 DUK_LOCAL void duk__uncaught_readable(duk_hthread *thr) {
46544 	const char *summary;
46545 	char buf[DUK_USE_FATAL_MAXLEN];
46546 
46547 	summary = duk_push_string_tval_readable(thr, &thr->heap->lj.value1);
46548 	DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary);
46549 	buf[sizeof(buf) - 1] = (char) 0;
46550 	(void) duk_fatal(thr, (const char *) buf);
46551 	DUK_WO_NORETURN(return;);
46552 }
46553 #endif
46554 
46555 #if !defined(DUK_USE_PREFER_SIZE)
46556 DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_error_aware(duk_hthread *thr));
46557 DUK_LOCAL void duk__uncaught_error_aware(duk_hthread *thr) {
46558 	const char *summary;
46559 	char buf[DUK_USE_FATAL_MAXLEN];
46560 
46561 	summary = duk_push_string_tval_readable_error(thr, &thr->heap->lj.value1);
46562 	DUK_ASSERT(summary != NULL);
46563 	DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary);
46564 	buf[sizeof(buf) - 1] = (char) 0;
46565 	(void) duk_fatal(thr, (const char *) buf);
46566 	DUK_WO_NORETURN(return;);
46567 }
46568 #endif
46569 
46570 DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr) {
46571 	DUK_ASSERT(thr != NULL);
46572 	DUK_ASSERT(thr->heap != NULL);
46573 
46574 	DUK_DD(DUK_DDPRINT("longjmp error: type=%d iserror=%d value1=%!T value2=%!T",
46575 	                   (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
46576 	                   &thr->heap->lj.value1, &thr->heap->lj.value2));
46577 
46578 	/* Prevent finalizer execution during error handling.  All error
46579 	 * handling sites will process pending finalizers once error handling
46580 	 * is complete and we're ready for the side effects.  Does not prevent
46581 	 * refzero freeing or mark-and-sweep during error handling.
46582 	 *
46583 	 * NOTE: when we come here some calling code may have used DECREF
46584 	 * NORZ macros without an explicit DUK_REFZERO_CHECK_xxx() call.
46585 	 * We don't want to do it here because it would just check for
46586 	 * pending finalizers and we prevent that explicitly.  Instead,
46587 	 * the error catcher will run the finalizers once error handling
46588 	 * is complete.
46589 	 */
46590 
46591 	DUK_ASSERT_LJSTATE_SET(thr->heap);
46592 
46593 	thr->heap->pf_prevent_count++;
46594 	DUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */
46595 
46596 #if defined(DUK_USE_ASSERTIONS)
46597 	/* XXX: set this immediately when longjmp state is set */
46598 	DUK_ASSERT(thr->heap->error_not_allowed == 0);  /* Detect error within critical section. */
46599 	thr->heap->error_not_allowed = 1;
46600 #endif
46601 
46602 	DUK_DD(DUK_DDPRINT("about to longjmp, pf_prevent_count=%ld", (long) thr->heap->pf_prevent_count));
46603 
46604 	/* If we don't have a jmpbuf_ptr, there is little we can do except
46605 	 * cause a fatal error.  The caller's expectation is that we never
46606 	 * return.
46607 	 */
46608 	if (!thr->heap->lj.jmpbuf_ptr) {
46609 		DUK_D(DUK_DPRINT("uncaught error: type=%d iserror=%d value1=%!T value2=%!T",
46610 		                 (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
46611 		                 &thr->heap->lj.value1, &thr->heap->lj.value2));
46612 
46613 #if defined(DUK_USE_PREFER_SIZE)
46614 		duk__uncaught_minimal(thr);
46615 #else
46616 		duk__uncaught_error_aware(thr);
46617 #endif
46618 		DUK_UNREACHABLE();
46619 	}
46620 
46621 #if defined(DUK_USE_CPP_EXCEPTIONS)
46622 	throw duk_internal_exception();  /* dummy */
46623 #else
46624 	DUK_LONGJMP(thr->heap->lj.jmpbuf_ptr->jb);
46625 #endif
46626 
46627 	DUK_UNREACHABLE();
46628 }
46629 /*
46630  *  Error helpers
46631  */
46632 
46633 /* #include duk_internal.h -> already included */
46634 
46635 /*
46636  *  Helper to walk the thread chain and see if there is an active error
46637  *  catcher.  Protected calls or finally blocks aren't considered catching.
46638  */
46639 
46640 #if defined(DUK_USE_DEBUGGER_SUPPORT)
46641 DUK_LOCAL duk_bool_t duk__have_active_catcher(duk_hthread *thr) {
46642 	/* As noted above, a protected API call won't be counted as a
46643 	 * catcher.  This is usually convenient, e.g. in the case of a top-
46644 	 * level duk_pcall(), but may not always be desirable.  Perhaps add
46645 	 * an argument to treat them as catchers?
46646 	 */
46647 
46648 	duk_activation *act;
46649 	duk_catcher *cat;
46650 
46651 	DUK_ASSERT(thr != NULL);
46652 
46653 	for (; thr != NULL; thr = thr->resumer) {
46654 		for (act = thr->callstack_curr; act != NULL; act = act->parent) {
46655 			for (cat = act->cat; cat != NULL; cat = cat->parent) {
46656 				if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
46657 					return 1;  /* all we need to know */
46658 				}
46659 			}
46660 		}
46661 	}
46662 	return 0;
46663 }
46664 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
46665 
46666 /*
46667  *  Get prototype object for an integer error code.
46668  */
46669 
46670 DUK_INTERNAL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t code) {
46671 	switch (code) {
46672 	case DUK_ERR_EVAL_ERROR:
46673 		return thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE];
46674 	case DUK_ERR_RANGE_ERROR:
46675 		return thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE];
46676 	case DUK_ERR_REFERENCE_ERROR:
46677 		return thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE];
46678 	case DUK_ERR_SYNTAX_ERROR:
46679 		return thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE];
46680 	case DUK_ERR_TYPE_ERROR:
46681 		return thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE];
46682 	case DUK_ERR_URI_ERROR:
46683 		return thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE];
46684 	case DUK_ERR_ERROR:
46685 	default:
46686 		return thr->builtins[DUK_BIDX_ERROR_PROTOTYPE];
46687 	}
46688 }
46689 
46690 /*
46691  *  Helper for debugger throw notify and pause-on-uncaught integration.
46692  */
46693 
46694 #if defined(DUK_USE_DEBUGGER_SUPPORT)
46695 DUK_INTERNAL void duk_err_check_debugger_integration(duk_hthread *thr) {
46696 	duk_bool_t uncaught;
46697 	duk_tval *tv_obj;
46698 
46699 	/* If something is thrown with the debugger attached and nobody will
46700 	 * catch it, execution is paused before the longjmp, turning over
46701 	 * control to the debug client.  This allows local state to be examined
46702 	 * before the stack is unwound.  Errors are not intercepted when debug
46703 	 * message loop is active (e.g. for Eval).
46704 	 */
46705 
46706 	DUK_ASSERT(thr != NULL);
46707 	DUK_ASSERT(thr->heap != NULL);
46708 
46709 	/* XXX: Allow customizing the pause and notify behavior at runtime
46710 	 * using debugger runtime flags.  For now the behavior is fixed using
46711 	 * config options.
46712 	 */
46713 
46714 	if (!duk_debug_is_attached(thr->heap) ||
46715 	    thr->heap->dbg_processing ||
46716 	    thr->heap->lj.type != DUK_LJ_TYPE_THROW ||
46717 	    thr->heap->creating_error) {
46718 		DUK_D(DUK_DPRINT("skip debugger error integration; not attached, debugger processing, not THROW, or error thrown while creating error"));
46719 		return;
46720 	}
46721 
46722 	/* Don't intercept a DoubleError, we may have caused the initial double
46723 	 * fault and attempting to intercept it will cause us to be called
46724 	 * recursively and exhaust the C stack.  (This should no longer happen
46725 	 * for the initial throw because DoubleError path doesn't do a debugger
46726 	 * integration check, but it might happen for rethrows.)
46727 	 */
46728 	tv_obj = &thr->heap->lj.value1;
46729 	if (DUK_TVAL_IS_OBJECT(tv_obj) && DUK_TVAL_GET_OBJECT(tv_obj) == thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
46730 		DUK_D(DUK_DPRINT("built-in DoubleError instance (re)thrown, not intercepting"));
46731 		return;
46732 	}
46733 
46734 	uncaught = !duk__have_active_catcher(thr);
46735 
46736 	/* Debugger code expects the value at stack top.  This also serves
46737 	 * as a backup: we need to store/restore the longjmp state because
46738 	 * when the debugger is paused Eval commands may be executed and
46739 	 * they can arbitrarily clobber the longjmp state.
46740 	 */
46741 	duk_push_tval(thr, tv_obj);
46742 
46743 	/* Store and reset longjmp state. */
46744 	DUK_ASSERT_LJSTATE_SET(thr->heap);
46745 	DUK_TVAL_DECREF_NORZ(thr, tv_obj);
46746 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));  /* Always for THROW type. */
46747 	DUK_TVAL_SET_UNDEFINED(tv_obj);
46748 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
46749 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
46750 
46751 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
46752 	/* Report it to the debug client */
46753 	DUK_D(DUK_DPRINT("throw with debugger attached, report to client"));
46754 	duk_debug_send_throw(thr, uncaught);
46755 #endif
46756 
46757 	if (uncaught) {
46758 		if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_UNCAUGHT_ERROR) {
46759 			DUK_D(DUK_DPRINT("PAUSE TRIGGERED by uncaught error"));
46760 			duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
46761 		}
46762 	} else {
46763 		if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_CAUGHT_ERROR) {
46764 			DUK_D(DUK_DPRINT("PAUSE TRIGGERED by caught error"));
46765 			duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
46766 		}
46767 	}
46768 
46769 	/* Restore longjmp state. */
46770 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
46771 	thr->heap->lj.type = DUK_LJ_TYPE_THROW;
46772 	tv_obj = DUK_GET_TVAL_NEGIDX(thr, -1);
46773 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
46774 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
46775 	DUK_TVAL_SET_TVAL(&thr->heap->lj.value1, tv_obj);
46776 	DUK_TVAL_INCREF(thr, tv_obj);
46777 	DUK_ASSERT_LJSTATE_SET(thr->heap);
46778 
46779 	duk_pop(thr);
46780 }
46781 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
46782 
46783 /*
46784  *  Helpers for setting up heap longjmp state.
46785  */
46786 
46787 DUK_INTERNAL void duk_err_setup_ljstate1(duk_hthread *thr, duk_small_uint_t lj_type, duk_tval *tv_val) {
46788 	duk_heap *heap;
46789 
46790 	DUK_ASSERT(thr != NULL);
46791 	heap = thr->heap;
46792 	DUK_ASSERT(heap != NULL);
46793 	DUK_ASSERT(tv_val != NULL);
46794 
46795 	DUK_ASSERT_LJSTATE_UNSET(heap);
46796 
46797 	heap->lj.type = lj_type;
46798 	DUK_TVAL_SET_TVAL(&heap->lj.value1, tv_val);
46799 	DUK_TVAL_INCREF(thr, tv_val);
46800 
46801 	DUK_ASSERT_LJSTATE_SET(heap);
46802 }
46803 /*
46804  *  Create and throw an ECMAScript error object based on a code and a message.
46805  *
46806  *  Used when we throw errors internally.  ECMAScript generated error objects
46807  *  are created by ECMAScript code, and the throwing is handled by the bytecode
46808  *  executor.
46809  */
46810 
46811 /* #include duk_internal.h -> already included */
46812 
46813 /*
46814  *  Create and throw an error (originating from Duktape internally)
46815  *
46816  *  Push an error object on top of the stack, possibly throw augmenting
46817  *  the error, and finally longjmp.
46818  *
46819  *  If an error occurs while we're dealing with the current error, we might
46820  *  enter an infinite recursion loop.  This is prevented by detecting a
46821  *  "double fault" through the heap->creating_error flag; the recursion
46822  *  then stops at the second level.
46823  */
46824 
46825 #if defined(DUK_USE_VERBOSE_ERRORS)
46826 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) {
46827 #else
46828 DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code) {
46829 #endif
46830 #if defined(DUK_USE_VERBOSE_ERRORS)
46831 	DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld, msg=%s, filename=%s, line=%ld",
46832 	                   (long) code, (const char *) msg,
46833 	                   (const char *) filename, (long) line));
46834 #else
46835 	DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld", (long) code));
46836 #endif
46837 
46838 	DUK_ASSERT(thr != NULL);
46839 
46840 	/* Even though nested call is possible because we throw an error when
46841 	 * trying to create an error, the potential errors must happen before
46842 	 * the longjmp state is configured.
46843 	 */
46844 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
46845 
46846 	/* Sync so that augmentation sees up-to-date activations, NULL
46847 	 * thr->ptr_curr_pc so that it's not used if side effects occur
46848 	 * in augmentation or longjmp handling.
46849 	 */
46850 	duk_hthread_sync_and_null_currpc(thr);
46851 
46852 	/*
46853 	 *  Create and push an error object onto the top of stack.
46854 	 *  The error is potentially augmented before throwing.
46855 	 *
46856 	 *  If a "double error" occurs, use a fixed error instance
46857 	 *  to avoid further trouble.
46858 	 */
46859 
46860 	if (thr->heap->creating_error) {
46861 		duk_tval tv_val;
46862 		duk_hobject *h_err;
46863 
46864 		thr->heap->creating_error = 0;
46865 
46866 		h_err = thr->builtins[DUK_BIDX_DOUBLE_ERROR];
46867 		if (h_err != NULL) {
46868 			DUK_D(DUK_DPRINT("double fault detected -> use built-in fixed 'double error' instance"));
46869 			DUK_TVAL_SET_OBJECT(&tv_val, h_err);
46870 		} else {
46871 			DUK_D(DUK_DPRINT("double fault detected; there is no built-in fixed 'double error' instance "
46872 			                 "-> use the error code as a number"));
46873 			DUK_TVAL_SET_I32(&tv_val, (duk_int32_t) code);
46874 		}
46875 
46876 		duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, &tv_val);
46877 
46878 		/* No augmentation to avoid any allocations or side effects. */
46879 	} else {
46880 		/* Prevent infinite recursion.  Extra call stack and C
46881 		 * recursion headroom (see GH-191) is added for augmentation.
46882 		 * That is now signalled by heap->augmenting error and taken
46883 		 * into account in call handling without an explicit limit bump.
46884 		 */
46885 		thr->heap->creating_error = 1;
46886 
46887 		duk_require_stack(thr, 1);
46888 
46889 		/* XXX: usually unnecessary '%s' formatting here, but cannot
46890 		 * use 'msg' as a format string directly.
46891 		 */
46892 #if defined(DUK_USE_VERBOSE_ERRORS)
46893 		duk_push_error_object_raw(thr,
46894 		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
46895 		                          filename,
46896 		                          line,
46897 		                          "%s",
46898 		                          (const char *) msg);
46899 #else
46900 		duk_push_error_object_raw(thr,
46901 		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
46902 		                          NULL,
46903 		                          0,
46904 		                          NULL);
46905 #endif
46906 
46907 		/* Note that an alloc error may happen during error augmentation.
46908 		 * This may happen both when the original error is an alloc error
46909 		 * and when it's something else.  Because any error in augmentation
46910 		 * must be handled correctly anyway, there's no special check for
46911 		 * avoiding it for alloc errors (this differs from Duktape 1.x).
46912 		 */
46913 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
46914 		DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT (before throw augment)",
46915 		                     (duk_tval *) duk_get_tval(thr, -1)));
46916 		duk_err_augment_error_throw(thr);
46917 #endif
46918 
46919 		duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, DUK_GET_TVAL_NEGIDX(thr, -1));
46920 		thr->heap->creating_error = 0;
46921 
46922 		/* Error is now created and we assume no errors can occur any
46923 		 * more.  Check for debugger Throw integration only when the
46924 		 * error is complete.  If we enter debugger message loop,
46925 		 * creating_error must be 0 so that errors can be thrown in
46926 		 * the paused state, e.g. in Eval commands.
46927 		 */
46928 #if defined(DUK_USE_DEBUGGER_SUPPORT)
46929 		duk_err_check_debugger_integration(thr);
46930 #endif
46931 	}
46932 
46933 	/*
46934 	 *  Finally, longjmp
46935 	 */
46936 
46937 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT, %!iT (after throw augment)",
46938 	                     (duk_tval *) &thr->heap->lj.value1, (duk_tval *) &thr->heap->lj.value2));
46939 
46940 	duk_err_longjmp(thr);
46941 	DUK_UNREACHABLE();
46942 }
46943 
46944 /*
46945  *  Helper for C function call negative return values.
46946  */
46947 
46948 DUK_INTERNAL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc) {
46949 	DUK_ASSERT(thr != NULL);
46950 	DUK_ASSERT(rc < 0);
46951 
46952 	/*
46953 	 *  The __FILE__ and __LINE__ information is intentionally not used in the
46954 	 *  creation of the error object, as it isn't useful in the tracedata.  The
46955 	 *  tracedata still contains the function which returned the negative return
46956 	 *  code, and having the file/line of this function isn't very useful.
46957 	 *
46958 	 *  The error messages for DUK_RET_xxx shorthand are intentionally very
46959 	 *  minimal: they're only really useful for low memory targets.
46960 	 */
46961 
46962 	duk_error_raw(thr, -rc, NULL, 0, "error (rc %ld)", (long) rc);
46963 	DUK_WO_NORETURN(return;);
46964 }
46965 /*
46966  *  duk_hbuffer allocation and freeing.
46967  */
46968 
46969 /* #include duk_internal.h -> already included */
46970 
46971 /* Allocate a new duk_hbuffer of a certain type and return a pointer to it
46972  * (NULL on error).  Write buffer data pointer to 'out_bufdata' (only if
46973  * allocation successful).
46974  */
46975 DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata) {
46976 	duk_hbuffer *res = NULL;
46977 	duk_size_t header_size;
46978 	duk_size_t alloc_size;
46979 
46980 	DUK_ASSERT(heap != NULL);
46981 	DUK_ASSERT(out_bufdata != NULL);
46982 
46983 	DUK_DDD(DUK_DDDPRINT("allocate hbuffer"));
46984 
46985 	/* Size sanity check.  Should not be necessary because caller is
46986 	 * required to check this, but we don't want to cause a segfault
46987 	 * if the size wraps either in duk_size_t computation or when
46988 	 * storing the size in a 16-bit field.
46989 	 */
46990 	if (size > DUK_HBUFFER_MAX_BYTELEN) {
46991 		DUK_D(DUK_DPRINT("hbuffer alloc failed: size too large: %ld", (long) size));
46992 		return NULL;  /* no need to write 'out_bufdata' */
46993 	}
46994 
46995 	if (flags & DUK_BUF_FLAG_EXTERNAL) {
46996 		header_size = sizeof(duk_hbuffer_external);
46997 		alloc_size = sizeof(duk_hbuffer_external);
46998 	} else if (flags & DUK_BUF_FLAG_DYNAMIC) {
46999 		header_size = sizeof(duk_hbuffer_dynamic);
47000 		alloc_size = sizeof(duk_hbuffer_dynamic);
47001 	} else {
47002 		header_size = sizeof(duk_hbuffer_fixed);
47003 		alloc_size = sizeof(duk_hbuffer_fixed) + size;
47004 		DUK_ASSERT(alloc_size >= sizeof(duk_hbuffer_fixed));  /* no wrapping */
47005 	}
47006 
47007 	res = (duk_hbuffer *) DUK_ALLOC(heap, alloc_size);
47008 	if (DUK_UNLIKELY(res == NULL)) {
47009 		goto alloc_error;
47010 	}
47011 
47012 	/* zero everything unless requested not to do so */
47013 #if defined(DUK_USE_ZERO_BUFFER_DATA)
47014 	duk_memzero((void *) res,
47015 	            (flags & DUK_BUF_FLAG_NOZERO) ? header_size : alloc_size);
47016 #else
47017 	duk_memzero((void *) res, header_size);
47018 #endif
47019 
47020 	if (flags & DUK_BUF_FLAG_EXTERNAL) {
47021 		duk_hbuffer_external *h;
47022 		h = (duk_hbuffer_external *) res;
47023 		DUK_UNREF(h);
47024 		*out_bufdata = NULL;
47025 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
47026 #if defined(DUK_USE_HEAPPTR16)
47027 /* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
47028 #else
47029 		DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap, h, NULL);
47030 #endif
47031 #endif
47032 		DUK_ASSERT(DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap, h) == NULL);
47033 	} else if (flags & DUK_BUF_FLAG_DYNAMIC) {
47034 		duk_hbuffer_dynamic *h = (duk_hbuffer_dynamic *) res;
47035 		void *ptr;
47036 
47037 		if (size > 0) {
47038 			DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));  /* alloc external with size zero */
47039 			DUK_DDD(DUK_DDDPRINT("dynamic buffer with nonzero size, alloc actual buffer"));
47040 #if defined(DUK_USE_ZERO_BUFFER_DATA)
47041 			ptr = DUK_ALLOC_ZEROED(heap, size);
47042 #else
47043 			ptr = DUK_ALLOC(heap, size);
47044 #endif
47045 			if (DUK_UNLIKELY(ptr == NULL)) {
47046 				/* Because size > 0, NULL check is correct */
47047 				goto alloc_error;
47048 			}
47049 			*out_bufdata = ptr;
47050 
47051 			DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, ptr);
47052 		} else {
47053 			*out_bufdata = NULL;
47054 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
47055 #if defined(DUK_USE_HEAPPTR16)
47056 /* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
47057 #else
47058 			DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, NULL);
47059 #endif
47060 #endif
47061 			DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, h) == NULL);
47062 		}
47063 	} else {
47064 		*out_bufdata = (void *) ((duk_hbuffer_fixed *) (void *) res + 1);
47065 	}
47066 
47067 	DUK_HBUFFER_SET_SIZE(res, size);
47068 
47069 	DUK_HEAPHDR_SET_TYPE(&res->hdr, DUK_HTYPE_BUFFER);
47070 	if (flags & DUK_BUF_FLAG_DYNAMIC) {
47071 		DUK_HBUFFER_SET_DYNAMIC(res);
47072 		if (flags & DUK_BUF_FLAG_EXTERNAL) {
47073 			DUK_HBUFFER_SET_EXTERNAL(res);
47074 		}
47075 	} else {
47076 		DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));
47077 	}
47078         DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &res->hdr);
47079 
47080 	DUK_DDD(DUK_DDDPRINT("allocated hbuffer: %p", (void *) res));
47081 	return res;
47082 
47083  alloc_error:
47084 	DUK_DD(DUK_DDPRINT("hbuffer allocation failed"));
47085 
47086 	DUK_FREE(heap, res);
47087 	return NULL;  /* no need to write 'out_bufdata' */
47088 }
47089 
47090 /* For indirect allocs. */
47091 
47092 DUK_INTERNAL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud) {
47093 	duk_hbuffer_dynamic *buf = (duk_hbuffer_dynamic *) ud;
47094 	DUK_UNREF(heap);
47095 	return (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, buf);
47096 }
47097 /*
47098  *  duk_hbuffer assertion helpers
47099  */
47100 
47101 /* #include duk_internal.h -> already included */
47102 
47103 #if defined(DUK_USE_ASSERTIONS)
47104 
47105 DUK_INTERNAL void duk_hbuffer_assert_valid(duk_hbuffer *h) {
47106 	DUK_ASSERT(h != NULL);
47107 }
47108 
47109 #endif  /* DUK_USE_ASSERTIONS */
47110 /*
47111  *  duk_hbuffer operations such as resizing and inserting/appending data to
47112  *  a dynamic buffer.
47113  */
47114 
47115 /* #include duk_internal.h -> already included */
47116 
47117 /*
47118  *  Resizing
47119  */
47120 
47121 DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size) {
47122 	void *res;
47123 	duk_size_t prev_size;
47124 
47125 	DUK_ASSERT(thr != NULL);
47126 	DUK_ASSERT(buf != NULL);
47127 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
47128 	DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
47129 
47130 	/*
47131 	 *  Maximum size check
47132 	 */
47133 
47134 	if (new_size > DUK_HBUFFER_MAX_BYTELEN) {
47135 		DUK_ERROR_RANGE(thr, "buffer too long");
47136 		DUK_WO_NORETURN(return;);
47137 	}
47138 
47139 	/*
47140 	 *  Note: use indirect realloc variant just in case mark-and-sweep
47141 	 *  (finalizers) might resize this same buffer during garbage
47142 	 *  collection.
47143 	 */
47144 
47145 	res = DUK_REALLOC_INDIRECT(thr->heap, duk_hbuffer_get_dynalloc_ptr, (void *) buf, new_size);
47146 	if (DUK_LIKELY(res != NULL || new_size == 0)) {
47147 		/* 'res' may be NULL if new allocation size is 0. */
47148 
47149 		DUK_DDD(DUK_DDDPRINT("resized dynamic buffer %p:%ld -> %p:%ld",
47150 		                     (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf),
47151 		                     (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf),
47152 		                     (void *) res,
47153 		                     (long) new_size));
47154 
47155 		/*
47156 		 *  The entire allocated buffer area, regardless of actual used
47157 		 *  size, is kept zeroed in resizes for simplicity.  If the buffer
47158 		 *  is grown, zero the new part.
47159 		 */
47160 
47161 		prev_size = DUK_HBUFFER_DYNAMIC_GET_SIZE(buf);
47162 		if (new_size > prev_size) {
47163 			DUK_ASSERT(new_size - prev_size > 0);
47164 #if defined(DUK_USE_ZERO_BUFFER_DATA)
47165 			duk_memzero((void *) ((char *) res + prev_size),
47166 			            (duk_size_t) (new_size - prev_size));
47167 #endif
47168 		}
47169 
47170 		DUK_HBUFFER_DYNAMIC_SET_SIZE(buf, new_size);
47171 		DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr->heap, buf, res);
47172 	} else {
47173 		DUK_ERROR_ALLOC_FAILED(thr);
47174 		DUK_WO_NORETURN(return;);
47175 	}
47176 
47177 	DUK_ASSERT(res != NULL || new_size == 0);
47178 }
47179 
47180 DUK_INTERNAL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf) {
47181 	DUK_ASSERT(thr != NULL);
47182 	DUK_ASSERT(buf != NULL);
47183 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
47184 	DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
47185 
47186 	duk_hbuffer_resize(thr, buf, 0);
47187 }
47188 /* #include duk_internal.h -> already included */
47189 
47190 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
47191 DUK_INTERNAL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len) {
47192 	duk_uint_t buf_size;
47193 	duk_uint_t buf_avail;
47194 
47195 	DUK_ASSERT(h_bufobj != NULL);
47196 	DUK_ASSERT(h_bufobj->buf != NULL);
47197 
47198 	buf_size = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_bufobj->buf);
47199 	if (h_bufobj->offset > buf_size) {
47200 		/* Slice starting point is beyond current length. */
47201 		return 0;
47202 	}
47203 	buf_avail = buf_size - h_bufobj->offset;
47204 
47205 	return buf_avail >= len ? len : buf_avail;
47206 }
47207 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
47208 /*
47209  *  duk_heap allocation and freeing.
47210  */
47211 
47212 /* #include duk_internal.h -> already included */
47213 
47214 #if defined(DUK_USE_ROM_STRINGS)
47215 /* Fixed seed value used with ROM strings. */
47216 #define DUK__FIXED_HASH_SEED       0xabcd1234
47217 #endif
47218 
47219 /*
47220  *  Free a heap object.
47221  *
47222  *  Free heap object and its internal (non-heap) pointers.  Assumes that
47223  *  caller has removed the object from heap allocated list or the string
47224  *  intern table, and any weak references (which strings may have) have
47225  *  been already dealt with.
47226  */
47227 
47228 DUK_INTERNAL void duk_free_hobject(duk_heap *heap, duk_hobject *h) {
47229 	DUK_ASSERT(heap != NULL);
47230 	DUK_ASSERT(h != NULL);
47231 
47232 	DUK_FREE(heap, DUK_HOBJECT_GET_PROPS(heap, h));
47233 
47234 	if (DUK_HOBJECT_IS_COMPFUNC(h)) {
47235 		duk_hcompfunc *f = (duk_hcompfunc *) h;
47236 		DUK_UNREF(f);
47237 		/* Currently nothing to free; 'data' is a heap object */
47238 	} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
47239 		duk_hnatfunc *f = (duk_hnatfunc *) h;
47240 		DUK_UNREF(f);
47241 		/* Currently nothing to free */
47242 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
47243 		duk_hthread *t = (duk_hthread *) h;
47244 		duk_activation *act;
47245 
47246 		DUK_FREE(heap, t->valstack);
47247 
47248 		/* Don't free h->resumer because it exists in the heap.
47249 		 * Callstack entries also contain function pointers which
47250 		 * are not freed for the same reason.  They are decref
47251 		 * finalized and the targets are freed if necessary based
47252 		 * on their refcount (or reachability).
47253 		 */
47254 		for (act = t->callstack_curr; act != NULL;) {
47255 			duk_activation *act_next;
47256 			duk_catcher *cat;
47257 
47258 			for (cat = act->cat; cat != NULL;) {
47259 				duk_catcher *cat_next;
47260 
47261 				cat_next = cat->parent;
47262 				DUK_FREE(heap, (void *) cat);
47263 				cat = cat_next;
47264 			}
47265 
47266 			act_next = act->parent;
47267 			DUK_FREE(heap, (void *) act);
47268 			act = act_next;
47269 		}
47270 
47271 		/* XXX: with 'caller' property the callstack would need
47272 		 * to be unwound to update the 'caller' properties of
47273 		 * functions in the callstack.
47274 		 */
47275 	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
47276 		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
47277 
47278 		DUK_FREE(heap, f->args);
47279 	}
47280 
47281 	DUK_FREE(heap, (void *) h);
47282 }
47283 
47284 DUK_INTERNAL void duk_free_hbuffer(duk_heap *heap, duk_hbuffer *h) {
47285 	DUK_ASSERT(heap != NULL);
47286 	DUK_ASSERT(h != NULL);
47287 
47288 	if (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h)) {
47289 		duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
47290 		DUK_DDD(DUK_DDDPRINT("free dynamic buffer %p", (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g)));
47291 		DUK_FREE(heap, DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g));
47292 	}
47293 	DUK_FREE(heap, (void *) h);
47294 }
47295 
47296 DUK_INTERNAL void duk_free_hstring(duk_heap *heap, duk_hstring *h) {
47297 	DUK_ASSERT(heap != NULL);
47298 	DUK_ASSERT(h != NULL);
47299 
47300 	DUK_UNREF(heap);
47301 	DUK_UNREF(h);
47302 
47303 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_FREE)
47304 	if (DUK_HSTRING_HAS_EXTDATA(h)) {
47305 		DUK_DDD(DUK_DDDPRINT("free extstr: hstring %!O, extdata: %p",
47306 		                     h, DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h)));
47307 		DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h));
47308 	}
47309 #endif
47310 	DUK_FREE(heap, (void *) h);
47311 }
47312 
47313 DUK_INTERNAL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr) {
47314 	DUK_ASSERT(heap);
47315 	DUK_ASSERT(hdr);
47316 
47317 	DUK_DDD(DUK_DDDPRINT("free heaphdr %p, htype %ld", (void *) hdr, (long) DUK_HEAPHDR_GET_TYPE(hdr)));
47318 
47319 	switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
47320 	case DUK_HTYPE_STRING:
47321 		duk_free_hstring(heap, (duk_hstring *) hdr);
47322 		break;
47323 	case DUK_HTYPE_OBJECT:
47324 		duk_free_hobject(heap, (duk_hobject *) hdr);
47325 		break;
47326 	default:
47327 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) == DUK_HTYPE_BUFFER);
47328 		duk_free_hbuffer(heap, (duk_hbuffer *) hdr);
47329 	}
47330 
47331 }
47332 
47333 /*
47334  *  Free the heap.
47335  *
47336  *  Frees heap-related non-heap-tracked allocations such as the
47337  *  string intern table; then frees the heap allocated objects;
47338  *  and finally frees the heap structure itself.  Reference counts
47339  *  and GC markers are ignored (and not updated) in this process,
47340  *  and finalizers won't be called.
47341  *
47342  *  The heap pointer and heap object pointers must not be used
47343  *  after this call.
47344  */
47345 
47346 #if defined(DUK_USE_CACHE_ACTIVATION)
47347 DUK_LOCAL duk_size_t duk__heap_free_activation_freelist(duk_heap *heap) {
47348 	duk_activation *act;
47349 	duk_activation *act_next;
47350 	duk_size_t count_act = 0;
47351 
47352 	for (act = heap->activation_free; act != NULL;) {
47353 		act_next = act->parent;
47354 		DUK_FREE(heap, (void *) act);
47355 		act = act_next;
47356 #if defined(DUK_USE_DEBUG)
47357 		count_act++;
47358 #endif
47359 	}
47360 	heap->activation_free = NULL;  /* needed when called from mark-and-sweep */
47361 	return count_act;
47362 }
47363 #endif  /* DUK_USE_CACHE_ACTIVATION */
47364 
47365 #if defined(DUK_USE_CACHE_CATCHER)
47366 DUK_LOCAL duk_size_t duk__heap_free_catcher_freelist(duk_heap *heap) {
47367 	duk_catcher *cat;
47368 	duk_catcher *cat_next;
47369 	duk_size_t count_cat = 0;
47370 
47371 	for (cat = heap->catcher_free; cat != NULL;) {
47372 		cat_next = cat->parent;
47373 		DUK_FREE(heap, (void *) cat);
47374 		cat = cat_next;
47375 #if defined(DUK_USE_DEBUG)
47376 		count_cat++;
47377 #endif
47378 	}
47379 	heap->catcher_free = NULL;  /* needed when called from mark-and-sweep */
47380 
47381 	return count_cat;
47382 }
47383 #endif  /* DUK_USE_CACHE_CATCHER */
47384 
47385 DUK_INTERNAL void duk_heap_free_freelists(duk_heap *heap) {
47386 	duk_size_t count_act = 0;
47387 	duk_size_t count_cat = 0;
47388 
47389 #if defined(DUK_USE_CACHE_ACTIVATION)
47390 	count_act = duk__heap_free_activation_freelist(heap);
47391 #endif
47392 #if defined(DUK_USE_CACHE_CATCHER)
47393 	count_cat = duk__heap_free_catcher_freelist(heap);
47394 #endif
47395 	DUK_UNREF(heap);
47396 	DUK_UNREF(count_act);
47397 	DUK_UNREF(count_cat);
47398 
47399 	DUK_D(DUK_DPRINT("freed %ld activation freelist entries, %ld catcher freelist entries",
47400 	                 (long) count_act, (long) count_cat));
47401 }
47402 
47403 DUK_LOCAL void duk__free_allocated(duk_heap *heap) {
47404 	duk_heaphdr *curr;
47405 	duk_heaphdr *next;
47406 
47407 	curr = heap->heap_allocated;
47408 	while (curr) {
47409 		/* We don't log or warn about freeing zero refcount objects
47410 		 * because they may happen with finalizer processing.
47411 		 */
47412 
47413 		DUK_DDD(DUK_DDDPRINT("FINALFREE (allocated): %!iO",
47414 		                     (duk_heaphdr *) curr));
47415 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
47416 		duk_heap_free_heaphdr_raw(heap, curr);
47417 		curr = next;
47418 	}
47419 }
47420 
47421 #if defined(DUK_USE_FINALIZER_SUPPORT)
47422 DUK_LOCAL void duk__free_finalize_list(duk_heap *heap) {
47423 	duk_heaphdr *curr;
47424 	duk_heaphdr *next;
47425 
47426 	curr = heap->finalize_list;
47427 	while (curr) {
47428 		DUK_DDD(DUK_DDDPRINT("FINALFREE (finalize_list): %!iO",
47429 		                     (duk_heaphdr *) curr));
47430 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
47431 		duk_heap_free_heaphdr_raw(heap, curr);
47432 		curr = next;
47433 	}
47434 }
47435 #endif  /* DUK_USE_FINALIZER_SUPPORT */
47436 
47437 DUK_LOCAL void duk__free_stringtable(duk_heap *heap) {
47438 	/* strings are only tracked by stringtable */
47439 	duk_heap_strtable_free(heap);
47440 }
47441 
47442 #if defined(DUK_USE_FINALIZER_SUPPORT)
47443 DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap) {
47444 	duk_heaphdr *curr;
47445 	duk_uint_t round_no;
47446 	duk_size_t count_all;
47447 	duk_size_t count_finalized;
47448 	duk_size_t curr_limit;
47449 
47450 	DUK_ASSERT(heap != NULL);
47451 
47452 #if defined(DUK_USE_REFERENCE_COUNTING)
47453 	DUK_ASSERT(heap->refzero_list == NULL);  /* refzero not running -> must be empty */
47454 #endif
47455 	DUK_ASSERT(heap->finalize_list == NULL);  /* mark-and-sweep last pass */
47456 
47457 	if (heap->heap_thread == NULL) {
47458 		/* May happen when heap allocation fails right off.  There
47459 		 * cannot be any finalizable objects in this case.
47460 		 */
47461 		DUK_D(DUK_DPRINT("no heap_thread in heap destruct, assume no finalizable objects"));
47462 		return;
47463 	}
47464 
47465 	/* Prevent finalize_list processing and mark-and-sweep entirely.
47466 	 * Setting ms_running != 0 also prevents refzero handling from moving
47467 	 * objects away from the heap_allocated list.  The flag name is a bit
47468 	 * misleading here.
47469 	 *
47470 	 * Use a distinct value for ms_running here (== 2) so that assertions
47471 	 * can detect this situation separate from the normal runtime
47472 	 * mark-and-sweep case.  This allows better assertions (GH-2030).
47473 	 */
47474 	DUK_ASSERT(heap->pf_prevent_count == 0);
47475 	DUK_ASSERT(heap->ms_running == 0);
47476 	DUK_ASSERT(heap->ms_prevent_count == 0);
47477 	heap->pf_prevent_count = 1;
47478 	heap->ms_running = 2;  /* Use distinguishable value. */
47479 	heap->ms_prevent_count = 1;  /* Bump, because mark-and-sweep assumes it's bumped when ms_running is set. */
47480 
47481 	curr_limit = 0;  /* suppress warning, not used */
47482 	for (round_no = 0; ; round_no++) {
47483 		curr = heap->heap_allocated;
47484 		count_all = 0;
47485 		count_finalized = 0;
47486 		while (curr) {
47487 			count_all++;
47488 			if (DUK_HEAPHDR_IS_OBJECT(curr)) {
47489 				/* Only objects in heap_allocated may have finalizers.  Check that
47490 				 * the object itself has a _Finalizer property (own or inherited)
47491 				 * so that we don't execute finalizers for e.g. Proxy objects.
47492 				 */
47493 				DUK_ASSERT(curr != NULL);
47494 
47495 				if (DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) curr)) {
47496 					if (!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) curr)) {
47497 						DUK_ASSERT(DUK_HEAP_HAS_FINALIZER_NORESCUE(heap));  /* maps to finalizer 2nd argument */
47498 						duk_heap_run_finalizer(heap, (duk_hobject *) curr);
47499 						count_finalized++;
47500 					}
47501 				}
47502 			}
47503 			curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
47504 		}
47505 
47506 		/* Each round of finalizer execution may spawn new finalizable objects
47507 		 * which is normal behavior for some applications.  Allow multiple
47508 		 * rounds of finalization, but use a shrinking limit based on the
47509 		 * first round to detect the case where a runaway finalizer creates
47510 		 * an unbounded amount of new finalizable objects.  Finalizer rescue
47511 		 * is not supported: the semantics are unclear because most of the
47512 		 * objects being finalized here are already reachable.  The finalizer
47513 		 * is given a boolean to indicate that rescue is not possible.
47514 		 *
47515 		 * See discussion in: https://github.com/svaarala/duktape/pull/473
47516 		 */
47517 
47518 		if (round_no == 0) {
47519 			/* Cannot wrap: each object is at least 8 bytes so count is
47520 			 * at most 1/8 of that.
47521 			 */
47522 			curr_limit = count_all * 2;
47523 		} else {
47524 			curr_limit = (curr_limit * 3) / 4;   /* Decrease by 25% every round */
47525 		}
47526 		DUK_D(DUK_DPRINT("finalizer round %ld complete, %ld objects, tried to execute %ld finalizers, current limit is %ld",
47527 		                 (long) round_no, (long) count_all, (long) count_finalized, (long) curr_limit));
47528 
47529 		if (count_finalized == 0) {
47530 			DUK_D(DUK_DPRINT("no more finalizable objects, forced finalization finished"));
47531 			break;
47532 		}
47533 		if (count_finalized >= curr_limit) {
47534 			DUK_D(DUK_DPRINT("finalizer count above limit, potentially runaway finalizer; skip remaining finalizers"));
47535 			break;
47536 		}
47537 	}
47538 
47539 	DUK_ASSERT(heap->ms_running == 2);
47540 	DUK_ASSERT(heap->pf_prevent_count == 1);
47541 	heap->ms_running = 0;
47542 	heap->pf_prevent_count = 0;
47543 }
47544 #endif  /* DUK_USE_FINALIZER_SUPPORT */
47545 
47546 DUK_INTERNAL void duk_heap_free(duk_heap *heap) {
47547 	DUK_D(DUK_DPRINT("free heap: %p", (void *) heap));
47548 
47549 #if defined(DUK_USE_DEBUG)
47550 	duk_heap_strtable_dump(heap);
47551 #endif
47552 
47553 #if defined(DUK_USE_DEBUGGER_SUPPORT)
47554 	/* Detach a debugger if attached (can be called multiple times)
47555 	 * safely.
47556 	 */
47557 	/* XXX: Add a flag to reject an attempt to re-attach?  Otherwise
47558 	 * the detached callback may immediately reattach.
47559 	 */
47560 	duk_debug_do_detach(heap);
47561 #endif
47562 
47563 	/* Execute finalizers before freeing the heap, even for reachable
47564 	 * objects.  This gives finalizers the chance to free any native
47565 	 * resources like file handles, allocations made outside Duktape,
47566 	 * etc.  This is quite tricky to get right, so that all finalizer
47567 	 * guarantees are honored.
47568 	 *
47569 	 * Run mark-and-sweep a few times just in case (unreachable object
47570 	 * finalizers run already here).  The last round must rescue objects
47571 	 * from the previous round without running any more finalizers.  This
47572 	 * ensures rescued objects get their FINALIZED flag cleared so that
47573 	 * their finalizer is called once more in forced finalization to
47574 	 * satisfy finalizer guarantees.  However, we don't want to run any
47575 	 * more finalizers because that'd required one more loop, and so on.
47576 	 *
47577 	 * XXX: this perhaps requires an execution time limit.
47578 	 */
47579 	DUK_D(DUK_DPRINT("execute finalizers before freeing heap"));
47580 	DUK_ASSERT(heap->pf_skip_finalizers == 0);
47581 	DUK_D(DUK_DPRINT("forced gc #1 in heap destruction"));
47582 	duk_heap_mark_and_sweep(heap, 0);
47583 	DUK_D(DUK_DPRINT("forced gc #2 in heap destruction"));
47584 	duk_heap_mark_and_sweep(heap, 0);
47585 	DUK_D(DUK_DPRINT("forced gc #3 in heap destruction (don't run finalizers)"));
47586 	heap->pf_skip_finalizers = 1;
47587 	duk_heap_mark_and_sweep(heap, 0);  /* Skip finalizers; queue finalizable objects to heap_allocated. */
47588 
47589 	/* There are never objects in refzero_list at this point, or at any
47590 	 * point beyond a DECREF (even a DECREF_NORZ).  Since Duktape 2.1
47591 	 * refzero_list processing is side effect free, so it is always
47592 	 * processed to completion by a DECREF initially triggering a zero
47593 	 * refcount.
47594 	 */
47595 #if defined(DUK_USE_REFERENCE_COUNTING)
47596 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always processed to completion inline. */
47597 #endif
47598 #if defined(DUK_USE_FINALIZER_SUPPORT)
47599 	DUK_ASSERT(heap->finalize_list == NULL);  /* Last mark-and-sweep with skip_finalizers. */
47600 #endif
47601 
47602 #if defined(DUK_USE_FINALIZER_SUPPORT)
47603 	DUK_D(DUK_DPRINT("run finalizers for remaining finalizable objects"));
47604 	DUK_HEAP_SET_FINALIZER_NORESCUE(heap);  /* Rescue no longer supported. */
47605 	duk__free_run_finalizers(heap);
47606 #endif  /* DUK_USE_FINALIZER_SUPPORT */
47607 
47608 	/* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object
47609 	 * are on the heap allocated list.
47610 	 */
47611 
47612 	DUK_D(DUK_DPRINT("freeing temporary freelists"));
47613 	duk_heap_free_freelists(heap);
47614 
47615 	DUK_D(DUK_DPRINT("freeing heap_allocated of heap: %p", (void *) heap));
47616 	duk__free_allocated(heap);
47617 
47618 #if defined(DUK_USE_REFERENCE_COUNTING)
47619 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always processed to completion inline. */
47620 #endif
47621 
47622 #if defined(DUK_USE_FINALIZER_SUPPORT)
47623 	DUK_D(DUK_DPRINT("freeing finalize_list of heap: %p", (void *) heap));
47624 	duk__free_finalize_list(heap);
47625 #endif
47626 
47627 	DUK_D(DUK_DPRINT("freeing string table of heap: %p", (void *) heap));
47628 	duk__free_stringtable(heap);
47629 
47630 	DUK_D(DUK_DPRINT("freeing heap structure: %p", (void *) heap));
47631 	heap->free_func(heap->heap_udata, heap);
47632 }
47633 
47634 /*
47635  *  Allocate a heap.
47636  *
47637  *  String table is initialized with built-in strings from genbuiltins.py,
47638  *  either by dynamically creating the strings or by referring to ROM strings.
47639  */
47640 
47641 #if defined(DUK_USE_ROM_STRINGS)
47642 DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
47643 #if defined(DUK_USE_ASSERTIONS)
47644 	duk_small_uint_t i;
47645 #endif
47646 
47647 	DUK_UNREF(heap);
47648 
47649 	/* With ROM-based strings, heap->strs[] and thr->strs[] are omitted
47650 	 * so nothing to initialize for strs[].
47651 	 */
47652 
47653 #if defined(DUK_USE_ASSERTIONS)
47654 	for (i = 0; i < sizeof(duk_rom_strings_lookup) / sizeof(const duk_hstring *); i++) {
47655 		const duk_hstring *h;
47656 		duk_uint32_t hash;
47657 
47658 		h = duk_rom_strings_lookup[i];
47659 		while (h != NULL) {
47660 			hash = duk_heap_hashstring(heap, (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
47661 			DUK_DD(DUK_DDPRINT("duk_rom_strings_lookup[%d] -> hash 0x%08lx, computed 0x%08lx",
47662 			                   (int) i, (unsigned long) DUK_HSTRING_GET_HASH(h), (unsigned long) hash));
47663 			DUK_ASSERT(hash == (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
47664 
47665 			h = (const duk_hstring *) h->hdr.h_next;
47666 		}
47667 	}
47668 #endif
47669 	return 1;
47670 }
47671 #else  /* DUK_USE_ROM_STRINGS */
47672 
47673 DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
47674 	duk_bitdecoder_ctx bd_ctx;
47675 	duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
47676 	duk_small_uint_t i;
47677 
47678 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
47679 	bd->data = (const duk_uint8_t *) duk_strings_data;
47680 	bd->length = (duk_size_t) DUK_STRDATA_DATA_LENGTH;
47681 
47682 	for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
47683 		duk_uint8_t tmp[DUK_STRDATA_MAX_STRLEN];
47684 		duk_small_uint_t len;
47685 		duk_hstring *h;
47686 
47687 		len = duk_bd_decode_bitpacked_string(bd, tmp);
47688 
47689 		/* No need to length check string: it will never exceed even
47690 		 * the 16-bit length maximum.
47691 		 */
47692 		DUK_ASSERT(len <= 0xffffUL);
47693 		DUK_DDD(DUK_DDDPRINT("intern built-in string %ld", (long) i));
47694 		h = duk_heap_strtable_intern(heap, tmp, len);
47695 		if (!h) {
47696 			goto failed;
47697 		}
47698 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
47699 
47700 		/* Special flags checks.  Since these strings are always
47701 		 * reachable and a string cannot appear twice in the string
47702 		 * table, there's no need to check/set these flags elsewhere.
47703 		 * The 'internal' flag is set by string intern code.
47704 		 */
47705 		if (i == DUK_STRIDX_EVAL || i == DUK_STRIDX_LC_ARGUMENTS) {
47706 			DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(h);
47707 		}
47708 		if (i >= DUK_STRIDX_START_RESERVED && i < DUK_STRIDX_END_RESERVED) {
47709 			DUK_HSTRING_SET_RESERVED_WORD(h);
47710 			if (i >= DUK_STRIDX_START_STRICT_RESERVED) {
47711 				DUK_HSTRING_SET_STRICT_RESERVED_WORD(h);
47712 			}
47713 		}
47714 
47715 		DUK_DDD(DUK_DDDPRINT("interned: %!O", (duk_heaphdr *) h));
47716 
47717 		/* XXX: The incref macro takes a thread pointer but doesn't
47718 		 * use it right now.
47719 		 */
47720 		DUK_HSTRING_INCREF(_never_referenced_, h);
47721 
47722 #if defined(DUK_USE_HEAPPTR16)
47723 		heap->strs16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
47724 #else
47725 		heap->strs[i] = h;
47726 #endif
47727 	}
47728 
47729 	return 1;
47730 
47731  failed:
47732 	return 0;
47733 }
47734 #endif  /* DUK_USE_ROM_STRINGS */
47735 
47736 DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap) {
47737 	duk_hthread *thr;
47738 
47739 	DUK_D(DUK_DPRINT("heap init: alloc heap thread"));
47740 	thr = duk_hthread_alloc_unchecked(heap,
47741 	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
47742 	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
47743 	if (thr == NULL) {
47744 		DUK_D(DUK_DPRINT("failed to alloc heap_thread"));
47745 		return 0;
47746 	}
47747 	thr->state = DUK_HTHREAD_STATE_INACTIVE;
47748 #if defined(DUK_USE_ROM_STRINGS)
47749 	/* No strs[] pointer. */
47750 #else  /* DUK_USE_ROM_STRINGS */
47751 #if defined(DUK_USE_HEAPPTR16)
47752 	thr->strs16 = heap->strs16;
47753 #else
47754 	thr->strs = heap->strs;
47755 #endif
47756 #endif  /* DUK_USE_ROM_STRINGS */
47757 
47758 	heap->heap_thread = thr;
47759 	DUK_HTHREAD_INCREF(thr, thr);  /* Note: first argument not really used */
47760 
47761 	/* 'thr' is now reachable */
47762 
47763 	DUK_D(DUK_DPRINT("heap init: init heap thread stacks"));
47764 	if (!duk_hthread_init_stacks(heap, thr)) {
47765 		return 0;
47766 	}
47767 
47768 	/* XXX: this may now fail, and is not handled correctly */
47769 	duk_hthread_create_builtin_objects(thr);
47770 
47771 	/* default prototype */
47772 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) thr, thr->builtins[DUK_BIDX_THREAD_PROTOTYPE]);
47773 
47774 	return 1;
47775 }
47776 
47777 #if defined(DUK_USE_DEBUG)
47778 #define DUK__DUMPSZ(t)  do { \
47779 		DUK_D(DUK_DPRINT("" #t "=%ld", (long) sizeof(t))); \
47780 	} while (0)
47781 
47782 /* These is not 100% because format would need to be non-portable "long long".
47783  * Also print out as doubles to catch cases where the "long" type is not wide
47784  * enough; the limits will then not be printed accurately but the magnitude
47785  * will be correct.
47786  */
47787 #define DUK__DUMPLM_SIGNED_RAW(t,a,b)  do { \
47788 		DUK_D(DUK_DPRINT(t "=[%ld,%ld]=[%lf,%lf]", \
47789 		                 (long) (a), (long) (b), \
47790 		                 (double) (a), (double) (b))); \
47791 	} while (0)
47792 #define DUK__DUMPLM_UNSIGNED_RAW(t,a,b)  do { \
47793 		DUK_D(DUK_DPRINT(t "=[%lu,%lu]=[%lf,%lf]", \
47794 		                 (unsigned long) (a), (unsigned long) (b), \
47795 		                 (double) (a), (double) (b))); \
47796 	} while (0)
47797 #define DUK__DUMPLM_SIGNED(t)  do { \
47798 		DUK__DUMPLM_SIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
47799 	} while (0)
47800 #define DUK__DUMPLM_UNSIGNED(t)  do { \
47801 		DUK__DUMPLM_UNSIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
47802 	} while (0)
47803 
47804 DUK_LOCAL void duk__dump_type_sizes(void) {
47805 	DUK_D(DUK_DPRINT("sizeof()"));
47806 
47807 	/* basic platform types */
47808 	DUK__DUMPSZ(char);
47809 	DUK__DUMPSZ(short);
47810 	DUK__DUMPSZ(int);
47811 	DUK__DUMPSZ(long);
47812 	DUK__DUMPSZ(double);
47813 	DUK__DUMPSZ(void *);
47814 	DUK__DUMPSZ(size_t);
47815 
47816 	/* basic types from duk_features.h */
47817 	DUK__DUMPSZ(duk_uint8_t);
47818 	DUK__DUMPSZ(duk_int8_t);
47819 	DUK__DUMPSZ(duk_uint16_t);
47820 	DUK__DUMPSZ(duk_int16_t);
47821 	DUK__DUMPSZ(duk_uint32_t);
47822 	DUK__DUMPSZ(duk_int32_t);
47823 	DUK__DUMPSZ(duk_uint64_t);
47824 	DUK__DUMPSZ(duk_int64_t);
47825 	DUK__DUMPSZ(duk_uint_least8_t);
47826 	DUK__DUMPSZ(duk_int_least8_t);
47827 	DUK__DUMPSZ(duk_uint_least16_t);
47828 	DUK__DUMPSZ(duk_int_least16_t);
47829 	DUK__DUMPSZ(duk_uint_least32_t);
47830 	DUK__DUMPSZ(duk_int_least32_t);
47831 #if defined(DUK_USE_64BIT_OPS)
47832 	DUK__DUMPSZ(duk_uint_least64_t);
47833 	DUK__DUMPSZ(duk_int_least64_t);
47834 #endif
47835 	DUK__DUMPSZ(duk_uint_fast8_t);
47836 	DUK__DUMPSZ(duk_int_fast8_t);
47837 	DUK__DUMPSZ(duk_uint_fast16_t);
47838 	DUK__DUMPSZ(duk_int_fast16_t);
47839 	DUK__DUMPSZ(duk_uint_fast32_t);
47840 	DUK__DUMPSZ(duk_int_fast32_t);
47841 #if defined(DUK_USE_64BIT_OPS)
47842 	DUK__DUMPSZ(duk_uint_fast64_t);
47843 	DUK__DUMPSZ(duk_int_fast64_t);
47844 #endif
47845 	DUK__DUMPSZ(duk_uintptr_t);
47846 	DUK__DUMPSZ(duk_intptr_t);
47847 	DUK__DUMPSZ(duk_uintmax_t);
47848 	DUK__DUMPSZ(duk_intmax_t);
47849 	DUK__DUMPSZ(duk_double_t);
47850 
47851 	/* important chosen base types */
47852 	DUK__DUMPSZ(duk_int_t);
47853 	DUK__DUMPSZ(duk_uint_t);
47854 	DUK__DUMPSZ(duk_int_fast_t);
47855 	DUK__DUMPSZ(duk_uint_fast_t);
47856 	DUK__DUMPSZ(duk_small_int_t);
47857 	DUK__DUMPSZ(duk_small_uint_t);
47858 	DUK__DUMPSZ(duk_small_int_fast_t);
47859 	DUK__DUMPSZ(duk_small_uint_fast_t);
47860 
47861 	/* some derived types */
47862 	DUK__DUMPSZ(duk_codepoint_t);
47863 	DUK__DUMPSZ(duk_ucodepoint_t);
47864 	DUK__DUMPSZ(duk_idx_t);
47865 	DUK__DUMPSZ(duk_errcode_t);
47866 	DUK__DUMPSZ(duk_uarridx_t);
47867 
47868 	/* tval */
47869 	DUK__DUMPSZ(duk_double_union);
47870 	DUK__DUMPSZ(duk_tval);
47871 
47872 	/* structs from duk_forwdecl.h */
47873 	DUK__DUMPSZ(duk_jmpbuf);  /* just one 'int' for C++ exceptions */
47874 	DUK__DUMPSZ(duk_heaphdr);
47875 	DUK__DUMPSZ(duk_heaphdr_string);
47876 	DUK__DUMPSZ(duk_hstring);
47877 	DUK__DUMPSZ(duk_hstring_external);
47878 	DUK__DUMPSZ(duk_hobject);
47879 	DUK__DUMPSZ(duk_harray);
47880 	DUK__DUMPSZ(duk_hcompfunc);
47881 	DUK__DUMPSZ(duk_hnatfunc);
47882 	DUK__DUMPSZ(duk_hdecenv);
47883 	DUK__DUMPSZ(duk_hobjenv);
47884 	DUK__DUMPSZ(duk_hthread);
47885 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
47886 	DUK__DUMPSZ(duk_hbufobj);
47887 #endif
47888 	DUK__DUMPSZ(duk_hproxy);
47889 	DUK__DUMPSZ(duk_hbuffer);
47890 	DUK__DUMPSZ(duk_hbuffer_fixed);
47891 	DUK__DUMPSZ(duk_hbuffer_dynamic);
47892 	DUK__DUMPSZ(duk_hbuffer_external);
47893 	DUK__DUMPSZ(duk_propaccessor);
47894 	DUK__DUMPSZ(duk_propvalue);
47895 	DUK__DUMPSZ(duk_propdesc);
47896 	DUK__DUMPSZ(duk_heap);
47897 	DUK__DUMPSZ(duk_activation);
47898 	DUK__DUMPSZ(duk_catcher);
47899 	DUK__DUMPSZ(duk_strcache_entry);
47900 	DUK__DUMPSZ(duk_litcache_entry);
47901 	DUK__DUMPSZ(duk_ljstate);
47902 	DUK__DUMPSZ(duk_fixedbuffer);
47903 	DUK__DUMPSZ(duk_bitdecoder_ctx);
47904 	DUK__DUMPSZ(duk_bitencoder_ctx);
47905 	DUK__DUMPSZ(duk_token);
47906 	DUK__DUMPSZ(duk_re_token);
47907 	DUK__DUMPSZ(duk_lexer_point);
47908 	DUK__DUMPSZ(duk_lexer_ctx);
47909 	DUK__DUMPSZ(duk_compiler_instr);
47910 	DUK__DUMPSZ(duk_compiler_func);
47911 	DUK__DUMPSZ(duk_compiler_ctx);
47912 	DUK__DUMPSZ(duk_re_matcher_ctx);
47913 	DUK__DUMPSZ(duk_re_compiler_ctx);
47914 }
47915 DUK_LOCAL void duk__dump_type_limits(void) {
47916 	DUK_D(DUK_DPRINT("limits"));
47917 
47918 	/* basic types */
47919 	DUK__DUMPLM_SIGNED(INT8);
47920 	DUK__DUMPLM_UNSIGNED(UINT8);
47921 	DUK__DUMPLM_SIGNED(INT_FAST8);
47922 	DUK__DUMPLM_UNSIGNED(UINT_FAST8);
47923 	DUK__DUMPLM_SIGNED(INT_LEAST8);
47924 	DUK__DUMPLM_UNSIGNED(UINT_LEAST8);
47925 	DUK__DUMPLM_SIGNED(INT16);
47926 	DUK__DUMPLM_UNSIGNED(UINT16);
47927 	DUK__DUMPLM_SIGNED(INT_FAST16);
47928 	DUK__DUMPLM_UNSIGNED(UINT_FAST16);
47929 	DUK__DUMPLM_SIGNED(INT_LEAST16);
47930 	DUK__DUMPLM_UNSIGNED(UINT_LEAST16);
47931 	DUK__DUMPLM_SIGNED(INT32);
47932 	DUK__DUMPLM_UNSIGNED(UINT32);
47933 	DUK__DUMPLM_SIGNED(INT_FAST32);
47934 	DUK__DUMPLM_UNSIGNED(UINT_FAST32);
47935 	DUK__DUMPLM_SIGNED(INT_LEAST32);
47936 	DUK__DUMPLM_UNSIGNED(UINT_LEAST32);
47937 #if defined(DUK_USE_64BIT_OPS)
47938 	DUK__DUMPLM_SIGNED(INT64);
47939 	DUK__DUMPLM_UNSIGNED(UINT64);
47940 	DUK__DUMPLM_SIGNED(INT_FAST64);
47941 	DUK__DUMPLM_UNSIGNED(UINT_FAST64);
47942 	DUK__DUMPLM_SIGNED(INT_LEAST64);
47943 	DUK__DUMPLM_UNSIGNED(UINT_LEAST64);
47944 #endif
47945 	DUK__DUMPLM_SIGNED(INTPTR);
47946 	DUK__DUMPLM_UNSIGNED(UINTPTR);
47947 	DUK__DUMPLM_SIGNED(INTMAX);
47948 	DUK__DUMPLM_UNSIGNED(UINTMAX);
47949 
47950 	/* derived types */
47951 	DUK__DUMPLM_SIGNED(INT);
47952 	DUK__DUMPLM_UNSIGNED(UINT);
47953 	DUK__DUMPLM_SIGNED(INT_FAST);
47954 	DUK__DUMPLM_UNSIGNED(UINT_FAST);
47955 	DUK__DUMPLM_SIGNED(SMALL_INT);
47956 	DUK__DUMPLM_UNSIGNED(SMALL_UINT);
47957 	DUK__DUMPLM_SIGNED(SMALL_INT_FAST);
47958 	DUK__DUMPLM_UNSIGNED(SMALL_UINT_FAST);
47959 }
47960 
47961 DUK_LOCAL void duk__dump_misc_options(void) {
47962 	DUK_D(DUK_DPRINT("DUK_VERSION: %ld", (long) DUK_VERSION));
47963 	DUK_D(DUK_DPRINT("DUK_GIT_DESCRIBE: %s", DUK_GIT_DESCRIBE));
47964 	DUK_D(DUK_DPRINT("OS string: %s", DUK_USE_OS_STRING));
47965 	DUK_D(DUK_DPRINT("architecture string: %s", DUK_USE_ARCH_STRING));
47966 	DUK_D(DUK_DPRINT("compiler string: %s", DUK_USE_COMPILER_STRING));
47967 	DUK_D(DUK_DPRINT("debug level: %ld", (long) DUK_USE_DEBUG_LEVEL));
47968 #if defined(DUK_USE_PACKED_TVAL)
47969 	DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: yes"));
47970 #else
47971 	DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: no"));
47972 #endif
47973 #if defined(DUK_USE_VARIADIC_MACROS)
47974 	DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: yes"));
47975 #else
47976 	DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: no"));
47977 #endif
47978 #if defined(DUK_USE_INTEGER_LE)
47979 	DUK_D(DUK_DPRINT("integer endianness: little"));
47980 #elif defined(DUK_USE_INTEGER_ME)
47981 	DUK_D(DUK_DPRINT("integer endianness: mixed"));
47982 #elif defined(DUK_USE_INTEGER_BE)
47983 	DUK_D(DUK_DPRINT("integer endianness: big"));
47984 #else
47985 	DUK_D(DUK_DPRINT("integer endianness: ???"));
47986 #endif
47987 #if defined(DUK_USE_DOUBLE_LE)
47988 	DUK_D(DUK_DPRINT("IEEE double endianness: little"));
47989 #elif defined(DUK_USE_DOUBLE_ME)
47990 	DUK_D(DUK_DPRINT("IEEE double endianness: mixed"));
47991 #elif defined(DUK_USE_DOUBLE_BE)
47992 	DUK_D(DUK_DPRINT("IEEE double endianness: big"));
47993 #else
47994 	DUK_D(DUK_DPRINT("IEEE double endianness: ???"));
47995 #endif
47996 }
47997 #endif  /* DUK_USE_DEBUG */
47998 
47999 DUK_INTERNAL
48000 duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
48001                          duk_realloc_function realloc_func,
48002                          duk_free_function free_func,
48003                          void *heap_udata,
48004                          duk_fatal_function fatal_func) {
48005 	duk_heap *res = NULL;
48006 	duk_uint32_t st_initsize;
48007 
48008 	DUK_D(DUK_DPRINT("allocate heap"));
48009 
48010 	/*
48011 	 *  Random config sanity asserts
48012 	 */
48013 
48014 	DUK_ASSERT(DUK_USE_STRTAB_MINSIZE >= 64);
48015 
48016 	DUK_ASSERT((DUK_HTYPE_STRING & 0x01U) == 0);
48017 	DUK_ASSERT((DUK_HTYPE_BUFFER & 0x01U) == 0);
48018 	DUK_ASSERT((DUK_HTYPE_OBJECT & 0x01U) == 1);  /* DUK_HEAPHDR_IS_OBJECT() relies ont his. */
48019 
48020 	/*
48021 	 *  Debug dump type sizes
48022 	 */
48023 
48024 #if defined(DUK_USE_DEBUG)
48025 	duk__dump_misc_options();
48026 	duk__dump_type_sizes();
48027 	duk__dump_type_limits();
48028 #endif
48029 
48030 	/*
48031 	 *  If selftests enabled, run them as early as possible.
48032 	 */
48033 
48034 #if defined(DUK_USE_SELF_TESTS)
48035 	DUK_D(DUK_DPRINT("run self tests"));
48036 	if (duk_selftest_run_tests(alloc_func, realloc_func, free_func, heap_udata) > 0) {
48037 		fatal_func(heap_udata, "self test(s) failed");
48038 	}
48039 	DUK_D(DUK_DPRINT("self tests passed"));
48040 #endif
48041 
48042 	/*
48043 	 *  Important assert-like checks that should be enabled even
48044 	 *  when assertions are otherwise not enabled.
48045 	 */
48046 
48047 #if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)
48048 	/* Can't check sizeof() using preprocessor so explicit check.
48049 	 * This will be optimized away in practice; unfortunately a
48050 	 * warning is generated on some compilers as a result.
48051 	 */
48052 #if defined(DUK_USE_PACKED_TVAL)
48053 	if (sizeof(duk_tval) != 8) {
48054 #else
48055 	if (sizeof(duk_tval) != 16) {
48056 #endif
48057 		fatal_func(heap_udata, "sizeof(duk_tval) not 8 or 16, cannot use DUK_USE_EXEC_REGCONST_OPTIMIZE option");
48058 	}
48059 #endif  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
48060 
48061 	/*
48062 	 *  Computed values (e.g. INFINITY)
48063 	 */
48064 
48065 #if defined(DUK_USE_COMPUTED_NAN)
48066 	do {
48067 		/* Workaround for some exotic platforms where NAN is missing
48068 		 * and the expression (0.0 / 0.0) does NOT result in a NaN.
48069 		 * Such platforms use the global 'duk_computed_nan' which must
48070 		 * be initialized at runtime.  Use 'volatile' to ensure that
48071 		 * the compiler will actually do the computation and not try
48072 		 * to do constant folding which might result in the original
48073 		 * problem.
48074 		 */
48075 		volatile double dbl1 = 0.0;
48076 		volatile double dbl2 = 0.0;
48077 		duk_computed_nan = dbl1 / dbl2;
48078 	} while (0);
48079 #endif
48080 
48081 #if defined(DUK_USE_COMPUTED_INFINITY)
48082 	do {
48083 		/* Similar workaround for INFINITY. */
48084 		volatile double dbl1 = 1.0;
48085 		volatile double dbl2 = 0.0;
48086 		duk_computed_infinity = dbl1 / dbl2;
48087 	} while (0);
48088 #endif
48089 
48090 	/*
48091 	 *  Allocate heap struct
48092 	 *
48093 	 *  Use a raw call, all macros expect the heap to be initialized
48094 	 */
48095 
48096 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 1)
48097 	goto failed;
48098 #endif
48099 	DUK_D(DUK_DPRINT("alloc duk_heap object"));
48100 	res = (duk_heap *) alloc_func(heap_udata, sizeof(duk_heap));
48101 	if (!res) {
48102 		goto failed;
48103 	}
48104 
48105 	/*
48106 	 *  Zero the struct, and start initializing roughly in order
48107 	 */
48108 
48109 	duk_memzero(res, sizeof(*res));
48110 #if defined(DUK_USE_ASSERTIONS)
48111 	res->heap_initializing = 1;
48112 #endif
48113 
48114 	/* explicit NULL inits */
48115 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
48116 	res->heap_udata = NULL;
48117 	res->heap_allocated = NULL;
48118 #if defined(DUK_USE_REFERENCE_COUNTING)
48119 	res->refzero_list = NULL;
48120 #endif
48121 #if defined(DUK_USE_FINALIZER_SUPPORT)
48122 	res->finalize_list = NULL;
48123 #if defined(DUK_USE_ASSERTIONS)
48124 	res->currently_finalizing = NULL;
48125 #endif
48126 #endif
48127 #if defined(DUK_USE_CACHE_ACTIVATION)
48128 	res->activation_free = NULL;
48129 #endif
48130 #if defined(DUK_USE_CACHE_CATCHER)
48131 	res->catcher_free = NULL;
48132 #endif
48133 	res->heap_thread = NULL;
48134 	res->curr_thread = NULL;
48135 	res->heap_object = NULL;
48136 #if defined(DUK_USE_STRTAB_PTRCOMP)
48137 	res->strtable16 = NULL;
48138 #else
48139 	res->strtable = NULL;
48140 #endif
48141 #if defined(DUK_USE_ROM_STRINGS)
48142 	/* no res->strs[] */
48143 #else  /* DUK_USE_ROM_STRINGS */
48144 #if defined(DUK_USE_HEAPPTR16)
48145 	/* res->strs16[] is zeroed and zero decodes to NULL, so no NULL inits. */
48146 #else
48147 	{
48148 		duk_small_uint_t i;
48149 	        for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
48150 			res->strs[i] = NULL;
48151 	        }
48152 	}
48153 #endif
48154 #endif  /* DUK_USE_ROM_STRINGS */
48155 #if defined(DUK_USE_DEBUGGER_SUPPORT)
48156 	res->dbg_read_cb = NULL;
48157 	res->dbg_write_cb = NULL;
48158 	res->dbg_peek_cb = NULL;
48159 	res->dbg_read_flush_cb = NULL;
48160 	res->dbg_write_flush_cb = NULL;
48161 	res->dbg_request_cb = NULL;
48162 	res->dbg_udata = NULL;
48163 	res->dbg_pause_act = NULL;
48164 #endif
48165 #endif  /* DUK_USE_EXPLICIT_NULL_INIT */
48166 
48167 	res->alloc_func = alloc_func;
48168 	res->realloc_func = realloc_func;
48169 	res->free_func = free_func;
48170 	res->heap_udata = heap_udata;
48171 	res->fatal_func = fatal_func;
48172 
48173 	/* XXX: for now there's a pointer packing zero assumption, i.e.
48174 	 * NULL <=> compressed pointer 0.  If this is removed, may need
48175 	 * to precompute e.g. null16 here.
48176 	 */
48177 
48178 	/* res->ms_trigger_counter == 0 -> now causes immediate GC; which is OK */
48179 
48180 	/* Prevent mark-and-sweep and finalizer execution until heap is completely
48181 	 * initialized.
48182 	 */
48183 	DUK_ASSERT(res->ms_prevent_count == 0);
48184 	DUK_ASSERT(res->pf_prevent_count == 0);
48185 	res->ms_prevent_count = 1;
48186 	res->pf_prevent_count = 1;
48187 	DUK_ASSERT(res->ms_running == 0);
48188 
48189 	res->call_recursion_depth = 0;
48190 	res->call_recursion_limit = DUK_USE_NATIVE_CALL_RECLIMIT;
48191 
48192 	/* XXX: use the pointer as a seed for now: mix in time at least */
48193 
48194 	/* The casts through duk_uintptr_t is to avoid the following GCC warning:
48195 	 *
48196 	 *   warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
48197 	 *
48198 	 * This still generates a /Wp64 warning on VS2010 when compiling for x86.
48199 	 */
48200 #if defined(DUK_USE_ROM_STRINGS)
48201 	/* XXX: make a common DUK_USE_ option, and allow custom fixed seed? */
48202 	DUK_D(DUK_DPRINT("using rom strings, force heap hash_seed to fixed value 0x%08lx", (long) DUK__FIXED_HASH_SEED));
48203 	res->hash_seed = (duk_uint32_t) DUK__FIXED_HASH_SEED;
48204 #else  /* DUK_USE_ROM_STRINGS */
48205 	res->hash_seed = (duk_uint32_t) (duk_uintptr_t) res;
48206 #if !defined(DUK_USE_STRHASH_DENSE)
48207 	res->hash_seed ^= 5381;  /* Bernstein hash init value is normally 5381; XOR it in in case pointer low bits are 0 */
48208 #endif
48209 #endif  /* DUK_USE_ROM_STRINGS */
48210 
48211 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
48212 	res->lj.jmpbuf_ptr = NULL;
48213 #endif
48214 	DUK_ASSERT(res->lj.type == DUK_LJ_TYPE_UNKNOWN);  /* zero */
48215 	DUK_ASSERT(res->lj.iserror == 0);
48216 	DUK_TVAL_SET_UNDEFINED(&res->lj.value1);
48217 	DUK_TVAL_SET_UNDEFINED(&res->lj.value2);
48218 
48219 	DUK_ASSERT_LJSTATE_UNSET(res);
48220 
48221 	/*
48222 	 *  Init stringtable: fixed variant
48223 	 */
48224 
48225 	st_initsize = DUK_USE_STRTAB_MINSIZE;
48226 #if defined(DUK_USE_STRTAB_PTRCOMP)
48227 	res->strtable16 = (duk_uint16_t *) alloc_func(heap_udata, sizeof(duk_uint16_t) * st_initsize);
48228 	if (res->strtable16 == NULL) {
48229 		goto failed;
48230 	}
48231 #else
48232 	res->strtable = (duk_hstring **) alloc_func(heap_udata, sizeof(duk_hstring *) * st_initsize);
48233 	if (res->strtable == NULL) {
48234 		goto failed;
48235 	}
48236 #endif
48237 	res->st_size = st_initsize;
48238 	res->st_mask = st_initsize - 1;
48239 #if (DUK_USE_STRTAB_MINSIZE != DUK_USE_STRTAB_MAXSIZE)
48240 	DUK_ASSERT(res->st_count == 0);
48241 #endif
48242 
48243 #if defined(DUK_USE_STRTAB_PTRCOMP)
48244 	/* zero assumption */
48245 	duk_memzero(res->strtable16, sizeof(duk_uint16_t) * st_initsize);
48246 #else
48247 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
48248 	{
48249 		duk_uint32_t i;
48250 	        for (i = 0; i < st_initsize; i++) {
48251 			res->strtable[i] = NULL;
48252 	        }
48253 	}
48254 #else
48255 	duk_memzero(res->strtable, sizeof(duk_hstring *) * st_initsize);
48256 #endif  /* DUK_USE_EXPLICIT_NULL_INIT */
48257 #endif  /* DUK_USE_STRTAB_PTRCOMP */
48258 
48259 	/*
48260 	 *  Init stringcache
48261 	 */
48262 
48263 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
48264 	{
48265 		duk_uint_t i;
48266 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
48267 			res->strcache[i].h = NULL;
48268 		}
48269 	}
48270 #endif
48271 
48272 	/*
48273 	 *  Init litcache
48274 	 */
48275 #if defined(DUK_USE_LITCACHE_SIZE)
48276 	DUK_ASSERT(DUK_USE_LITCACHE_SIZE > 0);
48277 	DUK_ASSERT(DUK_IS_POWER_OF_TWO((duk_uint_t) DUK_USE_LITCACHE_SIZE));
48278 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
48279 	{
48280 		duk_uint_t i;
48281 		for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
48282 			res->litcache[i].addr = NULL;
48283 			res->litcache[i].h = NULL;
48284 		}
48285 	}
48286 #endif
48287 #endif  /* DUK_USE_LITCACHE_SIZE */
48288 
48289 	/* XXX: error handling is incomplete.  It would be cleanest if
48290 	 * there was a setjmp catchpoint, so that all init code could
48291 	 * freely throw errors.  If that were the case, the return code
48292 	 * passing here could be removed.
48293 	 */
48294 
48295 	/*
48296 	 *  Init built-in strings
48297 	 */
48298 
48299 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 2)
48300 	goto failed;
48301 #endif
48302 	DUK_D(DUK_DPRINT("heap init: initialize heap strings"));
48303 	if (!duk__init_heap_strings(res)) {
48304 		goto failed;
48305 	}
48306 
48307 	/*
48308 	 *  Init the heap thread
48309 	 */
48310 
48311 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 3)
48312 	goto failed;
48313 #endif
48314 	DUK_D(DUK_DPRINT("heap init: initialize heap thread"));
48315 	if (!duk__init_heap_thread(res)) {
48316 		goto failed;
48317 	}
48318 
48319 	/*
48320 	 *  Init the heap object
48321 	 */
48322 
48323 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 4)
48324 	goto failed;
48325 #endif
48326 	DUK_D(DUK_DPRINT("heap init: initialize heap object"));
48327 	DUK_ASSERT(res->heap_thread != NULL);
48328 	res->heap_object = duk_hobject_alloc_unchecked(res, DUK_HOBJECT_FLAG_EXTENSIBLE |
48329 	                                                    DUK_HOBJECT_FLAG_FASTREFS |
48330 	                                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT));
48331 	if (res->heap_object == NULL) {
48332 		goto failed;
48333 	}
48334 	DUK_HOBJECT_INCREF(res->heap_thread, res->heap_object);
48335 
48336 	/*
48337 	 *  Odds and ends depending on the heap thread
48338 	 */
48339 
48340 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
48341 #if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
48342 	res->rnd_state = (duk_uint32_t) duk_time_get_ecmascript_time(res->heap_thread);
48343 	duk_util_tinyrandom_prepare_seed(res->heap_thread);
48344 #else
48345 	res->rnd_state[0] = (duk_uint64_t) duk_time_get_ecmascript_time(res->heap_thread);
48346 	DUK_ASSERT(res->rnd_state[1] == 0);  /* Not filled here, filled in by seed preparation. */
48347 #if 0  /* Manual test values matching misc/xoroshiro128plus_test.c. */
48348 	res->rnd_state[0] = DUK_U64_CONSTANT(0xdeadbeef12345678);
48349 	res->rnd_state[1] = DUK_U64_CONSTANT(0xcafed00d12345678);
48350 #endif
48351 	duk_util_tinyrandom_prepare_seed(res->heap_thread);
48352 	/* Mix in heap pointer: this ensures that if two Duktape heaps are
48353 	 * created on the same millisecond, they get a different PRNG
48354 	 * sequence (unless e.g. virtual memory addresses cause also the
48355 	 * heap object pointer to be the same).
48356 	 */
48357 	{
48358 		duk_uint64_t tmp_u64;
48359 		tmp_u64 = 0;
48360 		duk_memcpy((void *) &tmp_u64,
48361 		           (const void *) &res,
48362 		           (size_t) (sizeof(void *) >= sizeof(duk_uint64_t) ? sizeof(duk_uint64_t) : sizeof(void *)));
48363 		res->rnd_state[1] ^= tmp_u64;
48364 	}
48365 	do {
48366 		duk_small_uint_t i;
48367 		for (i = 0; i < 10; i++) {
48368 			/* Throw away a few initial random numbers just in
48369 			 * case.  Probably unnecessary due to SplitMix64
48370 			 * preparation.
48371 			 */
48372 			(void) duk_util_tinyrandom_get_double(res->heap_thread);
48373 		}
48374 	} while (0);
48375 #endif
48376 #endif
48377 
48378 	/*
48379 	 *  Allow finalizer and mark-and-sweep processing.
48380 	 */
48381 
48382 	DUK_D(DUK_DPRINT("heap init: allow finalizer/mark-and-sweep processing"));
48383 	DUK_ASSERT(res->ms_prevent_count == 1);
48384 	DUK_ASSERT(res->pf_prevent_count == 1);
48385 	res->ms_prevent_count = 0;
48386 	res->pf_prevent_count = 0;
48387 	DUK_ASSERT(res->ms_running == 0);
48388 #if defined(DUK_USE_ASSERTIONS)
48389 	res->heap_initializing = 0;
48390 #endif
48391 
48392 	/*
48393 	 *  All done.
48394 	 */
48395 
48396 	DUK_D(DUK_DPRINT("allocated heap: %p", (void *) res));
48397 	return res;
48398 
48399  failed:
48400 	DUK_D(DUK_DPRINT("heap allocation failed"));
48401 
48402 	if (res != NULL) {
48403 		/* Assumes that allocated pointers and alloc funcs are valid
48404 		 * if res exists.
48405 		 */
48406 		DUK_ASSERT(res->ms_prevent_count == 1);
48407 		DUK_ASSERT(res->pf_prevent_count == 1);
48408 		DUK_ASSERT(res->ms_running == 0);
48409 		if (res->heap_thread != NULL) {
48410 			res->ms_prevent_count = 0;
48411 			res->pf_prevent_count = 0;
48412 		}
48413 #if defined(DUK_USE_ASSERTIONS)
48414 		res->heap_initializing = 0;
48415 #endif
48416 
48417 		DUK_ASSERT(res->alloc_func != NULL);
48418 		DUK_ASSERT(res->realloc_func != NULL);
48419 		DUK_ASSERT(res->free_func != NULL);
48420 		duk_heap_free(res);
48421 	}
48422 
48423 	return NULL;
48424 }
48425 
48426 /* automatic undefs */
48427 #undef DUK__DUMPLM_SIGNED
48428 #undef DUK__DUMPLM_SIGNED_RAW
48429 #undef DUK__DUMPLM_UNSIGNED
48430 #undef DUK__DUMPLM_UNSIGNED_RAW
48431 #undef DUK__DUMPSZ
48432 #undef DUK__FIXED_HASH_SEED
48433 /*
48434  *  Finalizer handling.
48435  */
48436 
48437 /* #include duk_internal.h -> already included */
48438 
48439 #if defined(DUK_USE_FINALIZER_SUPPORT)
48440 
48441 /*
48442  *  Fake torture finalizer.
48443  */
48444 
48445 #if defined(DUK_USE_FINALIZER_TORTURE)
48446 DUK_LOCAL duk_ret_t duk__fake_global_finalizer(duk_hthread *thr) {
48447 	DUK_DD(DUK_DDPRINT("fake global torture finalizer executed"));
48448 
48449 	/* Require a lot of stack to force a value stack grow/shrink. */
48450 	duk_require_stack(thr, 100000);
48451 
48452 	/* Force a reallocation with pointer change for value stack
48453 	 * to maximize side effects.
48454 	 */
48455 	duk_hthread_valstack_torture_realloc(thr);
48456 
48457 	/* Inner function call, error throw. */
48458 	duk_eval_string_noresult(thr,
48459 		"(function dummy() {\n"
48460 		"    dummy.prototype = null;  /* break reference loop */\n"
48461 		"    try {\n"
48462 		"        throw 'fake-finalizer-dummy-error';\n"
48463 		"    } catch (e) {\n"
48464 		"        void e;\n"
48465 		"    }\n"
48466 		"})()");
48467 
48468 	/* The above creates garbage (e.g. a function instance).  Because
48469 	 * the function/prototype reference loop is broken, it gets collected
48470 	 * immediately by DECREF.  If Function.prototype has a _Finalizer
48471 	 * property (happens in some test cases), the garbage gets queued to
48472 	 * finalize_list.  This still won't cause an infinite loop because
48473 	 * the torture finalizer is called once per finalize_list run and
48474 	 * the garbage gets handled in the same run.  (If the garbage needs
48475 	 * mark-and-sweep collection, an infinite loop might ensue.)
48476 	 */
48477 	return 0;
48478 }
48479 
48480 DUK_LOCAL void duk__run_global_torture_finalizer(duk_hthread *thr) {
48481 	DUK_ASSERT(thr != NULL);
48482 
48483 	/* Avoid fake finalization when callstack limit is near.  Otherwise
48484 	 * a callstack limit error will be created, then refzero'ed.  The
48485 	 * +5 headroom is conservative.
48486 	 */
48487 	if (thr->heap->call_recursion_depth + 5 >= thr->heap->call_recursion_limit ||
48488 	    thr->callstack_top + 5 >= DUK_USE_CALLSTACK_LIMIT) {
48489 		DUK_D(DUK_DPRINT("skip global torture finalizer, too little headroom for call recursion or call stack size"));
48490 		return;
48491 	}
48492 
48493 	/* Run fake finalizer.  Avoid creating unnecessary garbage. */
48494 	duk_push_c_function(thr, duk__fake_global_finalizer, 0 /*nargs*/);
48495 	(void) duk_pcall(thr, 0 /*nargs*/);
48496 	duk_pop(thr);
48497 }
48498 #endif  /* DUK_USE_FINALIZER_TORTURE */
48499 
48500 /*
48501  *  Process the finalize_list to completion.
48502  *
48503  *  An object may be placed on finalize_list by either refcounting or
48504  *  mark-and-sweep.  The refcount of objects placed by refcounting will be
48505  *  zero; the refcount of objects placed by mark-and-sweep is > 0.  In both
48506  *  cases the refcount is bumped by 1 artificially so that a REFZERO event
48507  *  can never happen while an object is waiting for finalization.  Without
48508  *  this bump a REFZERO could now happen because user code may call
48509  *  duk_push_heapptr() and then pop a value even when it's on finalize_list.
48510  *
48511  *  List processing assumes refcounts are kept up-to-date at all times, so
48512  *  that once the finalizer returns, a zero refcount is a reliable reason to
48513  *  free the object immediately rather than place it back to the heap.  This
48514  *  is the case because we run outside of refzero_list processing so that
48515  *  DECREF cascades are handled fully inline.
48516  *
48517  *  For mark-and-sweep queued objects (had_zero_refcount false) the object
48518  *  may be freed immediately if its refcount is zero after the finalizer call
48519  *  (i.e. finalizer removed the reference loop for the object).  If not, the
48520  *  next mark-and-sweep will collect the object unless it has become reachable
48521  *  (i.e. rescued) by that time and its refcount hasn't fallen to zero before
48522  *  that.  Mark-and-sweep detects these objects because their FINALIZED flag
48523  *  is set.
48524  *
48525  *  There's an inherent limitation for mark-and-sweep finalizer rescuing: an
48526  *  object won't get refinalized if (1) it's rescued, but (2) becomes
48527  *  unreachable before mark-and-sweep has had time to notice it.  The next
48528  *  mark-and-sweep round simply doesn't have any information of whether the
48529  *  object has been unreachable the whole time or not (the only way to get
48530  *  that information would be a mark-and-sweep pass for *every finalized
48531  *  object*).  This is awkward for the application because the mark-and-sweep
48532  *  round is not generally visible or under full application control.
48533  *
48534  *  For refcount queued objects (had_zero_refcount true) the object is either
48535  *  immediately freed or rescued, and waiting for a mark-and-sweep round is not
48536  *  necessary (or desirable); FINALIZED is cleared when a rescued object is
48537  *  queued back to heap_allocated.  The object is eligible for finalization
48538  *  again (either via refcounting or mark-and-sweep) immediately after being
48539  *  rescued.  If a refcount finalized object is placed into an unreachable
48540  *  reference loop by its finalizer, it will get collected by mark-and-sweep
48541  *  and currently the finalizer will execute again.
48542  *
48543  *  There's a special case where:
48544  *
48545  *    - Mark-and-sweep queues an object to finalize_list for finalization.
48546  *    - The finalizer is executed, FINALIZED is set, and object is queued
48547  *      back to heap_allocated, waiting for a new mark-and-sweep round.
48548  *    - The object's refcount drops to zero before mark-and-sweep has a
48549  *      chance to run another round and make a rescue/free decision.
48550  *
48551  *  This is now handled by refzero code: if an object has a finalizer but
48552  *  FINALIZED is already set, the object is freed without finalizer processing.
48553  *  The outcome is the same as if mark-and-sweep was executed at that point;
48554  *  mark-and-sweep would also free the object without another finalizer run.
48555  *  This could also be changed so that the refzero-triggered finalizer *IS*
48556  *  executed: being refzero collected implies someone has operated on the
48557  *  object so it hasn't been totally unreachable the whole time.  This would
48558  *  risk a finalizer loop however.
48559  */
48560 
48561 DUK_INTERNAL void duk_heap_process_finalize_list(duk_heap *heap) {
48562 	duk_heaphdr *curr;
48563 #if defined(DUK_USE_DEBUG)
48564 	duk_size_t count = 0;
48565 #endif
48566 
48567 	DUK_DDD(DUK_DDDPRINT("duk_heap_process_finalize_list: %p", (void *) heap));
48568 
48569 	if (heap->pf_prevent_count != 0) {
48570 		DUK_DDD(DUK_DDDPRINT("skip finalize_list processing: pf_prevent_count != 0"));
48571 		return;
48572 	}
48573 
48574 	/* Heap alloc prevents mark-and-sweep before heap_thread is ready. */
48575 	DUK_ASSERT(heap != NULL);
48576 	DUK_ASSERT(heap->heap_thread != NULL);
48577 	DUK_ASSERT(heap->heap_thread->valstack != NULL);
48578 #if defined(DUK_USE_REFERENCE_COUNTING)
48579 	DUK_ASSERT(heap->refzero_list == NULL);
48580 #endif
48581 
48582 	DUK_ASSERT(heap->pf_prevent_count == 0);
48583 	heap->pf_prevent_count = 1;
48584 
48585 	/* Mark-and-sweep no longer needs to be prevented when running
48586 	 * finalizers: mark-and-sweep skips any rescue decisions if there
48587 	 * are any objects in finalize_list when mark-and-sweep is entered.
48588 	 * This protects finalized objects from incorrect rescue decisions
48589 	 * caused by finalize_list being a reachability root and only
48590 	 * partially processed.  Freeing decisions are not postponed.
48591 	 */
48592 
48593 	/* When finalizer torture is enabled, make a fake finalizer call with
48594 	 * maximum side effects regardless of whether finalize_list is empty.
48595 	 */
48596 #if defined(DUK_USE_FINALIZER_TORTURE)
48597 	duk__run_global_torture_finalizer(heap->heap_thread);
48598 #endif
48599 
48600 	/* Process finalize_list until it becomes empty.  There's currently no
48601 	 * protection against a finalizer always creating more garbage.
48602 	 */
48603 	while ((curr = heap->finalize_list) != NULL) {
48604 #if defined(DUK_USE_REFERENCE_COUNTING)
48605 		duk_bool_t queue_back;
48606 #endif
48607 
48608 		DUK_DD(DUK_DDPRINT("processing finalize_list entry: %p -> %!iO", (void *) curr, curr));
48609 
48610 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* Only objects have finalizers. */
48611 		DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));
48612 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(curr));
48613 		DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(curr));  /* All objects on finalize_list will have this flag (except object being finalized right now). */
48614 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));   /* Queueing code ensures. */
48615 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));  /* ROM objects never get freed (or finalized). */
48616 
48617 #if defined(DUK_USE_ASSERTIONS)
48618 		DUK_ASSERT(heap->currently_finalizing == NULL);
48619 		heap->currently_finalizing = curr;
48620 #endif
48621 
48622 		/* Clear FINALIZABLE for object being finalized, so that
48623 		 * duk_push_heapptr() can properly ignore the object.
48624 		 */
48625 		DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
48626 
48627 		if (DUK_LIKELY(!heap->pf_skip_finalizers)) {
48628 			/* Run the finalizer, duk_heap_run_finalizer() sets
48629 			 * and checks for FINALIZED to prevent the finalizer
48630 			 * from executing multiple times per finalization cycle.
48631 			 * (This safeguard shouldn't be actually needed anymore).
48632 			 */
48633 
48634 #if defined(DUK_USE_REFERENCE_COUNTING)
48635 			duk_bool_t had_zero_refcount;
48636 #endif
48637 
48638 			/* The object's refcount is >0 throughout so it won't be
48639 			 * refzero processed prematurely.
48640 			 */
48641 #if defined(DUK_USE_REFERENCE_COUNTING)
48642 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);
48643 			had_zero_refcount = (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1);  /* Preincremented on finalize_list insert. */
48644 #endif
48645 
48646 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
48647 			duk_heap_run_finalizer(heap, (duk_hobject *) curr);  /* must never longjmp */
48648 			DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(curr));
48649 			/* XXX: assert that object is still in finalize_list
48650 			 * when duk_push_heapptr() allows automatic rescue.
48651 			 */
48652 
48653 #if defined(DUK_USE_REFERENCE_COUNTING)
48654 			DUK_DD(DUK_DDPRINT("refcount after finalizer (includes bump): %ld", (long) DUK_HEAPHDR_GET_REFCOUNT(curr)));
48655 			if (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1) {  /* Only artificial bump in refcount? */
48656 #if defined(DUK_USE_DEBUG)
48657 				if (had_zero_refcount) {
48658 					DUK_DD(DUK_DDPRINT("finalized object's refcount is zero -> free immediately (refcount queued)"));
48659 				} else {
48660 					DUK_DD(DUK_DDPRINT("finalized object's refcount is zero -> free immediately (mark-and-sweep queued)"));
48661 				}
48662 #endif
48663 				queue_back = 0;
48664 			} else
48665 #endif
48666 			{
48667 #if defined(DUK_USE_REFERENCE_COUNTING)
48668 				queue_back = 1;
48669 				if (had_zero_refcount) {
48670 					/* When finalization is triggered
48671 					 * by refzero and we queue the object
48672 					 * back, clear FINALIZED right away
48673 					 * so that the object can be refinalized
48674 					 * immediately if necessary.
48675 					 */
48676 					DUK_HEAPHDR_CLEAR_FINALIZED(curr);
48677 				}
48678 #endif
48679 			}
48680 		} else {
48681 			/* Used during heap destruction: don't actually run finalizers
48682 			 * because we're heading into forced finalization.  Instead,
48683 			 * queue finalizable objects back to the heap_allocated list.
48684 			 */
48685 			DUK_D(DUK_DPRINT("skip finalizers flag set, queue object to heap_allocated without finalizing"));
48686 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
48687 #if defined(DUK_USE_REFERENCE_COUNTING)
48688 			queue_back = 1;
48689 #endif
48690 		}
48691 
48692 		/* Dequeue object from finalize_list.  Note that 'curr' may no
48693 		 * longer be finalize_list head because new objects may have
48694 		 * been queued to the list.  As a result we can't optimize for
48695 		 * the single-linked heap case and must scan the list for
48696 		 * removal, typically the scan is very short however.
48697 		 */
48698 		DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap, curr);
48699 
48700 		/* Queue back to heap_allocated or free immediately. */
48701 #if defined(DUK_USE_REFERENCE_COUNTING)
48702 		if (queue_back) {
48703 			/* FINALIZED is only cleared if object originally
48704 			 * queued for finalization by refcounting.  For
48705 			 * mark-and-sweep FINALIZED is left set, so that
48706 			 * next mark-and-sweep round can make a rescue/free
48707 			 * decision.
48708 			 */
48709 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);
48710 			DUK_HEAPHDR_PREDEC_REFCOUNT(curr);  /* Remove artificial refcount bump. */
48711 			DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
48712 			DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);
48713 		} else {
48714 			/* No need to remove the refcount bump here. */
48715 			DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* currently, always the case */
48716 			DUK_DD(DUK_DDPRINT("refcount finalize after finalizer call: %!O", curr));
48717 			duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) curr);
48718 			duk_free_hobject(heap, (duk_hobject *) curr);
48719 			DUK_DD(DUK_DDPRINT("freed hobject after finalization: %p", (void *) curr));
48720 		}
48721 #else  /* DUK_USE_REFERENCE_COUNTING */
48722 		DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
48723 		DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);
48724 #endif  /* DUK_USE_REFERENCE_COUNTING */
48725 
48726 #if defined(DUK_USE_DEBUG)
48727 		count++;
48728 #endif
48729 
48730 #if defined(DUK_USE_ASSERTIONS)
48731 		DUK_ASSERT(heap->currently_finalizing != NULL);
48732 		heap->currently_finalizing = NULL;
48733 #endif
48734 	}
48735 
48736 	/* finalize_list will always be processed completely. */
48737 	DUK_ASSERT(heap->finalize_list == NULL);
48738 
48739 #if 0
48740 	/* While NORZ macros are used above, this is unnecessary because the
48741 	 * only pending side effects are now finalizers, and finalize_list is
48742 	 * empty.
48743 	 */
48744 	DUK_REFZERO_CHECK_SLOW(heap->heap_thread);
48745 #endif
48746 
48747 	/* Prevent count may be bumped while finalizers run, but should always
48748 	 * be reliably unbumped by the time we get here.
48749 	 */
48750 	DUK_ASSERT(heap->pf_prevent_count == 1);
48751 	heap->pf_prevent_count = 0;
48752 
48753 #if defined(DUK_USE_DEBUG)
48754 	DUK_DD(DUK_DDPRINT("duk_heap_process_finalize_list: %ld finalizers called", (long) count));
48755 #endif
48756 }
48757 
48758 /*
48759  *  Run an duk_hobject finalizer.  Must never throw an uncaught error
48760  *  (but may throw caught errors).
48761  *
48762  *  There is no return value.  Any return value or error thrown by
48763  *  the finalizer is ignored (although errors are debug logged).
48764  *
48765  *  Notes:
48766  *
48767  *    - The finalizer thread 'top' assertions are there because it is
48768  *      critical that strict stack policy is observed (i.e. no cruft
48769  *      left on the finalizer stack).
48770  */
48771 
48772 DUK_LOCAL duk_ret_t duk__finalize_helper(duk_hthread *thr, void *udata) {
48773 	DUK_ASSERT(thr != NULL);
48774 	DUK_UNREF(udata);
48775 
48776 	DUK_DDD(DUK_DDDPRINT("protected finalization helper running"));
48777 
48778 	/* [... obj] */
48779 
48780 	/* _Finalizer property is read without checking if the value is
48781 	 * callable or even exists.  This is intentional, and handled
48782 	 * by throwing an error which is caught by the safe call wrapper.
48783 	 *
48784 	 * XXX: Finalizer lookup should traverse the prototype chain (to allow
48785 	 * inherited finalizers) but should not invoke accessors or proxy object
48786 	 * behavior.  At the moment this lookup will invoke proxy behavior, so
48787 	 * caller must ensure that this function is not called if the target is
48788 	 * a Proxy.
48789 	 */
48790 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_FINALIZER);  /* -> [... obj finalizer] */
48791 	duk_dup_m2(thr);
48792 	duk_push_boolean(thr, DUK_HEAP_HAS_FINALIZER_NORESCUE(thr->heap));
48793 	DUK_DDD(DUK_DDDPRINT("calling finalizer"));
48794 	duk_call(thr, 2);  /* [ ... obj finalizer obj heapDestruct ]  -> [ ... obj retval ] */
48795 	DUK_DDD(DUK_DDDPRINT("finalizer returned successfully"));
48796 	return 0;
48797 
48798 	/* Note: we rely on duk_safe_call() to fix up the stack for the caller,
48799 	 * so we don't need to pop stuff here.  There is no return value;
48800 	 * caller determines rescued status based on object refcount.
48801 	 */
48802 }
48803 
48804 DUK_INTERNAL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj) {
48805 	duk_hthread *thr;
48806 	duk_ret_t rc;
48807 #if defined(DUK_USE_ASSERTIONS)
48808 	duk_idx_t entry_top;
48809 #endif
48810 
48811 	DUK_DD(DUK_DDPRINT("running duk_hobject finalizer for object: %p", (void *) obj));
48812 
48813 	DUK_ASSERT(heap != NULL);
48814 	DUK_ASSERT(heap->heap_thread != NULL);
48815 	thr = heap->heap_thread;
48816 	DUK_ASSERT(obj != NULL);
48817 	DUK_ASSERT_VALSTACK_SPACE(heap->heap_thread, 1);
48818 
48819 #if defined(DUK_USE_ASSERTIONS)
48820 	entry_top = duk_get_top(thr);
48821 #endif
48822 	/*
48823 	 *  Get and call the finalizer.  All of this must be wrapped
48824 	 *  in a protected call, because even getting the finalizer
48825 	 *  may trigger an error (getter may throw one, for instance).
48826 	 */
48827 
48828 	/* ROM objects could inherit a finalizer, but they are never deemed
48829 	 * unreachable by mark-and-sweep, and their refcount never falls to 0.
48830 	 */
48831 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
48832 
48833 	/* Duktape 2.1: finalize_list never contains objects with FINALIZED
48834 	 * set, so no need to check here.
48835 	 */
48836 	DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj));
48837 #if 0
48838 	if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj)) {
48839 		DUK_D(DUK_DPRINT("object already finalized, avoid running finalizer twice: %!O", obj));
48840 		return;
48841 	}
48842 #endif
48843 	DUK_HEAPHDR_SET_FINALIZED((duk_heaphdr *) obj);  /* ensure never re-entered until rescue cycle complete */
48844 
48845 #if defined(DUK_USE_ES6_PROXY)
48846 	if (DUK_HOBJECT_IS_PROXY(obj)) {
48847 		/* This may happen if duk_set_finalizer() or Duktape.fin() is
48848 		 * called for a Proxy object.  In such cases the fast finalizer
48849 		 * flag will be set on the Proxy, not the target, and neither
48850 		 * will be finalized.
48851 		 */
48852 		DUK_D(DUK_DPRINT("object is a Proxy, skip finalizer call"));
48853 		return;
48854 	}
48855 #endif  /* DUK_USE_ES6_PROXY */
48856 
48857 	duk_push_hobject(thr, obj);  /* this also increases refcount by one */
48858 	rc = duk_safe_call(thr, duk__finalize_helper, NULL /*udata*/, 0 /*nargs*/, 1 /*nrets*/);  /* -> [... obj retval/error] */
48859 	DUK_ASSERT_TOP(thr, entry_top + 2);  /* duk_safe_call discipline */
48860 
48861 	if (rc != DUK_EXEC_SUCCESS) {
48862 		/* Note: we ask for one return value from duk_safe_call to get this
48863 		 * error debugging here.
48864 		 */
48865 		DUK_D(DUK_DPRINT("wrapped finalizer call failed for object %p (ignored); error: %!T",
48866 		                 (void *) obj, (duk_tval *) duk_get_tval(thr, -1)));
48867 	}
48868 	duk_pop_2(thr);  /* -> [...] */
48869 
48870 	DUK_ASSERT_TOP(thr, entry_top);
48871 }
48872 
48873 #else  /* DUK_USE_FINALIZER_SUPPORT */
48874 
48875 /* nothing */
48876 
48877 #endif  /* DUK_USE_FINALIZER_SUPPORT */
48878 /*
48879  *  String hash computation (interning).
48880  *
48881  *  String hashing is performance critical because a string hash is computed
48882  *  for all new strings which are candidates to be added to the string table.
48883  *  However, strings actually added to the string table go through a codepoint
48884  *  length calculation which dominates performance because it goes through
48885  *  every byte of the input string (but only for strings added).
48886  *
48887  *  The string hash algorithm should be fast, but on the other hand provide
48888  *  good enough hashes to ensure both string table and object property table
48889  *  hash tables work reasonably well (i.e., there aren't too many collisions
48890  *  with real world inputs).  Unless the hash is cryptographic, it's always
48891  *  possible to craft inputs with maximal hash collisions.
48892  *
48893  *  NOTE: The hash algorithms must match tools/dukutil.py:duk_heap_hashstring()
48894  *  for ROM string support!
48895  */
48896 
48897 /* #include duk_internal.h -> already included */
48898 
48899 #if defined(DUK_USE_STRHASH_DENSE)
48900 /* Constants for duk_hashstring(). */
48901 #define DUK__STRHASH_SHORTSTRING   4096L
48902 #define DUK__STRHASH_MEDIUMSTRING  (256L * 1024L)
48903 #define DUK__STRHASH_BLOCKSIZE     256L
48904 
48905 DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
48906 	duk_uint32_t hash;
48907 
48908 	/* Use Murmurhash2 directly for short strings, and use "block skipping"
48909 	 * for long strings: hash an initial part and then sample the rest of
48910 	 * the string with reasonably sized chunks.  An initial offset for the
48911 	 * sampling is computed based on a hash of the initial part of the string;
48912 	 * this is done to (usually) avoid the case where all long strings have
48913 	 * certain offset ranges which are never sampled.
48914 	 *
48915 	 * Skip should depend on length and bound the total time to roughly
48916 	 * logarithmic.  With current values:
48917 	 *
48918 	 *   1M string => 256 * 241 = 61696 bytes (0.06M) of hashing
48919 	 *   1G string => 256 * 16321 = 4178176 bytes (3.98M) of hashing
48920 	 *
48921 	 * XXX: It would be better to compute the skip offset more "smoothly"
48922 	 * instead of having a few boundary values.
48923 	 */
48924 
48925 	/* note: mixing len into seed improves hashing when skipping */
48926 	duk_uint32_t str_seed = heap->hash_seed ^ ((duk_uint32_t) len);
48927 
48928 	if (len <= DUK__STRHASH_SHORTSTRING) {
48929 		hash = duk_util_hashbytes(str, len, str_seed);
48930 	} else {
48931 		duk_size_t off;
48932 		duk_size_t skip;
48933 
48934 		if (len <= DUK__STRHASH_MEDIUMSTRING) {
48935 			skip = (duk_size_t) (16 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
48936 		} else {
48937 			skip = (duk_size_t) (256 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
48938 		}
48939 
48940 		hash = duk_util_hashbytes(str, (duk_size_t) DUK__STRHASH_SHORTSTRING, str_seed);
48941 		off = DUK__STRHASH_SHORTSTRING + (skip * (hash % 256)) / 256;
48942 
48943 		/* XXX: inefficient loop */
48944 		while (off < len) {
48945 			duk_size_t left = len - off;
48946 			duk_size_t now = (duk_size_t) (left > DUK__STRHASH_BLOCKSIZE ? DUK__STRHASH_BLOCKSIZE : left);
48947 			hash ^= duk_util_hashbytes(str + off, now, str_seed);
48948 			off += skip;
48949 		}
48950 	}
48951 
48952 #if defined(DUK_USE_STRHASH16)
48953 	/* Truncate to 16 bits here, so that a computed hash can be compared
48954 	 * against a hash stored in a 16-bit field.
48955 	 */
48956 	hash &= 0x0000ffffUL;
48957 #endif
48958 	return hash;
48959 }
48960 #else  /* DUK_USE_STRHASH_DENSE */
48961 DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
48962 	duk_uint32_t hash;
48963 	duk_size_t step;
48964 	duk_size_t off;
48965 
48966 	/* Slightly modified "Bernstein hash" from:
48967 	 *
48968 	 *     http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
48969 	 *
48970 	 * Modifications: string skipping and reverse direction similar to
48971 	 * Lua 5.1.5, and different hash initializer.
48972 	 *
48973 	 * The reverse direction ensures last byte it always included in the
48974 	 * hash which is a good default as changing parts of the string are
48975 	 * more often in the suffix than in the prefix.
48976 	 */
48977 
48978 	hash = heap->hash_seed ^ ((duk_uint32_t) len);  /* Bernstein hash init value is normally 5381 */
48979 	step = (len >> DUK_USE_STRHASH_SKIP_SHIFT) + 1;
48980 	for (off = len; off >= step; off -= step) {
48981 		DUK_ASSERT(off >= 1);  /* off >= step, and step >= 1 */
48982 		hash = (hash * 33) + str[off - 1];
48983 	}
48984 
48985 #if defined(DUK_USE_STRHASH16)
48986 	/* Truncate to 16 bits here, so that a computed hash can be compared
48987 	 * against a hash stored in a 16-bit field.
48988 	 */
48989 	hash &= 0x0000ffffUL;
48990 #endif
48991 	return hash;
48992 }
48993 #endif  /* DUK_USE_STRHASH_DENSE */
48994 
48995 /* automatic undefs */
48996 #undef DUK__STRHASH_BLOCKSIZE
48997 #undef DUK__STRHASH_MEDIUMSTRING
48998 #undef DUK__STRHASH_SHORTSTRING
48999 /*
49000  *  Mark-and-sweep garbage collection.
49001  */
49002 
49003 /* #include duk_internal.h -> already included */
49004 
49005 DUK_LOCAL_DECL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h);
49006 DUK_LOCAL_DECL void duk__mark_heaphdr_nonnull(duk_heap *heap, duk_heaphdr *h);
49007 DUK_LOCAL_DECL void duk__mark_tval(duk_heap *heap, duk_tval *tv);
49008 DUK_LOCAL_DECL void duk__mark_tvals(duk_heap *heap, duk_tval *tv, duk_idx_t count);
49009 
49010 /*
49011  *  Marking functions for heap types: mark children recursively.
49012  */
49013 
49014 DUK_LOCAL void duk__mark_hstring(duk_heap *heap, duk_hstring *h) {
49015 	DUK_UNREF(heap);
49016 	DUK_UNREF(h);
49017 
49018 	DUK_DDD(DUK_DDDPRINT("duk__mark_hstring: %p", (void *) h));
49019 	DUK_ASSERT(h);
49020 	DUK_HSTRING_ASSERT_VALID(h);
49021 
49022 	/* nothing to process */
49023 }
49024 
49025 DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
49026 	duk_uint_fast32_t i;
49027 
49028 	DUK_DDD(DUK_DDDPRINT("duk__mark_hobject: %p", (void *) h));
49029 
49030 	DUK_ASSERT(h);
49031 	DUK_HOBJECT_ASSERT_VALID(h);
49032 
49033 	/* XXX: use advancing pointers instead of index macros -> faster and smaller? */
49034 
49035 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
49036 		duk_hstring *key = DUK_HOBJECT_E_GET_KEY(heap, h, i);
49037 		if (key == NULL) {
49038 			continue;
49039 		}
49040 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) key);
49041 		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
49042 			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
49043 			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
49044 		} else {
49045 			duk__mark_tval(heap, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
49046 		}
49047 	}
49048 
49049 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
49050 		duk__mark_tval(heap, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
49051 	}
49052 
49053 	/* Hash part is a 'weak reference' and does not contribute. */
49054 
49055 	duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
49056 
49057 	/* Fast path for objects which don't have a subclass struct, or have a
49058 	 * subclass struct but nothing that needs marking in the subclass struct.
49059 	 */
49060 	if (DUK_HOBJECT_HAS_FASTREFS(h)) {
49061 		DUK_ASSERT(DUK_HOBJECT_ALLOWS_FASTREFS(h));
49062 		return;
49063 	}
49064 	DUK_ASSERT(DUK_HOBJECT_PROHIBITS_FASTREFS(h));
49065 
49066 	/* XXX: reorg, more common first */
49067 	if (DUK_HOBJECT_IS_COMPFUNC(h)) {
49068 		duk_hcompfunc *f = (duk_hcompfunc *) h;
49069 		duk_tval *tv, *tv_end;
49070 		duk_hobject **fn, **fn_end;
49071 
49072 		DUK_HCOMPFUNC_ASSERT_VALID(f);
49073 
49074 		/* 'data' is reachable through every compiled function which
49075 		 * contains a reference.
49076 		 */
49077 
49078 		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_DATA(heap, f));
49079 		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_LEXENV(heap, f));
49080 		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_VARENV(heap, f));
49081 
49082 		if (DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL) {
49083 			tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
49084 			tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);
49085 			while (tv < tv_end) {
49086 				duk__mark_tval(heap, tv);
49087 				tv++;
49088 			}
49089 
49090 			fn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);
49091 			fn_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);
49092 			while (fn < fn_end) {
49093 				duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) *fn);
49094 				fn++;
49095 			}
49096 		} else {
49097 			/* May happen in some out-of-memory corner cases. */
49098 			DUK_D(DUK_DPRINT("duk_hcompfunc 'data' is NULL, skipping marking"));
49099 		}
49100 	} else if (DUK_HOBJECT_IS_DECENV(h)) {
49101 		duk_hdecenv *e = (duk_hdecenv *) h;
49102 		DUK_HDECENV_ASSERT_VALID(e);
49103 		duk__mark_heaphdr(heap, (duk_heaphdr *) e->thread);
49104 		duk__mark_heaphdr(heap, (duk_heaphdr *) e->varmap);
49105 	} else if (DUK_HOBJECT_IS_OBJENV(h)) {
49106 		duk_hobjenv *e = (duk_hobjenv *) h;
49107 		DUK_HOBJENV_ASSERT_VALID(e);
49108 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) e->target);
49109 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
49110 	} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
49111 		duk_hbufobj *b = (duk_hbufobj *) h;
49112 		DUK_HBUFOBJ_ASSERT_VALID(b);
49113 		duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf);
49114 		duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf_prop);
49115 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
49116 	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
49117 		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
49118 		DUK_HBOUNDFUNC_ASSERT_VALID(f);
49119 		duk__mark_tval(heap, &f->target);
49120 		duk__mark_tval(heap, &f->this_binding);
49121 		duk__mark_tvals(heap, f->args, f->nargs);
49122 #if defined(DUK_USE_ES6_PROXY)
49123 	} else if (DUK_HOBJECT_IS_PROXY(h)) {
49124 		duk_hproxy *p = (duk_hproxy *) h;
49125 		DUK_HPROXY_ASSERT_VALID(p);
49126 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) p->target);
49127 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) p->handler);
49128 #endif  /* DUK_USE_ES6_PROXY */
49129 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
49130 		duk_hthread *t = (duk_hthread *) h;
49131 		duk_activation *act;
49132 		duk_tval *tv;
49133 
49134 		DUK_HTHREAD_ASSERT_VALID(t);
49135 
49136 		tv = t->valstack;
49137 		while (tv < t->valstack_top) {
49138 			duk__mark_tval(heap, tv);
49139 			tv++;
49140 		}
49141 
49142 		for (act = t->callstack_curr; act != NULL; act = act->parent) {
49143 			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_ACT_GET_FUNC(act));
49144 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->var_env);
49145 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->lex_env);
49146 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
49147 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->prev_caller);
49148 #endif
49149 #if 0  /* nothing now */
49150 			for (cat = act->cat; cat != NULL; cat = cat->parent) {
49151 			}
49152 #endif
49153 		}
49154 
49155 		duk__mark_heaphdr(heap, (duk_heaphdr *) t->resumer);
49156 
49157 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
49158 			duk__mark_heaphdr(heap, (duk_heaphdr *) t->builtins[i]);
49159 		}
49160 	} else {
49161 		/* We may come here if the object should have a FASTREFS flag
49162 		 * but it's missing for some reason.  Assert for never getting
49163 		 * here; however, other than performance, this is harmless.
49164 		 */
49165 		DUK_D(DUK_DPRINT("missing FASTREFS flag for: %!iO", h));
49166 		DUK_ASSERT(0);
49167 	}
49168 }
49169 
49170 /* Mark any duk_heaphdr type.  Recursion tracking happens only here. */
49171 DUK_LOCAL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h) {
49172 	DUK_DDD(DUK_DDDPRINT("duk__mark_heaphdr %p, type %ld",
49173 	                     (void *) h,
49174 	                     (h != NULL ? (long) DUK_HEAPHDR_GET_TYPE(h) : (long) -1)));
49175 
49176 	/* XXX: add non-null variant? */
49177 	if (h == NULL) {
49178 		return;
49179 	}
49180 
49181 	DUK_HEAPHDR_ASSERT_VALID(h);
49182 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(h) || DUK_HEAPHDR_HAS_REACHABLE(h));
49183 
49184 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
49185 	if (!DUK_HEAPHDR_HAS_READONLY(h)) {
49186 		h->h_assert_refcount++;  /* Comparison refcount: bump even if already reachable. */
49187 	}
49188 #endif
49189 	if (DUK_HEAPHDR_HAS_REACHABLE(h)) {
49190 		DUK_DDD(DUK_DDDPRINT("already marked reachable, skip"));
49191 		return;
49192 	}
49193 #if defined(DUK_USE_ROM_OBJECTS)
49194 	/* READONLY objects always have REACHABLE set, so the check above
49195 	 * will prevent READONLY objects from being marked here.
49196 	 */
49197 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(h));
49198 #endif
49199 
49200 	DUK_HEAPHDR_SET_REACHABLE(h);
49201 
49202 	if (heap->ms_recursion_depth >= DUK_USE_MARK_AND_SWEEP_RECLIMIT) {
49203 		DUK_D(DUK_DPRINT("mark-and-sweep recursion limit reached, marking as temproot: %p", (void *) h));
49204 		DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap);
49205 		DUK_HEAPHDR_SET_TEMPROOT(h);
49206 		return;
49207 	}
49208 
49209 	heap->ms_recursion_depth++;
49210 	DUK_ASSERT(heap->ms_recursion_depth != 0);  /* Wrap. */
49211 
49212 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
49213 	case DUK_HTYPE_STRING:
49214 		duk__mark_hstring(heap, (duk_hstring *) h);
49215 		break;
49216 	case DUK_HTYPE_OBJECT:
49217 		duk__mark_hobject(heap, (duk_hobject *) h);
49218 		break;
49219 	case DUK_HTYPE_BUFFER:
49220 		/* nothing to mark */
49221 		break;
49222 	default:
49223 		DUK_D(DUK_DPRINT("attempt to mark heaphdr %p with invalid htype %ld", (void *) h, (long) DUK_HEAPHDR_GET_TYPE(h)));
49224 		DUK_UNREACHABLE();
49225 	}
49226 
49227 	DUK_ASSERT(heap->ms_recursion_depth > 0);
49228 	heap->ms_recursion_depth--;
49229 }
49230 
49231 DUK_LOCAL void duk__mark_tval(duk_heap *heap, duk_tval *tv) {
49232 	DUK_DDD(DUK_DDDPRINT("duk__mark_tval %p", (void *) tv));
49233 	if (tv == NULL) {
49234 		return;
49235 	}
49236 	DUK_TVAL_ASSERT_VALID(tv);
49237 	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
49238 		duk_heaphdr *h;
49239 		h = DUK_TVAL_GET_HEAPHDR(tv);
49240 		DUK_ASSERT(h != NULL);
49241 		duk__mark_heaphdr_nonnull(heap, h);
49242 	}
49243 }
49244 
49245 DUK_LOCAL void duk__mark_tvals(duk_heap *heap, duk_tval *tv, duk_idx_t count) {
49246 	DUK_ASSERT(count == 0 || tv != NULL);
49247 
49248 	while (count-- > 0) {
49249 		DUK_TVAL_ASSERT_VALID(tv);
49250 		if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
49251 			duk_heaphdr *h;
49252 			h = DUK_TVAL_GET_HEAPHDR(tv);
49253 			DUK_ASSERT(h != NULL);
49254 			duk__mark_heaphdr_nonnull(heap, h);
49255 		}
49256 		tv++;
49257 	}
49258 }
49259 
49260 /* Mark any duk_heaphdr type, caller guarantees a non-NULL pointer. */
49261 DUK_LOCAL void duk__mark_heaphdr_nonnull(duk_heap *heap, duk_heaphdr *h) {
49262 	/* For now, just call the generic handler.  Change when call sites
49263 	 * are changed too.
49264 	 */
49265 	duk__mark_heaphdr(heap, h);
49266 }
49267 
49268 /*
49269  *  Mark the heap.
49270  */
49271 
49272 DUK_LOCAL void duk__mark_roots_heap(duk_heap *heap) {
49273 	duk_small_uint_t i;
49274 
49275 	DUK_DD(DUK_DDPRINT("duk__mark_roots_heap: %p", (void *) heap));
49276 
49277 	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_thread);
49278 	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_object);
49279 
49280 	for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
49281 		duk_hstring *h = DUK_HEAP_GET_STRING(heap, i);
49282 		duk__mark_heaphdr(heap, (duk_heaphdr *) h);
49283 	}
49284 
49285 	duk__mark_tval(heap, &heap->lj.value1);
49286 	duk__mark_tval(heap, &heap->lj.value2);
49287 
49288 #if defined(DUK_USE_DEBUGGER_SUPPORT)
49289 	for (i = 0; i < heap->dbg_breakpoint_count; i++) {
49290 		duk__mark_heaphdr(heap, (duk_heaphdr *) heap->dbg_breakpoints[i].filename);
49291 	}
49292 #endif
49293 }
49294 
49295 /*
49296  *  Mark unreachable, finalizable objects.
49297  *
49298  *  Such objects will be moved aside and their finalizers run later.  They
49299  *  have to be treated as reachability roots for their properties etc to
49300  *  remain allocated.  This marking is only done for unreachable values which
49301  *  would be swept later.
49302  *
49303  *  Objects are first marked FINALIZABLE and only then marked as reachability
49304  *  roots; otherwise circular references might be handled inconsistently.
49305  */
49306 
49307 #if defined(DUK_USE_FINALIZER_SUPPORT)
49308 DUK_LOCAL void duk__mark_finalizable(duk_heap *heap) {
49309 	duk_heaphdr *hdr;
49310 	duk_size_t count_finalizable = 0;
49311 
49312 	DUK_DD(DUK_DDPRINT("duk__mark_finalizable: %p", (void *) heap));
49313 
49314 	DUK_ASSERT(heap->heap_thread != NULL);
49315 
49316 	hdr = heap->heap_allocated;
49317 	while (hdr != NULL) {
49318 		/* A finalizer is looked up from the object and up its
49319 		 * prototype chain (which allows inherited finalizers).
49320 		 * The finalizer is checked for using a duk_hobject flag
49321 		 * which is kept in sync with the presence and callability
49322 		 * of a _Finalizer hidden symbol.
49323 		 */
49324 
49325 		if (!DUK_HEAPHDR_HAS_REACHABLE(hdr) &&
49326 		    DUK_HEAPHDR_IS_OBJECT(hdr) &&
49327 		    !DUK_HEAPHDR_HAS_FINALIZED(hdr) &&
49328 		    DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) hdr)) {
49329 			/* heaphdr:
49330 			 *  - is not reachable
49331 			 *  - is an object
49332 			 *  - is not a finalized object waiting for rescue/keep decision
49333 			 *  - has a finalizer
49334 			 */
49335 
49336 			DUK_DD(DUK_DDPRINT("unreachable heap object will be "
49337 			                   "finalized -> mark as finalizable "
49338 			                   "and treat as a reachability root: %p",
49339 			                   (void *) hdr));
49340 			DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr));
49341 			DUK_HEAPHDR_SET_FINALIZABLE(hdr);
49342 			count_finalizable++;
49343 		}
49344 
49345 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49346 	}
49347 
49348 	if (count_finalizable == 0) {
49349 		return;
49350 	}
49351 
49352 	DUK_DD(DUK_DDPRINT("marked %ld heap objects as finalizable, now mark them reachable",
49353 	                   (long) count_finalizable));
49354 
49355 	hdr = heap->heap_allocated;
49356 	while (hdr != NULL) {
49357 		if (DUK_HEAPHDR_HAS_FINALIZABLE(hdr)) {
49358 			duk__mark_heaphdr_nonnull(heap, hdr);
49359 		}
49360 
49361 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49362 	}
49363 
49364 	/* Caller will finish the marking process if we hit a recursion limit. */
49365 }
49366 #endif  /* DUK_USE_FINALIZER_SUPPORT */
49367 
49368 /*
49369  *  Mark objects on finalize_list.
49370  */
49371 
49372 #if defined(DUK_USE_FINALIZER_SUPPORT)
49373 DUK_LOCAL void duk__mark_finalize_list(duk_heap *heap) {
49374 	duk_heaphdr *hdr;
49375 #if defined(DUK_USE_DEBUG)
49376 	duk_size_t count_finalize_list = 0;
49377 #endif
49378 
49379 	DUK_DD(DUK_DDPRINT("duk__mark_finalize_list: %p", (void *) heap));
49380 
49381 	hdr = heap->finalize_list;
49382 	while (hdr != NULL) {
49383 		duk__mark_heaphdr_nonnull(heap, hdr);
49384 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49385 #if defined(DUK_USE_DEBUG)
49386 		count_finalize_list++;
49387 #endif
49388 	}
49389 
49390 #if defined(DUK_USE_DEBUG)
49391 	if (count_finalize_list > 0) {
49392 		DUK_D(DUK_DPRINT("marked %ld objects on the finalize_list as reachable (previous finalizer run skipped)",
49393 		                 (long) count_finalize_list));
49394 	}
49395 #endif
49396 }
49397 #endif  /* DUK_USE_FINALIZER_SUPPORT */
49398 
49399 /*
49400  *  Fallback marking handler if recursion limit is reached.
49401  *
49402  *  Iterates 'temproots' until recursion limit is no longer hit.  Temproots
49403  *  can be in heap_allocated or finalize_list; refzero_list is now always
49404  *  empty for mark-and-sweep.  A temproot may occur in finalize_list now if
49405  *  there are objects on the finalize_list and user code creates a reference
49406  *  from an object in heap_allocated to the object in finalize_list (which is
49407  *  now allowed), and it happened to coincide with the recursion depth limit.
49408  *
49409  *  This is a slow scan, but guarantees that we finish with a bounded C stack.
49410  *
49411  *  Note that nodes may have been marked as temproots before this scan begun,
49412  *  OR they may have been marked during the scan (as we process nodes
49413  *  recursively also during the scan).  This is intended behavior.
49414  */
49415 
49416 #if defined(DUK_USE_DEBUG)
49417 DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr, duk_size_t *count) {
49418 #else
49419 DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr) {
49420 #endif
49421 	DUK_ASSERT(hdr != NULL);
49422 
49423 	if (!DUK_HEAPHDR_HAS_TEMPROOT(hdr)) {
49424 		DUK_DDD(DUK_DDDPRINT("not a temp root: %p", (void *) hdr));
49425 		return;
49426 	}
49427 
49428 	DUK_DDD(DUK_DDDPRINT("found a temp root: %p", (void *) hdr));
49429 	DUK_HEAPHDR_CLEAR_TEMPROOT(hdr);
49430 	DUK_HEAPHDR_CLEAR_REACHABLE(hdr);  /* Done so that duk__mark_heaphdr() works correctly. */
49431 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
49432 	hdr->h_assert_refcount--;  /* Same node visited twice. */
49433 #endif
49434 	duk__mark_heaphdr_nonnull(heap, hdr);
49435 
49436 #if defined(DUK_USE_DEBUG)
49437 	(*count)++;
49438 #endif
49439 }
49440 
49441 DUK_LOCAL void duk__mark_temproots_by_heap_scan(duk_heap *heap) {
49442 	duk_heaphdr *hdr;
49443 #if defined(DUK_USE_DEBUG)
49444 	duk_size_t count;
49445 #endif
49446 
49447 	DUK_DD(DUK_DDPRINT("duk__mark_temproots_by_heap_scan: %p", (void *) heap));
49448 
49449 	while (DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)) {
49450 		DUK_DD(DUK_DDPRINT("recursion limit reached, doing heap scan to continue from temproots"));
49451 
49452 #if defined(DUK_USE_DEBUG)
49453 		count = 0;
49454 #endif
49455 		DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap);
49456 
49457 		hdr = heap->heap_allocated;
49458 		while (hdr) {
49459 #if defined(DUK_USE_DEBUG)
49460 			duk__handle_temproot(heap, hdr, &count);
49461 #else
49462 			duk__handle_temproot(heap, hdr);
49463 #endif
49464 			hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49465 		}
49466 
49467 #if defined(DUK_USE_FINALIZER_SUPPORT)
49468 		hdr = heap->finalize_list;
49469 		while (hdr) {
49470 #if defined(DUK_USE_DEBUG)
49471 			duk__handle_temproot(heap, hdr, &count);
49472 #else
49473 			duk__handle_temproot(heap, hdr);
49474 #endif
49475 			hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49476 		}
49477 #endif
49478 
49479 #if defined(DUK_USE_DEBUG)
49480 		DUK_DD(DUK_DDPRINT("temproot mark heap scan processed %ld temp roots", (long) count));
49481 #endif
49482 	}
49483 }
49484 
49485 /*
49486  *  Finalize refcounts for heap elements just about to be freed.
49487  *  This must be done for all objects before freeing to avoid any
49488  *  stale pointer dereferences.
49489  *
49490  *  Note that this must deduce the set of objects to be freed
49491  *  identically to duk__sweep_heap().
49492  */
49493 
49494 #if defined(DUK_USE_REFERENCE_COUNTING)
49495 DUK_LOCAL void duk__finalize_refcounts(duk_heap *heap) {
49496 	duk_heaphdr *hdr;
49497 
49498 	DUK_ASSERT(heap->heap_thread != NULL);
49499 
49500 	DUK_DD(DUK_DDPRINT("duk__finalize_refcounts: heap=%p", (void *) heap));
49501 
49502 	hdr = heap->heap_allocated;
49503 	while (hdr) {
49504 		if (!DUK_HEAPHDR_HAS_REACHABLE(hdr)) {
49505 			/*
49506 			 *  Unreachable object about to be swept.  Finalize target refcounts
49507 			 *  (objects which the unreachable object points to) without doing
49508 			 *  refzero processing.  Recursive decrefs are also prevented when
49509 			 *  refzero processing is disabled.
49510 			 *
49511 			 *  Value cannot be a finalizable object, as they have been made
49512 			 *  temporarily reachable for this round.
49513 			 */
49514 
49515 			DUK_DDD(DUK_DDDPRINT("unreachable object, refcount finalize before sweeping: %p", (void *) hdr));
49516 
49517 			/* Finalize using heap->heap_thread; DECREF has a
49518 			 * suppress check for mark-and-sweep which is based
49519 			 * on heap->ms_running.
49520 			 */
49521 			duk_heaphdr_refcount_finalize_norz(heap, hdr);
49522 		}
49523 
49524 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49525 	}
49526 }
49527 #endif  /* DUK_USE_REFERENCE_COUNTING */
49528 
49529 /*
49530  *  Clear (reachable) flags of finalize_list.
49531  *
49532  *  We could mostly do in the sweep phase when we move objects from the
49533  *  heap into the finalize_list.  However, if a finalizer run is skipped
49534  *  during a mark-and-sweep, the objects on the finalize_list will be marked
49535  *  reachable during the next mark-and-sweep.  Since they're already on the
49536  *  finalize_list, no-one will be clearing their REACHABLE flag so we do it
49537  *  here.  (This now overlaps with the sweep handling in a harmless way.)
49538  */
49539 
49540 #if defined(DUK_USE_FINALIZER_SUPPORT)
49541 DUK_LOCAL void duk__clear_finalize_list_flags(duk_heap *heap) {
49542 	duk_heaphdr *hdr;
49543 
49544 	DUK_DD(DUK_DDPRINT("duk__clear_finalize_list_flags: %p", (void *) heap));
49545 
49546 	hdr = heap->finalize_list;
49547 	while (hdr) {
49548 		DUK_HEAPHDR_CLEAR_REACHABLE(hdr);
49549 #if defined(DUK_USE_ASSERTIONS)
49550 		DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(hdr) || \
49551 		           (heap->currently_finalizing == hdr));
49552 #endif
49553 		/* DUK_HEAPHDR_FLAG_FINALIZED may be set. */
49554 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
49555 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49556 	}
49557 }
49558 #endif  /* DUK_USE_FINALIZER_SUPPORT */
49559 
49560 /*
49561  *  Sweep stringtable.
49562  */
49563 
49564 DUK_LOCAL void duk__sweep_stringtable(duk_heap *heap, duk_size_t *out_count_keep) {
49565 	duk_hstring *h;
49566 	duk_hstring *prev;
49567 	duk_uint32_t i;
49568 #if defined(DUK_USE_DEBUG)
49569 	duk_size_t count_free = 0;
49570 #endif
49571 	duk_size_t count_keep = 0;
49572 
49573 	DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));
49574 
49575 #if defined(DUK_USE_STRTAB_PTRCOMP)
49576 	if (heap->strtable16 == NULL) {
49577 #else
49578 	if (heap->strtable == NULL) {
49579 #endif
49580 		goto done;
49581 	}
49582 
49583 	for (i = 0; i < heap->st_size; i++) {
49584 #if defined(DUK_USE_STRTAB_PTRCOMP)
49585 		h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
49586 #else
49587 		h = heap->strtable[i];
49588 #endif
49589 		prev = NULL;
49590 		while (h != NULL) {
49591 			duk_hstring *next;
49592 			next = h->hdr.h_next;
49593 
49594 			if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h))
49595 			{
49596 				DUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h);
49597 				count_keep++;
49598 				prev = h;
49599 			} else {
49600 #if defined(DUK_USE_DEBUG)
49601 				count_free++;
49602 #endif
49603 
49604 				/* For pinned strings the refcount has been
49605 				 * bumped.  We could unbump it here before
49606 				 * freeing, but that's actually not necessary
49607 				 * except for assertions.
49608 				 */
49609 #if 0
49610 				if (DUK_HSTRING_HAS_PINNED_LITERAL(h)) {
49611 					DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) > 0U);
49612 					DUK_HSTRING_DECREF_NORZ(heap->heap_thread, h);
49613 					DUK_HSTRING_CLEAR_PINNED_LITERAL(h);
49614 				}
49615 #endif
49616 #if defined(DUK_USE_REFERENCE_COUNTING)
49617 				/* Non-zero refcounts should not happen for unreachable strings,
49618 				 * because we refcount finalize all unreachable objects which
49619 				 * should have decreased unreachable string refcounts to zero
49620 				 * (even for cycles).  However, pinned strings have a +1 bump.
49621 				 */
49622 				DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) ==
49623 				           DUK_HSTRING_HAS_PINNED_LITERAL(h) ? 1U : 0U);
49624 #endif
49625 
49626 				/* Deal with weak references first. */
49627 				duk_heap_strcache_string_remove(heap, (duk_hstring *) h);
49628 
49629 				/* Remove the string from the string table. */
49630 				duk_heap_strtable_unlink_prev(heap, (duk_hstring *) h, (duk_hstring *) prev);
49631 
49632 				/* Free inner references (these exist e.g. when external
49633 				 * strings are enabled) and the struct itself.
49634 				 */
49635 				duk_free_hstring(heap, (duk_hstring *) h);
49636 
49637 				/* Don't update 'prev'; it should be last string kept. */
49638 			}
49639 
49640 			h = next;
49641 		}
49642 	}
49643 
49644  done:
49645 #if defined(DUK_USE_DEBUG)
49646 	DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept",
49647 	                 (long) count_free, (long) count_keep));
49648 #endif
49649 	*out_count_keep = count_keep;
49650 }
49651 
49652 /*
49653  *  Sweep heap.
49654  */
49655 
49656 DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_small_uint_t flags, duk_size_t *out_count_keep) {
49657 	duk_heaphdr *prev;  /* last element that was left in the heap */
49658 	duk_heaphdr *curr;
49659 	duk_heaphdr *next;
49660 #if defined(DUK_USE_DEBUG)
49661 	duk_size_t count_free = 0;
49662 	duk_size_t count_finalize = 0;
49663 	duk_size_t count_rescue = 0;
49664 #endif
49665 	duk_size_t count_keep = 0;
49666 
49667 	DUK_DD(DUK_DDPRINT("duk__sweep_heap: %p", (void *) heap));
49668 
49669 	prev = NULL;
49670 	curr = heap->heap_allocated;
49671 	heap->heap_allocated = NULL;
49672 	while (curr) {
49673 		/* Strings and ROM objects are never placed on the heap allocated list. */
49674 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_STRING);
49675 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));
49676 
49677 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
49678 
49679 		if (DUK_HEAPHDR_HAS_REACHABLE(curr)) {
49680 			/*
49681 			 *  Reachable object:
49682 			 *    - If FINALIZABLE -> actually unreachable (but marked
49683 			 *      artificially reachable), queue to finalize_list.
49684 			 *    - If !FINALIZABLE but FINALIZED -> rescued after
49685 			 *      finalizer execution.
49686 			 *    - Otherwise just a normal, reachable object.
49687 			 *
49688 			 *  Objects which are kept are queued to heap_allocated
49689 			 *  tail (we're essentially filtering heap_allocated in
49690 			 *  practice).
49691 			 */
49692 
49693 #if defined(DUK_USE_FINALIZER_SUPPORT)
49694 			if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZABLE(curr))) {
49695 				DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
49696 				DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);
49697 				DUK_DD(DUK_DDPRINT("sweep; reachable, finalizable --> move to finalize_list: %p", (void *) curr));
49698 
49699 #if defined(DUK_USE_REFERENCE_COUNTING)
49700 				DUK_HEAPHDR_PREINC_REFCOUNT(curr);  /* Bump refcount so that refzero never occurs when pending a finalizer call. */
49701 #endif
49702 				DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap, curr);
49703 #if defined(DUK_USE_DEBUG)
49704 				count_finalize++;
49705 #endif
49706 			}
49707 			else
49708 #endif  /* DUK_USE_FINALIZER_SUPPORT */
49709 			{
49710 				if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZED(curr))) {
49711 					DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
49712 					DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);
49713 
49714 					if (flags & DUK_MS_FLAG_POSTPONE_RESCUE) {
49715 						DUK_DD(DUK_DDPRINT("sweep; reachable, finalized, but postponing rescue decisions --> keep object (with FINALIZED set): %!iO", curr));
49716 						count_keep++;
49717 					} else {
49718 						DUK_DD(DUK_DDPRINT("sweep; reachable, finalized --> rescued after finalization: %p", (void *) curr));
49719 #if defined(DUK_USE_FINALIZER_SUPPORT)
49720 						DUK_HEAPHDR_CLEAR_FINALIZED(curr);
49721 #endif
49722 #if defined(DUK_USE_DEBUG)
49723 						count_rescue++;
49724 #endif
49725 					}
49726 				} else {
49727 					DUK_DD(DUK_DDPRINT("sweep; reachable --> keep: %!iO", curr));
49728 					count_keep++;
49729 				}
49730 
49731 				if (prev != NULL) {
49732 					DUK_ASSERT(heap->heap_allocated != NULL);
49733 					DUK_HEAPHDR_SET_NEXT(heap, prev, curr);
49734 				} else {
49735 					DUK_ASSERT(heap->heap_allocated == NULL);
49736 					heap->heap_allocated = curr;
49737 				}
49738 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
49739 				DUK_HEAPHDR_SET_PREV(heap, curr, prev);
49740 #endif
49741 				DUK_HEAPHDR_ASSERT_LINKS(heap, prev);
49742 				DUK_HEAPHDR_ASSERT_LINKS(heap, curr);
49743 				prev = curr;
49744 			}
49745 
49746 			/*
49747 			 *  Shrink check for value stacks here.  We're inside
49748 			 *  ms_prevent_count protection which prevents recursive
49749 			 *  mark-and-sweep and refzero finalizers, so there are
49750 			 *  no side effects that would affect the heap lists.
49751 			 */
49752 			if (DUK_HEAPHDR_IS_OBJECT(curr) && DUK_HOBJECT_IS_THREAD((duk_hobject *) curr)) {
49753 				duk_hthread *thr_curr = (duk_hthread *) curr;
49754 				DUK_DD(DUK_DDPRINT("value stack shrink check for thread: %!O", curr));
49755 				duk_valstack_shrink_check_nothrow(thr_curr, flags & DUK_MS_FLAG_EMERGENCY /*snug*/);
49756 			}
49757 
49758 			DUK_HEAPHDR_CLEAR_REACHABLE(curr);
49759 			/* Keep FINALIZED if set, used if rescue decisions are postponed. */
49760 			/* Keep FINALIZABLE for objects on finalize_list. */
49761 			DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));
49762 		} else {
49763 			/*
49764 			 *  Unreachable object:
49765 			 *    - If FINALIZED, object was finalized but not
49766 			 *      rescued.  This doesn't affect freeing.
49767 			 *    - Otherwise normal unreachable object.
49768 			 *
49769 			 *  There's no guard preventing a FINALIZED object
49770 			 *  from being freed while finalizers execute: the
49771 			 *  artificial finalize_list reachability roots can't
49772 			 *  cause an incorrect free decision (but can cause
49773 			 *  an incorrect rescue decision).
49774 			 */
49775 
49776 #if defined(DUK_USE_REFERENCE_COUNTING)
49777 			/* Non-zero refcounts should not happen because we refcount
49778 			 * finalize all unreachable objects which should cancel out
49779 			 * refcounts (even for cycles).
49780 			 */
49781 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) == 0);
49782 #endif
49783 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
49784 
49785 #if defined(DUK_USE_DEBUG)
49786 			if (DUK_HEAPHDR_HAS_FINALIZED(curr)) {
49787 				DUK_DD(DUK_DDPRINT("sweep; unreachable, finalized --> finalized object not rescued: %p", (void *) curr));
49788 			} else {
49789 				DUK_DD(DUK_DDPRINT("sweep; not reachable --> free: %p", (void *) curr));
49790 			}
49791 
49792 #endif
49793 
49794 			/* Note: object cannot be a finalizable unreachable object, as
49795 			 * they have been marked temporarily reachable for this round,
49796 			 * and are handled above.
49797 			 */
49798 
49799 #if defined(DUK_USE_DEBUG)
49800 			count_free++;
49801 #endif
49802 
49803 			/* Weak refs should be handled here, but no weak refs for
49804 			 * any non-string objects exist right now.
49805 			 */
49806 
49807 			/* Free object and all auxiliary (non-heap) allocs. */
49808 			duk_heap_free_heaphdr_raw(heap, curr);
49809 		}
49810 
49811 		curr = next;
49812 	}
49813 
49814 	if (prev != NULL) {
49815 		DUK_HEAPHDR_SET_NEXT(heap, prev, NULL);
49816 	}
49817 	DUK_HEAPHDR_ASSERT_LINKS(heap, prev);
49818 
49819 #if defined(DUK_USE_DEBUG)
49820 	DUK_D(DUK_DPRINT("mark-and-sweep sweep objects (non-string): %ld freed, %ld kept, %ld rescued, %ld queued for finalization",
49821 	                 (long) count_free, (long) count_keep, (long) count_rescue, (long) count_finalize));
49822 #endif
49823 	*out_count_keep = count_keep;
49824 }
49825 
49826 /*
49827  *  Litcache helpers.
49828  */
49829 
49830 #if defined(DUK_USE_LITCACHE_SIZE)
49831 DUK_LOCAL void duk__wipe_litcache(duk_heap *heap) {
49832 	duk_uint_t i;
49833 	duk_litcache_entry *e;
49834 
49835 	e = heap->litcache;
49836 	for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
49837 		e->addr = NULL;
49838 		/* e->h does not need to be invalidated: when e->addr is
49839 		 * NULL, e->h is considered garbage.
49840 		 */
49841 		e++;
49842 	}
49843 }
49844 #endif  /* DUK_USE_LITCACHE_SIZE */
49845 
49846 /*
49847  *  Object compaction.
49848  *
49849  *  Compaction is assumed to never throw an error.
49850  */
49851 
49852 DUK_LOCAL int duk__protected_compact_object(duk_hthread *thr, void *udata) {
49853 	duk_hobject *obj;
49854 	/* XXX: for threads, compact stacks? */
49855 
49856 	DUK_UNREF(udata);
49857 	obj = duk_known_hobject(thr, -1);
49858 	duk_hobject_compact_props(thr, obj);
49859 	return 0;
49860 }
49861 
49862 #if defined(DUK_USE_DEBUG)
49863 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) {
49864 #else
49865 DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start) {
49866 #endif
49867 	duk_heaphdr *curr;
49868 #if defined(DUK_USE_DEBUG)
49869 	duk_size_t old_size, new_size;
49870 #endif
49871 	duk_hobject *obj;
49872 
49873 	DUK_UNREF(heap);
49874 
49875 	curr = start;
49876 	while (curr) {
49877 		DUK_DDD(DUK_DDDPRINT("mark-and-sweep compact: %p", (void *) curr));
49878 
49879 		if (DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_OBJECT) {
49880 			goto next;
49881 		}
49882 		obj = (duk_hobject *) curr;
49883 
49884 #if defined(DUK_USE_DEBUG)
49885 		old_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
49886 		                                      DUK_HOBJECT_GET_ASIZE(obj),
49887 		                                      DUK_HOBJECT_GET_HSIZE(obj));
49888 #endif
49889 
49890 		DUK_DD(DUK_DDPRINT("compact object: %p", (void *) obj));
49891 		duk_push_hobject(thr, obj);
49892 		/* XXX: disable error handlers for duration of compaction? */
49893 		duk_safe_call(thr, duk__protected_compact_object, NULL, 1, 0);
49894 
49895 #if defined(DUK_USE_DEBUG)
49896 		new_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
49897 		                                      DUK_HOBJECT_GET_ASIZE(obj),
49898 		                                      DUK_HOBJECT_GET_HSIZE(obj));
49899 #endif
49900 
49901 #if defined(DUK_USE_DEBUG)
49902 		(*p_count_compact)++;
49903 		(*p_count_bytes_saved) += (duk_size_t) (old_size - new_size);
49904 #endif
49905 
49906 	 next:
49907 		curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
49908 #if defined(DUK_USE_DEBUG)
49909 		(*p_count_check)++;
49910 #endif
49911 	}
49912 }
49913 
49914 DUK_LOCAL void duk__compact_objects(duk_heap *heap) {
49915 	/* XXX: which lists should participate?  to be finalized? */
49916 #if defined(DUK_USE_DEBUG)
49917 	duk_size_t count_check = 0;
49918 	duk_size_t count_compact = 0;
49919 	duk_size_t count_bytes_saved = 0;
49920 #endif
49921 
49922 	DUK_DD(DUK_DDPRINT("duk__compact_objects: %p", (void *) heap));
49923 
49924 	DUK_ASSERT(heap->heap_thread != NULL);
49925 
49926 #if defined(DUK_USE_DEBUG)
49927 	duk__compact_object_list(heap, heap->heap_thread, heap->heap_allocated, &count_check, &count_compact, &count_bytes_saved);
49928 #if defined(DUK_USE_FINALIZER_SUPPORT)
49929 	duk__compact_object_list(heap, heap->heap_thread, heap->finalize_list, &count_check, &count_compact, &count_bytes_saved);
49930 #endif
49931 #else
49932 	duk__compact_object_list(heap, heap->heap_thread, heap->heap_allocated);
49933 #if defined(DUK_USE_FINALIZER_SUPPORT)
49934 	duk__compact_object_list(heap, heap->heap_thread, heap->finalize_list);
49935 #endif
49936 #endif
49937 #if defined(DUK_USE_REFERENCE_COUNTING)
49938 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always handled to completion inline in DECREF. */
49939 #endif
49940 
49941 #if defined(DUK_USE_DEBUG)
49942 	DUK_D(DUK_DPRINT("mark-and-sweep compact objects: %ld checked, %ld compaction attempts, %ld bytes saved by compaction",
49943 	                 (long) count_check, (long) count_compact, (long) count_bytes_saved));
49944 #endif
49945 }
49946 
49947 /*
49948  *  Assertion helpers.
49949  */
49950 
49951 #if defined(DUK_USE_ASSERTIONS)
49952 typedef void (*duk__gc_heaphdr_assert)(duk_heap *heap, duk_heaphdr *h);
49953 typedef void (*duk__gc_hstring_assert)(duk_heap *heap, duk_hstring *h);
49954 
49955 DUK_LOCAL void duk__assert_walk_list(duk_heap *heap, duk_heaphdr *start, duk__gc_heaphdr_assert func) {
49956 	duk_heaphdr *curr;
49957 	for (curr = start; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
49958 		func(heap, curr);
49959 	}
49960 }
49961 
49962 DUK_LOCAL void duk__assert_walk_strtable(duk_heap *heap, duk__gc_hstring_assert func) {
49963 	duk_uint32_t i;
49964 
49965 	for (i = 0; i < heap->st_size; i++) {
49966 		duk_hstring *h;
49967 
49968 #if defined(DUK_USE_STRTAB_PTRCOMP)
49969 		h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
49970 #else
49971 		h = heap->strtable[i];
49972 #endif
49973 		while (h != NULL) {
49974 			func(heap, h);
49975 			h = h->hdr.h_next;
49976 		}
49977 	}
49978 }
49979 
49980 DUK_LOCAL void duk__assert_heaphdr_flags_cb(duk_heap *heap, duk_heaphdr *h) {
49981 	DUK_UNREF(heap);
49982 	DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(h));
49983 	DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(h));
49984 	DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(h));
49985 	/* may have FINALIZED */
49986 }
49987 DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
49988 	duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_heaphdr_flags_cb);
49989 #if defined(DUK_USE_REFERENCE_COUNTING)
49990 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always handled to completion inline in DECREF. */
49991 #endif
49992 	/* XXX: Assertions for finalize_list? */
49993 }
49994 
49995 DUK_LOCAL void duk__assert_validity_cb1(duk_heap *heap, duk_heaphdr *h) {
49996 	DUK_UNREF(heap);
49997 	DUK_ASSERT(DUK_HEAPHDR_IS_OBJECT(h) || DUK_HEAPHDR_IS_BUFFER(h));
49998 	duk_heaphdr_assert_valid_subclassed(h);
49999 }
50000 DUK_LOCAL void duk__assert_validity_cb2(duk_heap *heap, duk_hstring *h) {
50001 	DUK_UNREF(heap);
50002 	DUK_ASSERT(DUK_HEAPHDR_IS_STRING((duk_heaphdr *) h));
50003 	duk_heaphdr_assert_valid_subclassed((duk_heaphdr *) h);
50004 }
50005 DUK_LOCAL void duk__assert_validity(duk_heap *heap) {
50006 	duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_validity_cb1);
50007 #if defined(DUK_USE_FINALIZER_SUPPORT)
50008 	duk__assert_walk_list(heap, heap->finalize_list, duk__assert_validity_cb1);
50009 #endif
50010 #if defined(DUK_USE_REFERENCE_COUNTING)
50011 	duk__assert_walk_list(heap, heap->refzero_list, duk__assert_validity_cb1);
50012 #endif
50013 	duk__assert_walk_strtable(heap, duk__assert_validity_cb2);
50014 }
50015 
50016 #if defined(DUK_USE_REFERENCE_COUNTING)
50017 DUK_LOCAL void duk__assert_valid_refcounts_cb(duk_heap *heap, duk_heaphdr *h) {
50018 	/* Cannot really assert much w.r.t. refcounts now. */
50019 
50020 	DUK_UNREF(heap);
50021 	if (DUK_HEAPHDR_GET_REFCOUNT(h) == 0 &&
50022 	    DUK_HEAPHDR_HAS_FINALIZED(h)) {
50023 		/* An object may be in heap_allocated list with a zero
50024 		 * refcount if it has just been finalized and is waiting
50025 		 * to be collected by the next cycle.
50026 		 * (This doesn't currently happen however.)
50027 		 */
50028 	} else if (DUK_HEAPHDR_GET_REFCOUNT(h) == 0) {
50029 		/* An object may be in heap_allocated list with a zero
50030 		 * refcount also if it is a temporary object created
50031 		 * during debugger paused state.  It will get collected
50032 		 * by mark-and-sweep based on its reachability status
50033 		 * (presumably not reachable because refcount is 0).
50034 		 */
50035 	}
50036 	DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);  /* Unsigned. */
50037 }
50038 DUK_LOCAL void duk__assert_valid_refcounts(duk_heap *heap) {
50039 	duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_valid_refcounts_cb);
50040 }
50041 
50042 DUK_LOCAL void duk__clear_assert_refcounts_cb1(duk_heap *heap, duk_heaphdr *h) {
50043 	DUK_UNREF(heap);
50044 	h->h_assert_refcount = 0;
50045 }
50046 DUK_LOCAL void duk__clear_assert_refcounts_cb2(duk_heap *heap, duk_hstring *h) {
50047 	DUK_UNREF(heap);
50048 	((duk_heaphdr *) h)->h_assert_refcount = 0;
50049 }
50050 DUK_LOCAL void duk__clear_assert_refcounts(duk_heap *heap) {
50051 	duk__assert_walk_list(heap, heap->heap_allocated, duk__clear_assert_refcounts_cb1);
50052 #if defined(DUK_USE_FINALIZER_SUPPORT)
50053 	duk__assert_walk_list(heap, heap->finalize_list, duk__clear_assert_refcounts_cb1);
50054 #endif
50055 #if defined(DUK_USE_REFERENCE_COUNTING)
50056 	duk__assert_walk_list(heap, heap->refzero_list, duk__clear_assert_refcounts_cb1);
50057 #endif
50058 	duk__assert_walk_strtable(heap, duk__clear_assert_refcounts_cb2);
50059 }
50060 
50061 DUK_LOCAL void duk__check_refcount_heaphdr(duk_heaphdr *hdr) {
50062 	duk_bool_t count_ok;
50063 	duk_size_t expect_refc;
50064 
50065 	/* The refcount check only makes sense for reachable objects on
50066 	 * heap_allocated or string table, after the sweep phase.  Prior to
50067 	 * sweep phase refcounts will include references that are not visible
50068 	 * via reachability roots.
50069 	 *
50070 	 * Because we're called after the sweep phase, all heap objects on
50071 	 * heap_allocated are reachable.  REACHABLE flags have already been
50072 	 * cleared so we can't check them.
50073 	 */
50074 
50075 	/* ROM objects have intentionally incorrect refcount (1), but we won't
50076 	 * check them.
50077 	 */
50078 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr));
50079 
50080 	expect_refc = hdr->h_assert_refcount;
50081 	if (DUK_HEAPHDR_IS_STRING(hdr) && DUK_HSTRING_HAS_PINNED_LITERAL((duk_hstring *) hdr)) {
50082 		expect_refc++;
50083 	}
50084 	count_ok = ((duk_size_t) DUK_HEAPHDR_GET_REFCOUNT(hdr) == expect_refc);
50085 	if (!count_ok) {
50086 		DUK_D(DUK_DPRINT("refcount mismatch for: %p: header=%ld counted=%ld --> %!iO",
50087 		                 (void *) hdr, (long) DUK_HEAPHDR_GET_REFCOUNT(hdr),
50088 		                 (long) hdr->h_assert_refcount, hdr));
50089 		DUK_ASSERT(0);
50090 	}
50091 }
50092 
50093 DUK_LOCAL void duk__check_assert_refcounts_cb1(duk_heap *heap, duk_heaphdr *h) {
50094 	DUK_UNREF(heap);
50095 	duk__check_refcount_heaphdr(h);
50096 }
50097 DUK_LOCAL void duk__check_assert_refcounts_cb2(duk_heap *heap, duk_hstring *h) {
50098 	DUK_UNREF(heap);
50099 	duk__check_refcount_heaphdr((duk_heaphdr *) h);
50100 }
50101 DUK_LOCAL void duk__check_assert_refcounts(duk_heap *heap) {
50102 	duk__assert_walk_list(heap, heap->heap_allocated, duk__check_assert_refcounts_cb1);
50103 #if defined(DUK_USE_FINALIZER_SUPPORT)
50104 	duk__assert_walk_list(heap, heap->finalize_list, duk__check_assert_refcounts_cb1);
50105 #endif
50106 	/* XXX: Assert anything for refzero_list? */
50107 	duk__assert_walk_strtable(heap, duk__check_assert_refcounts_cb2);
50108 }
50109 #endif  /* DUK_USE_REFERENCE_COUNTING */
50110 
50111 #if defined(DUK_USE_LITCACHE_SIZE)
50112 DUK_LOCAL void duk__assert_litcache_nulls(duk_heap *heap) {
50113 	duk_uint_t i;
50114 	duk_litcache_entry *e;
50115 
50116 	e = heap->litcache;
50117 	for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
50118 		/* Entry addresses were NULLed before mark-and-sweep, check
50119 		 * that they're still NULL afterwards to ensure no pointers
50120 		 * were recorded through any side effects.
50121 		 */
50122 		DUK_ASSERT(e->addr == NULL);
50123 	}
50124 }
50125 #endif  /* DUK_USE_LITCACHE_SIZE */
50126 #endif  /* DUK_USE_ASSERTIONS */
50127 
50128 /*
50129  *  Stats dump.
50130  */
50131 
50132 #if defined(DUK_USE_DEBUG)
50133 DUK_LOCAL void duk__dump_stats(duk_heap *heap) {
50134 	DUK_D(DUK_DPRINT("stats executor: opcodes=%ld, interrupt=%ld, throw=%ld",
50135 	                 (long) heap->stats_exec_opcodes, (long) heap->stats_exec_interrupt,
50136 	                 (long) heap->stats_exec_throw));
50137 	DUK_D(DUK_DPRINT("stats call: all=%ld, tailcall=%ld, ecmatoecma=%ld",
50138 	                 (long) heap->stats_call_all, (long) heap->stats_call_tailcall,
50139 	                 (long) heap->stats_call_ecmatoecma));
50140 	DUK_D(DUK_DPRINT("stats safecall: all=%ld, nothrow=%ld, throw=%ld",
50141 	                 (long) heap->stats_safecall_all, (long) heap->stats_safecall_nothrow,
50142 	                 (long) heap->stats_safecall_throw));
50143 	DUK_D(DUK_DPRINT("stats mark-and-sweep: try_count=%ld, skip_count=%ld, emergency_count=%ld",
50144 	                 (long) heap->stats_ms_try_count, (long) heap->stats_ms_skip_count,
50145 	                 (long) heap->stats_ms_emergency_count));
50146 	DUK_D(DUK_DPRINT("stats stringtable: intern_hit=%ld, intern_miss=%ld, "
50147 	                 "resize_check=%ld, resize_grow=%ld, resize_shrink=%ld, "
50148 	                 "litcache_hit=%ld, litcache_miss=%ld, litcache_pin=%ld",
50149 	                 (long) heap->stats_strtab_intern_hit, (long) heap->stats_strtab_intern_miss,
50150 	                 (long) heap->stats_strtab_resize_check, (long) heap->stats_strtab_resize_grow,
50151 	                 (long) heap->stats_strtab_resize_shrink, (long) heap->stats_strtab_litcache_hit,
50152 	                 (long) heap->stats_strtab_litcache_miss, (long) heap->stats_strtab_litcache_pin));
50153 	DUK_D(DUK_DPRINT("stats object: realloc_props=%ld, abandon_array=%ld",
50154 	                 (long) heap->stats_object_realloc_props, (long) heap->stats_object_abandon_array));
50155 	DUK_D(DUK_DPRINT("stats getownpropdesc: count=%ld, hit=%ld, miss=%ld",
50156 	                 (long) heap->stats_getownpropdesc_count, (long) heap->stats_getownpropdesc_hit,
50157 	                 (long) heap->stats_getownpropdesc_miss));
50158 	DUK_D(DUK_DPRINT("stats getpropdesc: count=%ld, hit=%ld, miss=%ld",
50159 	                 (long) heap->stats_getpropdesc_count, (long) heap->stats_getpropdesc_hit,
50160 	                 (long) heap->stats_getpropdesc_miss));
50161 	DUK_D(DUK_DPRINT("stats getprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, "
50162 	                 "bufferidx=%ld, bufferlen=%ld, stringidx=%ld, stringlen=%ld, "
50163 	                 "proxy=%ld, arguments=%ld",
50164 	                 (long) heap->stats_getprop_all, (long) heap->stats_getprop_arrayidx,
50165 	                 (long) heap->stats_getprop_bufobjidx, (long) heap->stats_getprop_bufferidx,
50166 	                 (long) heap->stats_getprop_bufferlen, (long) heap->stats_getprop_stringidx,
50167 	                 (long) heap->stats_getprop_stringlen, (long) heap->stats_getprop_proxy,
50168 	                 (long) heap->stats_getprop_arguments));
50169 	DUK_D(DUK_DPRINT("stats putprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, "
50170 	                 "bufferidx=%ld, proxy=%ld",
50171 	                 (long) heap->stats_putprop_all, (long) heap->stats_putprop_arrayidx,
50172 	                 (long) heap->stats_putprop_bufobjidx, (long) heap->stats_putprop_bufferidx,
50173 	                 (long) heap->stats_putprop_proxy));
50174 	DUK_D(DUK_DPRINT("stats getvar: all=%ld",
50175 	                 (long) heap->stats_getvar_all));
50176 	DUK_D(DUK_DPRINT("stats putvar: all=%ld",
50177 	                 (long) heap->stats_putvar_all));
50178 	DUK_D(DUK_DPRINT("stats envrec: delayedcreate=%ld, create=%ld, newenv=%ld, oldenv=%ld, pushclosure=%ld",
50179 	                 (long) heap->stats_envrec_delayedcreate,
50180 	                 (long) heap->stats_envrec_create,
50181 	                 (long) heap->stats_envrec_newenv,
50182 	                 (long) heap->stats_envrec_oldenv,
50183 	                 (long) heap->stats_envrec_pushclosure));
50184 }
50185 #endif  /* DUK_USE_DEBUG */
50186 
50187 /*
50188  *  Main mark-and-sweep function.
50189  *
50190  *  'flags' represents the features requested by the caller.  The current
50191  *  heap->ms_base_flags is ORed automatically into the flags; the base flags
50192  *  mask typically prevents certain mark-and-sweep operation to avoid trouble.
50193  */
50194 
50195 DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {
50196 	duk_size_t count_keep_obj;
50197 	duk_size_t count_keep_str;
50198 #if defined(DUK_USE_VOLUNTARY_GC)
50199 	duk_size_t tmp;
50200 #endif
50201 
50202 	DUK_STATS_INC(heap, stats_ms_try_count);
50203 #if defined(DUK_USE_DEBUG)
50204 	if (flags & DUK_MS_FLAG_EMERGENCY) {
50205 		DUK_STATS_INC(heap, stats_ms_emergency_count);
50206 	}
50207 #endif
50208 
50209 	/* If debugger is paused, garbage collection is disabled by default.
50210 	 * This is achieved by bumping ms_prevent_count when becoming paused.
50211 	 */
50212 	DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) || heap->ms_prevent_count > 0);
50213 
50214 	/* Prevention/recursion check as soon as possible because we may
50215 	 * be called a number of times when voluntary mark-and-sweep is
50216 	 * pending.
50217 	 */
50218 	if (heap->ms_prevent_count != 0) {
50219 		DUK_DD(DUK_DDPRINT("reject recursive mark-and-sweep"));
50220 		DUK_STATS_INC(heap, stats_ms_skip_count);
50221 		return;
50222 	}
50223 	DUK_ASSERT(heap->ms_running == 0);  /* ms_prevent_count is bumped when ms_running is set */
50224 
50225 	/* Heap_thread is used during mark-and-sweep for refcount finalization
50226 	 * (it's also used for finalizer execution once mark-and-sweep is
50227 	 * complete).  Heap allocation code ensures heap_thread is set and
50228 	 * properly initialized before setting ms_prevent_count to 0.
50229 	 */
50230 	DUK_ASSERT(heap->heap_thread != NULL);
50231 	DUK_ASSERT(heap->heap_thread->valstack != NULL);
50232 
50233 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) starting, requested flags: 0x%08lx, effective flags: 0x%08lx",
50234 	                 (unsigned long) flags, (unsigned long) (flags | heap->ms_base_flags)));
50235 
50236 	flags |= heap->ms_base_flags;
50237 #if defined(DUK_USE_FINALIZER_SUPPORT)
50238 	if (heap->finalize_list != NULL) {
50239 		flags |= DUK_MS_FLAG_POSTPONE_RESCUE;
50240 	}
50241 #endif
50242 
50243 	/*
50244 	 *  Assertions before
50245 	 */
50246 
50247 #if defined(DUK_USE_ASSERTIONS)
50248 	DUK_ASSERT(heap->ms_prevent_count == 0);
50249 	DUK_ASSERT(heap->ms_running == 0);
50250 	DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(heap));
50251 	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
50252 	DUK_ASSERT(heap->ms_recursion_depth == 0);
50253 	duk__assert_heaphdr_flags(heap);
50254 	duk__assert_validity(heap);
50255 #if defined(DUK_USE_REFERENCE_COUNTING)
50256 	/* Note: heap->refzero_free_running may be true; a refcount
50257 	 * finalizer may trigger a mark-and-sweep.
50258 	 */
50259 	duk__assert_valid_refcounts(heap);
50260 #endif  /* DUK_USE_REFERENCE_COUNTING */
50261 #endif  /* DUK_USE_ASSERTIONS */
50262 
50263 	/*
50264 	 *  Begin
50265 	 */
50266 
50267 	DUK_ASSERT(heap->ms_prevent_count == 0);
50268 	DUK_ASSERT(heap->ms_running == 0);
50269 	heap->ms_prevent_count = 1;
50270 	heap->ms_running = 1;
50271 
50272 	/*
50273 	 *  Free activation/catcher freelists on every mark-and-sweep for now.
50274 	 *  This is an initial rough draft; ideally we'd keep count of the
50275 	 *  freelist size and free only excess entries.
50276 	 */
50277 
50278 	DUK_D(DUK_DPRINT("freeing temporary freelists"));
50279 	duk_heap_free_freelists(heap);
50280 
50281 	/*
50282 	 *  Mark roots, hoping that recursion limit is not normally hit.
50283 	 *  If recursion limit is hit, run additional reachability rounds
50284 	 *  starting from "temproots" until marking is complete.
50285 	 *
50286 	 *  Marking happens in two phases: first we mark actual reachability
50287 	 *  roots (and run "temproots" to complete the process).  Then we
50288 	 *  check which objects are unreachable and are finalizable; such
50289 	 *  objects are marked as FINALIZABLE and marked as reachability
50290 	 *  (and "temproots" is run again to complete the process).
50291 	 *
50292 	 *  The heap finalize_list must also be marked as a reachability root.
50293 	 *  There may be objects on the list from a previous round if the
50294 	 *  previous run had finalizer skip flag.
50295 	 */
50296 
50297 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
50298 	duk__clear_assert_refcounts(heap);
50299 #endif
50300 #if defined(DUK_USE_LITCACHE_SIZE)
50301 	duk__wipe_litcache(heap);
50302 #endif
50303 	duk__mark_roots_heap(heap);               /* Mark main reachability roots. */
50304 #if defined(DUK_USE_REFERENCE_COUNTING)
50305 	DUK_ASSERT(heap->refzero_list == NULL);   /* Always handled to completion inline in DECREF. */
50306 #endif
50307 	duk__mark_temproots_by_heap_scan(heap);   /* Temproots. */
50308 
50309 #if defined(DUK_USE_FINALIZER_SUPPORT)
50310 	duk__mark_finalizable(heap);              /* Mark finalizable as reachability roots. */
50311 	duk__mark_finalize_list(heap);            /* Mark finalizer work list as reachability roots. */
50312 #endif
50313 	duk__mark_temproots_by_heap_scan(heap);   /* Temproots. */
50314 
50315 	/*
50316 	 *  Sweep garbage and remove marking flags, and move objects with
50317 	 *  finalizers to the finalizer work list.
50318 	 *
50319 	 *  Objects to be swept need to get their refcounts finalized before
50320 	 *  they are swept.  In other words, their target object refcounts
50321 	 *  need to be decreased.  This has to be done before freeing any
50322 	 *  objects to avoid decref'ing dangling pointers (which may happen
50323 	 *  even without bugs, e.g. with reference loops)
50324 	 *
50325 	 *  Because strings don't point to other heap objects, similar
50326 	 *  finalization is not necessary for strings.
50327 	 */
50328 
50329 	/* XXX: more emergency behavior, e.g. find smaller hash sizes etc */
50330 
50331 #if defined(DUK_USE_REFERENCE_COUNTING)
50332 	duk__finalize_refcounts(heap);
50333 #endif
50334 	duk__sweep_heap(heap, flags, &count_keep_obj);
50335 	duk__sweep_stringtable(heap, &count_keep_str);
50336 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
50337 	duk__check_assert_refcounts(heap);
50338 #endif
50339 #if defined(DUK_USE_REFERENCE_COUNTING)
50340 	DUK_ASSERT(heap->refzero_list == NULL);   /* Always handled to completion inline in DECREF. */
50341 #endif
50342 #if defined(DUK_USE_FINALIZER_SUPPORT)
50343 	duk__clear_finalize_list_flags(heap);
50344 #endif
50345 
50346 	/*
50347 	 *  Object compaction (emergency only).
50348 	 *
50349 	 *  Object compaction is a separate step after sweeping, as there is
50350 	 *  more free memory for it to work with.  Also, currently compaction
50351 	 *  may insert new objects into the heap allocated list and the string
50352 	 *  table which we don't want to do during a sweep (the reachability
50353 	 *  flags of such objects would be incorrect).  The objects inserted
50354 	 *  are currently:
50355 	 *
50356 	 *    - a temporary duk_hbuffer for a new properties allocation
50357 	 *    - if array part is abandoned, string keys are interned
50358 	 *
50359 	 *  The object insertions go to the front of the list, so they do not
50360 	 *  cause an infinite loop (they are not compacted).
50361 	 *
50362 	 *  At present compaction is not allowed when mark-and-sweep runs
50363 	 *  during error handling because it involves a duk_safe_call()
50364 	 *  interfering with error state.
50365 	 */
50366 
50367 	if ((flags & DUK_MS_FLAG_EMERGENCY) &&
50368 	    !(flags & DUK_MS_FLAG_NO_OBJECT_COMPACTION)) {
50369 		if (heap->lj.type != DUK_LJ_TYPE_UNKNOWN) {
50370 			DUK_D(DUK_DPRINT("lj.type (%ld) not DUK_LJ_TYPE_UNKNOWN, skip object compaction", (long) heap->lj.type));
50371 		} else {
50372 			DUK_D(DUK_DPRINT("object compaction"));
50373 			duk__compact_objects(heap);
50374 		}
50375 	}
50376 
50377 	/*
50378 	 *  String table resize check.
50379 	 *
50380 	 *  This is mainly useful in emergency GC: if the string table load
50381 	 *  factor is really low for some reason, we can shrink the string
50382 	 *  table to a smaller size and free some memory in the process.
50383 	 *  Only execute in emergency GC.  String table has internal flags
50384 	 *  to protect against recursive resizing if this mark-and-sweep pass
50385 	 *  was triggered by a string table resize.
50386 	 */
50387 
50388 	if (flags & DUK_MS_FLAG_EMERGENCY) {
50389 		DUK_D(DUK_DPRINT("stringtable resize check in emergency gc"));
50390 		duk_heap_strtable_force_resize(heap);
50391 	}
50392 
50393 	/*
50394 	 *  Finish
50395 	 */
50396 
50397 	DUK_ASSERT(heap->ms_prevent_count == 1);
50398 	DUK_ASSERT(heap->ms_running == 1);
50399 	heap->ms_prevent_count = 0;
50400 	heap->ms_running = 0;
50401 
50402 	/*
50403 	 *  Assertions after
50404 	 */
50405 
50406 #if defined(DUK_USE_ASSERTIONS)
50407 	DUK_ASSERT(heap->ms_prevent_count == 0);
50408 	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
50409 	DUK_ASSERT(heap->ms_recursion_depth == 0);
50410 	duk__assert_heaphdr_flags(heap);
50411 	duk__assert_validity(heap);
50412 #if defined(DUK_USE_REFERENCE_COUNTING)
50413 	/* Note: heap->refzero_free_running may be true; a refcount
50414 	 * finalizer may trigger a mark-and-sweep.
50415 	 */
50416 	duk__assert_valid_refcounts(heap);
50417 #endif  /* DUK_USE_REFERENCE_COUNTING */
50418 #if defined(DUK_USE_LITCACHE_SIZE)
50419 	duk__assert_litcache_nulls(heap);
50420 #endif  /* DUK_USE_LITCACHE_SIZE */
50421 #endif  /* DUK_USE_ASSERTIONS */
50422 
50423 	/*
50424 	 *  Reset trigger counter
50425 	 */
50426 
50427 #if defined(DUK_USE_VOLUNTARY_GC)
50428 	tmp = (count_keep_obj + count_keep_str) / 256;
50429 	heap->ms_trigger_counter = (duk_int_t) (
50430 	    (tmp * DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT) +
50431 	    DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD);
50432 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, trigger reset to %ld",
50433 	                 (long) count_keep_obj, (long) count_keep_str, (long) heap->ms_trigger_counter));
50434 #else
50435 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, no voluntary trigger",
50436 	                 (long) count_keep_obj, (long) count_keep_str));
50437 #endif
50438 
50439 	/*
50440 	 *  Stats dump
50441 	 */
50442 
50443 #if defined(DUK_USE_DEBUG)
50444 	duk__dump_stats(heap);
50445 #endif
50446 
50447 	/*
50448 	 *  Finalize objects in the finalization work list.  Finalized
50449 	 *  objects are queued back to heap_allocated with FINALIZED set.
50450 	 *
50451 	 *  Since finalizers may cause arbitrary side effects, they are
50452 	 *  prevented e.g. during string table and object property allocation
50453 	 *  resizing using heap->pf_prevent_count.  In this case the objects
50454 	 *  remain in the finalization work list after mark-and-sweep exits
50455 	 *  and they may be finalized on the next pass or any DECREF checking
50456 	 *  for finalize_list.
50457 	 *
50458 	 *  As of Duktape 2.1 finalization happens outside mark-and-sweep
50459 	 *  protection.  Mark-and-sweep is allowed while the finalize_list
50460 	 *  is being processed, but no rescue decisions are done while the
50461 	 *  process is on-going.  This avoids incorrect rescue decisions
50462 	 *  if an object is considered reachable (and thus rescued) because
50463 	 *  of a reference via finalize_list (which is considered a reachability
50464 	 *  root).  When finalize_list is being processed, reachable objects
50465 	 *  with FINALIZED set will just keep their FINALIZED flag for later
50466 	 *  mark-and-sweep processing.
50467 	 *
50468 	 *  This could also be handled (a bit better) by having a more refined
50469 	 *  notion of reachability for rescue/free decisions.
50470 	 *
50471 	 *  XXX: avoid finalizer execution when doing emergency GC?
50472 	 */
50473 
50474 #if defined(DUK_USE_FINALIZER_SUPPORT)
50475 	/* Attempt to process finalize_list, pf_prevent_count check
50476 	 * is inside the target.
50477 	 */
50478 	duk_heap_process_finalize_list(heap);
50479 #endif  /* DUK_USE_FINALIZER_SUPPORT */
50480 }
50481 /*
50482  *  Memory allocation handling.
50483  */
50484 
50485 /* #include duk_internal.h -> already included */
50486 
50487 /*
50488  *  Voluntary GC check
50489  */
50490 
50491 #if defined(DUK_USE_VOLUNTARY_GC)
50492 DUK_LOCAL DUK_INLINE void duk__check_voluntary_gc(duk_heap *heap) {
50493 	if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
50494 #if defined(DUK_USE_DEBUG)
50495 		if (heap->ms_prevent_count == 0) {
50496 			DUK_D(DUK_DPRINT("triggering voluntary mark-and-sweep"));
50497 		} else {
50498 			DUK_DD(DUK_DDPRINT("gc blocked -> skip voluntary mark-and-sweep now"));
50499 		}
50500 #endif
50501 
50502 		/* Prevention checks in the call target handle cases where
50503 		 * voluntary GC is not allowed.  The voluntary GC trigger
50504 		 * counter is only rewritten if mark-and-sweep actually runs.
50505 		 */
50506 		duk_heap_mark_and_sweep(heap, DUK_MS_FLAG_VOLUNTARY /*flags*/);
50507 	}
50508 }
50509 #define DUK__VOLUNTARY_PERIODIC_GC(heap)  do { duk__check_voluntary_gc((heap)); } while (0)
50510 #else
50511 #define DUK__VOLUNTARY_PERIODIC_GC(heap)  /* no voluntary gc */
50512 #endif  /* DUK_USE_VOLUNTARY_GC */
50513 
50514 /*
50515  *  Allocate memory with garbage collection
50516  */
50517 
50518 DUK_INTERNAL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
50519 	void *res;
50520 	duk_small_int_t i;
50521 
50522 	DUK_ASSERT(heap != NULL);
50523 	DUK_ASSERT_DISABLE(size >= 0);
50524 
50525 	/*
50526 	 *  Voluntary periodic GC (if enabled)
50527 	 */
50528 
50529 	DUK__VOLUNTARY_PERIODIC_GC(heap);
50530 
50531 	/*
50532 	 *  First attempt
50533 	 */
50534 
50535 #if defined(DUK_USE_GC_TORTURE)
50536 	/* Simulate alloc failure on every alloc, except when mark-and-sweep
50537 	 * is running.
50538 	 */
50539 	if (heap->ms_prevent_count == 0) {
50540 		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first alloc attempt fails"));
50541 		res = NULL;
50542 		DUK_UNREF(res);
50543 		goto skip_attempt;
50544 	}
50545 #endif
50546 	res = heap->alloc_func(heap->heap_udata, size);
50547 	if (DUK_LIKELY(res || size == 0)) {
50548 		/* For zero size allocations NULL is allowed. */
50549 		return res;
50550 	}
50551 #if defined(DUK_USE_GC_TORTURE)
50552  skip_attempt:
50553 #endif
50554 
50555 	DUK_D(DUK_DPRINT("first alloc attempt failed, attempt to gc and retry"));
50556 
50557 #if 0
50558 	/*
50559 	 *  Avoid a GC if GC is already running.  This can happen at a late
50560 	 *  stage in a GC when we try to e.g. resize the stringtable
50561 	 *  or compact objects.
50562 	 *
50563 	 *  NOTE: explicit handling isn't actually be needed: if the GC is
50564 	 *  not allowed, duk_heap_mark_and_sweep() will reject it for every
50565 	 *  attempt in the loop below, resulting in a NULL same as here.
50566 	 */
50567 
50568 	if (heap->ms_prevent_count != 0) {
50569 		DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed, gc in progress (gc skipped), alloc size %ld", (long) size));
50570 		return NULL;
50571 	}
50572 #endif
50573 
50574 	/*
50575 	 *  Retry with several GC attempts.  Initial attempts are made without
50576 	 *  emergency mode; later attempts use emergency mode which minimizes
50577 	 *  memory allocations forcibly.
50578 	 */
50579 
50580 	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
50581 		duk_small_uint_t flags;
50582 
50583 		flags = 0;
50584 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
50585 			flags |= DUK_MS_FLAG_EMERGENCY;
50586 		}
50587 
50588 		duk_heap_mark_and_sweep(heap, flags);
50589 
50590 		res = heap->alloc_func(heap->heap_udata, size);
50591 		if (res) {
50592 			DUK_D(DUK_DPRINT("duk_heap_mem_alloc() succeeded after gc (pass %ld), alloc size %ld",
50593 			                 (long) (i + 1), (long) size));
50594 			return res;
50595 		}
50596 	}
50597 
50598 	DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed even after gc, alloc size %ld", (long) size));
50599 	return NULL;
50600 }
50601 
50602 DUK_INTERNAL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size) {
50603 	void *res;
50604 
50605 	DUK_ASSERT(heap != NULL);
50606 	DUK_ASSERT_DISABLE(size >= 0);
50607 
50608 	res = DUK_ALLOC(heap, size);
50609 	if (DUK_LIKELY(res != NULL)) {
50610 		duk_memzero(res, size);
50611 	}
50612 	return res;
50613 }
50614 
50615 DUK_INTERNAL void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size) {
50616 	void *res;
50617 
50618 	DUK_ASSERT(thr != NULL);
50619 	res = duk_heap_mem_alloc(thr->heap, size);
50620 	if (DUK_LIKELY(res != NULL || size == 0)) {
50621 		return res;
50622 	}
50623 	DUK_ERROR_ALLOC_FAILED(thr);
50624 	DUK_WO_NORETURN(return NULL;);
50625 }
50626 
50627 DUK_INTERNAL void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size) {
50628 	void *res;
50629 
50630 	DUK_ASSERT(thr != NULL);
50631 	res = duk_heap_mem_alloc_zeroed(thr->heap, size);
50632 	if (DUK_LIKELY(res != NULL || size == 0)) {
50633 		return res;
50634 	}
50635 	DUK_ERROR_ALLOC_FAILED(thr);
50636 	DUK_WO_NORETURN(return NULL;);
50637 }
50638 
50639 /*
50640  *  Reallocate memory with garbage collection
50641  */
50642 
50643 DUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
50644 	void *res;
50645 	duk_small_int_t i;
50646 
50647 	DUK_ASSERT(heap != NULL);
50648 	/* ptr may be NULL */
50649 	DUK_ASSERT_DISABLE(newsize >= 0);
50650 
50651 	/*
50652 	 *  Voluntary periodic GC (if enabled)
50653 	 */
50654 
50655 	DUK__VOLUNTARY_PERIODIC_GC(heap);
50656 
50657 	/*
50658 	 *  First attempt
50659 	 */
50660 
50661 #if defined(DUK_USE_GC_TORTURE)
50662 	/* Simulate alloc failure on every realloc, except when mark-and-sweep
50663 	 * is running.
50664 	 */
50665 	if (heap->ms_prevent_count == 0) {
50666 		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first realloc attempt fails"));
50667 		res = NULL;
50668 		DUK_UNREF(res);
50669 		goto skip_attempt;
50670 	}
50671 #endif
50672 	res = heap->realloc_func(heap->heap_udata, ptr, newsize);
50673 	if (DUK_LIKELY(res || newsize == 0)) {
50674 		/* For zero size allocations NULL is allowed. */
50675 		return res;
50676 	}
50677 #if defined(DUK_USE_GC_TORTURE)
50678  skip_attempt:
50679 #endif
50680 
50681 	DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));
50682 
50683 #if 0
50684 	/*
50685 	 *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().
50686 	 */
50687 
50688 	if (heap->ms_prevent_count != 0) {
50689 		DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
50690 		return NULL;
50691 	}
50692 #endif
50693 
50694 	/*
50695 	 *  Retry with several GC attempts.  Initial attempts are made without
50696 	 *  emergency mode; later attempts use emergency mode which minimizes
50697 	 *  memory allocations forcibly.
50698 	 */
50699 
50700 	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
50701 		duk_small_uint_t flags;
50702 
50703 		flags = 0;
50704 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
50705 			flags |= DUK_MS_FLAG_EMERGENCY;
50706 		}
50707 
50708 		duk_heap_mark_and_sweep(heap, flags);
50709 
50710 		res = heap->realloc_func(heap->heap_udata, ptr, newsize);
50711 		if (res || newsize == 0) {
50712 			DUK_D(DUK_DPRINT("duk_heap_mem_realloc() succeeded after gc (pass %ld), alloc size %ld",
50713 			                 (long) (i + 1), (long) newsize));
50714 			return res;
50715 		}
50716 	}
50717 
50718 	DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed even after gc, alloc size %ld", (long) newsize));
50719 	return NULL;
50720 }
50721 
50722 /*
50723  *  Reallocate memory with garbage collection, using a callback to provide
50724  *  the current allocated pointer.  This variant is used when a mark-and-sweep
50725  *  (e.g. finalizers) might change the original pointer.
50726  */
50727 
50728 DUK_INTERNAL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
50729 	void *res;
50730 	duk_small_int_t i;
50731 
50732 	DUK_ASSERT(heap != NULL);
50733 	DUK_ASSERT_DISABLE(newsize >= 0);
50734 
50735 	/*
50736 	 *  Voluntary periodic GC (if enabled)
50737 	 */
50738 
50739 	DUK__VOLUNTARY_PERIODIC_GC(heap);
50740 
50741 	/*
50742 	 *  First attempt
50743 	 */
50744 
50745 #if defined(DUK_USE_GC_TORTURE)
50746 	/* Simulate alloc failure on every realloc, except when mark-and-sweep
50747 	 * is running.
50748 	 */
50749 	if (heap->ms_prevent_count == 0) {
50750 		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first indirect realloc attempt fails"));
50751 		res = NULL;
50752 		DUK_UNREF(res);
50753 		goto skip_attempt;
50754 	}
50755 #endif
50756 	res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
50757 	if (DUK_LIKELY(res || newsize == 0)) {
50758 		/* For zero size allocations NULL is allowed. */
50759 		return res;
50760 	}
50761 #if defined(DUK_USE_GC_TORTURE)
50762  skip_attempt:
50763 #endif
50764 
50765 	DUK_D(DUK_DPRINT("first indirect realloc attempt failed, attempt to gc and retry"));
50766 
50767 #if 0
50768 	/*
50769 	 *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().
50770 	 */
50771 
50772 	if (heap->ms_prevent_count != 0) {
50773 		DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
50774 		return NULL;
50775 	}
50776 #endif
50777 
50778 	/*
50779 	 *  Retry with several GC attempts.  Initial attempts are made without
50780 	 *  emergency mode; later attempts use emergency mode which minimizes
50781 	 *  memory allocations forcibly.
50782 	 */
50783 
50784 	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
50785 		duk_small_uint_t flags;
50786 
50787 #if defined(DUK_USE_DEBUG)
50788 		void *ptr_pre;
50789 		void *ptr_post;
50790 #endif
50791 
50792 #if defined(DUK_USE_DEBUG)
50793 		ptr_pre = cb(heap, ud);
50794 #endif
50795 		flags = 0;
50796 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
50797 			flags |= DUK_MS_FLAG_EMERGENCY;
50798 		}
50799 
50800 		duk_heap_mark_and_sweep(heap, flags);
50801 #if defined(DUK_USE_DEBUG)
50802 		ptr_post = cb(heap, ud);
50803 		if (ptr_pre != ptr_post) {
50804 			DUK_DD(DUK_DDPRINT("realloc base pointer changed by mark-and-sweep: %p -> %p",
50805 			                   (void *) ptr_pre, (void *) ptr_post));
50806 		}
50807 #endif
50808 
50809 		/* Note: key issue here is to re-lookup the base pointer on every attempt.
50810 		 * The pointer being reallocated may change after every mark-and-sweep.
50811 		 */
50812 
50813 		res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
50814 		if (res || newsize == 0) {
50815 			DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() succeeded after gc (pass %ld), alloc size %ld",
50816 			                 (long) (i + 1), (long) newsize));
50817 			return res;
50818 		}
50819 	}
50820 
50821 	DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed even after gc, alloc size %ld", (long) newsize));
50822 	return NULL;
50823 }
50824 
50825 /*
50826  *  Free memory
50827  */
50828 
50829 DUK_INTERNAL void duk_heap_mem_free(duk_heap *heap, void *ptr) {
50830 	DUK_ASSERT(heap != NULL);
50831 	/* ptr may be NULL */
50832 
50833 	/* Must behave like a no-op with NULL and any pointer returned from
50834 	 * malloc/realloc with zero size.
50835 	 */
50836 	heap->free_func(heap->heap_udata, ptr);
50837 
50838 	/* Never perform a GC (even voluntary) in a memory free, otherwise
50839 	 * all call sites doing frees would need to deal with the side effects.
50840 	 * No need to update voluntary GC counter either.
50841 	 */
50842 }
50843 
50844 /* automatic undefs */
50845 #undef DUK__VOLUNTARY_PERIODIC_GC
50846 /*
50847  *  Support functions for duk_heap.
50848  */
50849 
50850 /* #include duk_internal.h -> already included */
50851 
50852 DUK_INTERNAL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
50853 	duk_heaphdr *root;
50854 
50855 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);
50856 
50857 	root = heap->heap_allocated;
50858 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
50859 	if (root != NULL) {
50860 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
50861 		DUK_HEAPHDR_SET_PREV(heap, root, hdr);
50862 	}
50863 	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
50864 #endif
50865 	DUK_HEAPHDR_SET_NEXT(heap, hdr, root);
50866 	DUK_HEAPHDR_ASSERT_LINKS(heap, hdr);
50867 	DUK_HEAPHDR_ASSERT_LINKS(heap, root);
50868 	heap->heap_allocated = hdr;
50869 }
50870 
50871 #if defined(DUK_USE_REFERENCE_COUNTING)
50872 DUK_INTERNAL void duk_heap_remove_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
50873 	duk_heaphdr *prev;
50874 	duk_heaphdr *next;
50875 
50876 	/* Strings are in string table. */
50877 	DUK_ASSERT(hdr != NULL);
50878 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);
50879 
50880 	/* Target 'hdr' must be in heap_allocated (not e.g. finalize_list).
50881 	 * If not, heap lists will become corrupted so assert early for it.
50882 	 */
50883 #if defined(DUK_USE_ASSERTIONS)
50884 	{
50885 		duk_heaphdr *tmp;
50886 		for (tmp = heap->heap_allocated; tmp != NULL; tmp = DUK_HEAPHDR_GET_NEXT(heap, tmp)) {
50887 			if (tmp == hdr) {
50888 				break;
50889 			}
50890 		}
50891 		DUK_ASSERT(tmp == hdr);
50892 	}
50893 #endif
50894 
50895 	/* Read/write only once to minimize pointer compression calls. */
50896 	prev = DUK_HEAPHDR_GET_PREV(heap, hdr);
50897 	next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
50898 
50899 	if (prev != NULL) {
50900 		DUK_ASSERT(heap->heap_allocated != hdr);
50901 		DUK_HEAPHDR_SET_NEXT(heap, prev, next);
50902 	} else {
50903 		DUK_ASSERT(heap->heap_allocated == hdr);
50904 		heap->heap_allocated = next;
50905 	}
50906 	if (next != NULL) {
50907 		DUK_HEAPHDR_SET_PREV(heap, next, prev);
50908 	} else {
50909 		;
50910 	}
50911 }
50912 #endif  /* DUK_USE_REFERENCE_COUNTING */
50913 
50914 #if defined(DUK_USE_FINALIZER_SUPPORT)
50915 DUK_INTERNAL void duk_heap_insert_into_finalize_list(duk_heap *heap, duk_heaphdr *hdr) {
50916 	duk_heaphdr *root;
50917 
50918 	root = heap->finalize_list;
50919 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
50920 	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
50921 	if (root != NULL) {
50922 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
50923 		DUK_HEAPHDR_SET_PREV(heap, root, hdr);
50924 	}
50925 #endif
50926 	DUK_HEAPHDR_SET_NEXT(heap, hdr, root);
50927 	DUK_HEAPHDR_ASSERT_LINKS(heap, hdr);
50928 	DUK_HEAPHDR_ASSERT_LINKS(heap, root);
50929 	heap->finalize_list = hdr;
50930 }
50931 #endif  /* DUK_USE_FINALIZER_SUPPORT */
50932 
50933 #if defined(DUK_USE_FINALIZER_SUPPORT)
50934 DUK_INTERNAL void duk_heap_remove_from_finalize_list(duk_heap *heap, duk_heaphdr *hdr) {
50935 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
50936 	duk_heaphdr *next;
50937 	duk_heaphdr *prev;
50938 
50939 	next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
50940 	prev = DUK_HEAPHDR_GET_PREV(heap, hdr);
50941 	if (next != NULL) {
50942 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, next) == hdr);
50943 		DUK_HEAPHDR_SET_PREV(heap, next, prev);
50944 	}
50945 	if (prev == NULL) {
50946 		DUK_ASSERT(hdr == heap->finalize_list);
50947 		heap->finalize_list = next;
50948 	} else {
50949 		DUK_ASSERT(hdr != heap->finalize_list);
50950 		DUK_HEAPHDR_SET_NEXT(heap, prev, next);
50951 	}
50952 #else
50953 	duk_heaphdr *next;
50954 	duk_heaphdr *curr;
50955 
50956 	/* Random removal is expensive: we need to locate the previous element
50957 	 * because we don't have a 'prev' pointer.
50958 	 */
50959 	curr = heap->finalize_list;
50960 	if (curr == hdr) {
50961 		heap->finalize_list = DUK_HEAPHDR_GET_NEXT(heap, curr);
50962 	} else {
50963 		DUK_ASSERT(hdr != heap->finalize_list);
50964 		for (;;) {
50965 			DUK_ASSERT(curr != NULL);  /* Caller responsibility. */
50966 
50967 			next = DUK_HEAPHDR_GET_NEXT(heap, curr);
50968 			if (next == hdr) {
50969 				next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
50970 				DUK_HEAPHDR_SET_NEXT(heap, curr, next);
50971 				break;
50972 			}
50973 		}
50974 	}
50975 #endif
50976 }
50977 #endif  /* DUK_USE_FINALIZER_SUPPORT */
50978 
50979 #if defined(DUK_USE_ASSERTIONS)
50980 DUK_INTERNAL duk_bool_t duk_heap_in_heap_allocated(duk_heap *heap, duk_heaphdr *ptr) {
50981 	duk_heaphdr *curr;
50982 	DUK_ASSERT(heap != NULL);
50983 
50984 	for (curr = heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
50985 		if (curr == ptr) {
50986 			return 1;
50987 		}
50988 	}
50989 	return 0;
50990 }
50991 #endif  /* DUK_USE_ASSERTIONS */
50992 
50993 #if defined(DUK_USE_INTERRUPT_COUNTER)
50994 DUK_INTERNAL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr) {
50995 	duk_hthread *curr_thr;
50996 
50997 	DUK_ASSERT(heap != NULL);
50998 
50999 	if (new_thr != NULL) {
51000 		curr_thr = heap->curr_thread;
51001 		if (curr_thr == NULL) {
51002 			/* For initial entry use default value; zero forces an
51003 			 * interrupt before executing the first insturction.
51004 			 */
51005 			DUK_DD(DUK_DDPRINT("switch thread, initial entry, init default interrupt counter"));
51006 			new_thr->interrupt_counter = 0;
51007 			new_thr->interrupt_init = 0;
51008 		} else {
51009 			/* Copy interrupt counter/init value state to new thread (if any).
51010 			 * It's OK for new_thr to be the same as curr_thr.
51011 			 */
51012 #if defined(DUK_USE_DEBUG)
51013 			if (new_thr != curr_thr) {
51014 				DUK_DD(DUK_DDPRINT("switch thread, not initial entry, copy interrupt counter"));
51015 			}
51016 #endif
51017 			new_thr->interrupt_counter = curr_thr->interrupt_counter;
51018 			new_thr->interrupt_init = curr_thr->interrupt_init;
51019 		}
51020 	} else {
51021 		DUK_DD(DUK_DDPRINT("switch thread, new thread is NULL, no interrupt counter changes"));
51022 	}
51023 
51024 	heap->curr_thread = new_thr;  /* may be NULL */
51025 }
51026 #endif  /* DUK_USE_INTERRUPT_COUNTER */
51027 
51028 #if defined(DUK_USE_ASSERTIONS)
51029 DUK_INTERNAL void duk_heap_assert_valid(duk_heap *heap) {
51030 	DUK_ASSERT(heap != NULL);
51031 }
51032 #endif
51033 /*
51034  *  Reference counting implementation.
51035  *
51036  *  INCREF/DECREF, finalization and freeing of objects whose refcount reaches
51037  *  zero (refzero).  These operations are very performance sensitive, so
51038  *  various small tricks are used in an attempt to maximize speed.
51039  */
51040 
51041 /* #include duk_internal.h -> already included */
51042 
51043 #if defined(DUK_USE_REFERENCE_COUNTING)
51044 
51045 #if !defined(DUK_USE_DOUBLE_LINKED_HEAP)
51046 #error internal error, reference counting requires a double linked heap
51047 #endif
51048 
51049 /*
51050  *  Heap object refcount finalization.
51051  *
51052  *  When an object is about to be freed, all other objects it refers to must
51053  *  be decref'd.  Refcount finalization does NOT free the object or its inner
51054  *  allocations (mark-and-sweep shares these helpers), it just manipulates
51055  *  the refcounts.
51056  *
51057  *  Note that any of the DECREFs may cause a refcount to drop to zero.  If so,
51058  *  the object won't be refzero processed inline, but will just be queued to
51059  *  refzero_list and processed by an earlier caller working on refzero_list,
51060  *  eliminating C recursion from even long refzero cascades.  If refzero
51061  *  finalization is triggered by mark-and-sweep, refzero conditions are ignored
51062  *  (objects are not even queued to refzero_list) because mark-and-sweep deals
51063  *  with them; refcounts are still updated so that they remain in sync with
51064  *  actual references.
51065  */
51066 
51067 DUK_LOCAL void duk__decref_tvals_norz(duk_hthread *thr, duk_tval *tv, duk_idx_t count) {
51068 	DUK_ASSERT(count == 0 || tv != NULL);
51069 
51070 	while (count-- > 0) {
51071 		DUK_TVAL_DECREF_NORZ(thr, tv);
51072 		tv++;
51073 	}
51074 }
51075 
51076 DUK_INTERNAL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject *h) {
51077 	duk_hthread *thr;
51078 	duk_uint_fast32_t i;
51079 	duk_uint_fast32_t n;
51080 	duk_propvalue *p_val;
51081 	duk_tval *p_tv;
51082 	duk_hstring **p_key;
51083 	duk_uint8_t *p_flag;
51084 	duk_hobject *h_proto;
51085 
51086 	DUK_ASSERT(heap != NULL);
51087 	DUK_ASSERT(heap->heap_thread != NULL);
51088 	DUK_ASSERT(h);
51089 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h) == DUK_HTYPE_OBJECT);
51090 
51091 	thr = heap->heap_thread;
51092 	DUK_ASSERT(thr != NULL);
51093 
51094 	p_key = DUK_HOBJECT_E_GET_KEY_BASE(heap, h);
51095 	p_val = DUK_HOBJECT_E_GET_VALUE_BASE(heap, h);
51096 	p_flag = DUK_HOBJECT_E_GET_FLAGS_BASE(heap, h);
51097 	n = DUK_HOBJECT_GET_ENEXT(h);
51098 	while (n-- > 0) {
51099 		duk_hstring *key;
51100 
51101 		key = p_key[n];
51102 		if (DUK_UNLIKELY(key == NULL)) {
51103 			continue;
51104 		}
51105 		DUK_HSTRING_DECREF_NORZ(thr, key);
51106 		if (DUK_UNLIKELY(p_flag[n] & DUK_PROPDESC_FLAG_ACCESSOR)) {
51107 			duk_hobject *h_getset;
51108 			h_getset = p_val[n].a.get;
51109 			DUK_ASSERT(h_getset == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_getset));
51110 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_getset);
51111 			h_getset = p_val[n].a.set;
51112 			DUK_ASSERT(h_getset == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_getset));
51113 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_getset);
51114 		} else {
51115 			duk_tval *tv_val;
51116 			tv_val = &p_val[n].v;
51117 			DUK_TVAL_DECREF_NORZ(thr, tv_val);
51118 		}
51119 	}
51120 
51121 	p_tv = DUK_HOBJECT_A_GET_BASE(heap, h);
51122 	n = DUK_HOBJECT_GET_ASIZE(h);
51123 	while (n-- > 0) {
51124 		duk_tval *tv_val;
51125 		tv_val = p_tv + n;
51126 		DUK_TVAL_DECREF_NORZ(thr, tv_val);
51127 	}
51128 
51129 	/* Hash part is a 'weak reference' and doesn't contribute to refcounts. */
51130 
51131 	h_proto = (duk_hobject *) DUK_HOBJECT_GET_PROTOTYPE(heap, h);
51132 	DUK_ASSERT(h_proto == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_proto));
51133 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_proto);
51134 
51135 	/* XXX: Object subclass tests are quite awkward at present, ideally
51136 	 * we should be able to switch-case here with a dense index (subtype
51137 	 * number or something).  For now, fast path plain objects and arrays
51138 	 * and bit test the rest individually.
51139 	 */
51140 
51141 	if (DUK_HOBJECT_HAS_FASTREFS(h)) {
51142 		/* Plain object or array, nothing more to do.  While a
51143 		 * duk_harray has additional fields, none of them need
51144 		 * DECREF updates.
51145 		 */
51146 		DUK_ASSERT(DUK_HOBJECT_ALLOWS_FASTREFS(h));
51147 		return;
51148 	}
51149 	DUK_ASSERT(DUK_HOBJECT_PROHIBITS_FASTREFS(h));
51150 
51151 	/* Slow path: special object, start bit checks from most likely. */
51152 
51153 	/* XXX: reorg, more common first */
51154 	if (DUK_HOBJECT_IS_COMPFUNC(h)) {
51155 		duk_hcompfunc *f = (duk_hcompfunc *) h;
51156 		duk_tval *tv, *tv_end;
51157 		duk_hobject **funcs, **funcs_end;
51158 
51159 		DUK_HCOMPFUNC_ASSERT_VALID(f);
51160 
51161 		if (DUK_LIKELY(DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL)) {
51162 			tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
51163 			tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);
51164 			while (tv < tv_end) {
51165 				DUK_TVAL_DECREF_NORZ(thr, tv);
51166 				tv++;
51167 			}
51168 
51169 			funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);
51170 			funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);
51171 			while (funcs < funcs_end) {
51172 				duk_hobject *h_func;
51173 				h_func = *funcs;
51174 				DUK_ASSERT(h_func != NULL);
51175 				DUK_ASSERT(DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_func));
51176 				DUK_HCOMPFUNC_DECREF_NORZ(thr, (duk_hcompfunc *) h_func);
51177 				funcs++;
51178 			}
51179 		} else {
51180 			/* May happen in some out-of-memory corner cases. */
51181 			DUK_D(DUK_DPRINT("duk_hcompfunc 'data' is NULL, skipping decref"));
51182 		}
51183 
51184 		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_heaphdr *) DUK_HCOMPFUNC_GET_LEXENV(heap, f));
51185 		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_heaphdr *) DUK_HCOMPFUNC_GET_VARENV(heap, f));
51186 		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(heap, f));
51187 	} else if (DUK_HOBJECT_IS_DECENV(h)) {
51188 		duk_hdecenv *e = (duk_hdecenv *) h;
51189 		DUK_HDECENV_ASSERT_VALID(e);
51190 		DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, e->thread);
51191 		DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, e->varmap);
51192 	} else if (DUK_HOBJECT_IS_OBJENV(h)) {
51193 		duk_hobjenv *e = (duk_hobjenv *) h;
51194 		DUK_HOBJENV_ASSERT_VALID(e);
51195 		DUK_ASSERT(e->target != NULL);  /* Required for object environments. */
51196 		DUK_HOBJECT_DECREF_NORZ(thr, e->target);
51197 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
51198 	} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
51199 		duk_hbufobj *b = (duk_hbufobj *) h;
51200 		DUK_HBUFOBJ_ASSERT_VALID(b);
51201 		DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr, (duk_hbuffer *) b->buf);
51202 		DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) b->buf_prop);
51203 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
51204 	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
51205 		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
51206 		DUK_HBOUNDFUNC_ASSERT_VALID(f);
51207 		DUK_TVAL_DECREF_NORZ(thr, &f->target);
51208 		DUK_TVAL_DECREF_NORZ(thr, &f->this_binding);
51209 		duk__decref_tvals_norz(thr, f->args, f->nargs);
51210 #if defined(DUK_USE_ES6_PROXY)
51211 	} else if (DUK_HOBJECT_IS_PROXY(h)) {
51212 		duk_hproxy *p = (duk_hproxy *) h;
51213 		DUK_HPROXY_ASSERT_VALID(p);
51214 		DUK_HOBJECT_DECREF_NORZ(thr, p->target);
51215 		DUK_HOBJECT_DECREF_NORZ(thr, p->handler);
51216 #endif  /* DUK_USE_ES6_PROXY */
51217 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
51218 		duk_hthread *t = (duk_hthread *) h;
51219 		duk_activation *act;
51220 		duk_tval *tv;
51221 
51222 		DUK_HTHREAD_ASSERT_VALID(t);
51223 
51224 		tv = t->valstack;
51225 		while (tv < t->valstack_top) {
51226 			DUK_TVAL_DECREF_NORZ(thr, tv);
51227 			tv++;
51228 		}
51229 
51230 		for (act = t->callstack_curr; act != NULL; act = act->parent) {
51231 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) DUK_ACT_GET_FUNC(act));
51232 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->var_env);
51233 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->lex_env);
51234 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
51235 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->prev_caller);
51236 #endif
51237 #if 0  /* nothing now */
51238 			for (cat = act->cat; cat != NULL; cat = cat->parent) {
51239 			}
51240 #endif
51241 		}
51242 
51243 
51244 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
51245 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) t->builtins[i]);
51246 		}
51247 
51248 		DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, (duk_hthread *) t->resumer);
51249 	} else {
51250 		/* We may come here if the object should have a FASTREFS flag
51251 		 * but it's missing for some reason.  Assert for never getting
51252 		 * here; however, other than performance, this is harmless.
51253 		 */
51254 		DUK_D(DUK_DPRINT("missing FASTREFS flag for: %!iO", h));
51255 		DUK_ASSERT(0);
51256 	}
51257 }
51258 
51259 DUK_INTERNAL void duk_heaphdr_refcount_finalize_norz(duk_heap *heap, duk_heaphdr *hdr) {
51260 	DUK_ASSERT(heap != NULL);
51261 	DUK_ASSERT(heap->heap_thread != NULL);
51262 	DUK_ASSERT(hdr != NULL);
51263 
51264 	if (DUK_HEAPHDR_IS_OBJECT(hdr)) {
51265 		duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) hdr);
51266 	}
51267 	/* DUK_HTYPE_BUFFER: nothing to finalize */
51268 	/* DUK_HTYPE_STRING: nothing to finalize */
51269 }
51270 
51271 /*
51272  *  Refzero processing for duk_hobject: queue a refzero'ed object to either
51273  *  finalize_list or refzero_list and process the relevent list(s) if
51274  *  necessary.
51275  *
51276  *  Refzero_list is single linked, with only 'prev' pointers set and valid.
51277  *  All 'next' pointers are intentionally left as garbage.  This doesn't
51278  *  matter because refzero_list is processed to completion before any other
51279  *  code (like mark-and-sweep) might walk the list.
51280  *
51281  *  In more detail:
51282  *
51283  *  - On first insert refzero_list is NULL and the new object becomes the
51284  *    first and only element on the list; duk__refcount_free_pending() is
51285  *    called and it starts processing the list from the initial element,
51286  *    i.e. the list tail.
51287  *
51288  *  - As each object is refcount finalized, new objects may be queued to
51289  *    refzero_list head.  Their 'next' pointers are left as garbage, but
51290  *    'prev' points are set correctly, with the element at refzero_list
51291  *    having a NULL 'prev' pointer.  The fact that refzero_list is non-NULL
51292  *    is used to reject (1) recursive duk__refcount_free_pending() and
51293  *    (2) finalize_list processing calls.
51294  *
51295  *  - When we're done with the current object, read its 'prev' pointer and
51296  *    free the object.  If 'prev' is NULL, we've reached head of list and are
51297  *    done: set refzero_list to NULL and process pending finalizers.  Otherwise
51298  *    continue processing the list.
51299  *
51300  *  A refzero cascade is free of side effects because it only involves
51301  *  queueing more objects and freeing memory; finalizer execution is blocked
51302  *  in the code path queueing objects to finalize_list.  As a result the
51303  *  initial refzero call (which triggers duk__refcount_free_pending()) must
51304  *  check finalize_list so that finalizers are executed snappily.
51305  *
51306  *  If finalize_list processing starts first, refzero may occur while we're
51307  *  processing finalizers.  That's fine: that particular refzero cascade is
51308  *  handled to completion without side effects.  Once the cascade is complete,
51309  *  we'll run pending finalizers but notice that we're already doing that and
51310  *  return.
51311  *
51312  *  This could be expanded to allow incremental freeing: just bail out
51313  *  early and resume at a future alloc/decref/refzero.  However, if that
51314  *  were done, the list structure would need to be kept consistent at all
51315  *  times, mark-and-sweep would need to handle refzero_list, etc.
51316  */
51317 
51318 DUK_LOCAL void duk__refcount_free_pending(duk_heap *heap) {
51319 	duk_heaphdr *curr;
51320 #if defined(DUK_USE_DEBUG)
51321 	duk_int_t count = 0;
51322 #endif
51323 
51324 	DUK_ASSERT(heap != NULL);
51325 
51326 	curr = heap->refzero_list;
51327 	DUK_ASSERT(curr != NULL);
51328 	DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, curr) == NULL);  /* We're called on initial insert only. */
51329 	/* curr->next is GARBAGE. */
51330 
51331 	do {
51332 		duk_heaphdr *prev;
51333 
51334 		DUK_DDD(DUK_DDDPRINT("refzero processing %p: %!O", (void *) curr, (duk_heaphdr *) curr));
51335 
51336 #if defined(DUK_USE_DEBUG)
51337 		count++;
51338 #endif
51339 
51340 		DUK_ASSERT(curr != NULL);
51341 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* currently, always the case */
51342 		/* FINALIZED may be set; don't care about flags here. */
51343 
51344 		/* Refcount finalize 'curr'.  Refzero_list must be non-NULL
51345 		 * here to prevent recursive entry to duk__refcount_free_pending().
51346 		 */
51347 		DUK_ASSERT(heap->refzero_list != NULL);
51348 		duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) curr);
51349 
51350 		prev = DUK_HEAPHDR_GET_PREV(heap, curr);
51351 		DUK_ASSERT((prev == NULL && heap->refzero_list == curr) || \
51352 		           (prev != NULL && heap->refzero_list != curr));
51353 		/* prev->next is intentionally not updated and is garbage. */
51354 
51355 		duk_free_hobject(heap, (duk_hobject *) curr);  /* Invalidates 'curr'. */
51356 
51357 		curr = prev;
51358 	} while (curr != NULL);
51359 
51360 	heap->refzero_list = NULL;
51361 
51362 	DUK_DD(DUK_DDPRINT("refzero processed %ld objects", (long) count));
51363 }
51364 
51365 DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hobject(duk_heap *heap, duk_hobject *obj, duk_bool_t skip_free_pending) {
51366 	duk_heaphdr *hdr;
51367 	duk_heaphdr *root;
51368 
51369 	DUK_ASSERT(heap != NULL);
51370 	DUK_ASSERT(heap->heap_thread != NULL);
51371 	DUK_ASSERT(obj != NULL);
51372 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) obj) == DUK_HTYPE_OBJECT);
51373 
51374 	hdr = (duk_heaphdr *) obj;
51375 
51376 	/* Refzero'd objects must be in heap_allocated.  They can't be in
51377 	 * finalize_list because all objects on finalize_list have an
51378 	 * artificial +1 refcount bump.
51379 	 */
51380 #if defined(DUK_USE_ASSERTIONS)
51381 	DUK_ASSERT(duk_heap_in_heap_allocated(heap, (duk_heaphdr *) obj));
51382 #endif
51383 
51384 	DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap, hdr);
51385 
51386 #if defined(DUK_USE_FINALIZER_SUPPORT)
51387 	/* This finalizer check MUST BE side effect free.  It should also be
51388 	 * as fast as possible because it's applied to every object freed.
51389 	 */
51390 	if (DUK_UNLIKELY(DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) hdr) != 0U)) {
51391 		/* Special case: FINALIZED may be set if mark-and-sweep queued
51392 		 * object for finalization, the finalizer was executed (and
51393 		 * FINALIZED set), mark-and-sweep hasn't yet processed the
51394 		 * object again, but its refcount drops to zero.  Free without
51395 		 * running the finalizer again.
51396 		 */
51397 		if (DUK_HEAPHDR_HAS_FINALIZED(hdr)) {
51398 			DUK_D(DUK_DPRINT("refzero'd object has finalizer and FINALIZED is set -> free"));
51399 		} else {
51400 			/* Set FINALIZABLE flag so that all objects on finalize_list
51401 			 * will have it set and are thus detectable based on the
51402 			 * flag alone.
51403 			 */
51404 			DUK_HEAPHDR_SET_FINALIZABLE(hdr);
51405 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));
51406 
51407 #if defined(DUK_USE_REFERENCE_COUNTING)
51408 			/* Bump refcount on finalize_list insert so that a
51409 			 * refzero can never occur when an object is waiting
51410 			 * for its finalizer call.  Refzero might otherwise
51411 			 * now happen because we allow duk_push_heapptr() for
51412 			 * objects pending finalization.
51413 			 */
51414 			DUK_HEAPHDR_PREINC_REFCOUNT(hdr);
51415 #endif
51416 			DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap, hdr);
51417 
51418 			/* Process finalizers unless skipping is explicitly
51419 			 * requested (NORZ) or refzero_list is being processed
51420 			 * (avoids side effects during a refzero cascade).
51421 			 * If refzero_list is processed, the initial refzero
51422 			 * call will run pending finalizers when refzero_list
51423 			 * is done.
51424 			 */
51425 			if (!skip_free_pending && heap->refzero_list == NULL) {
51426 				duk_heap_process_finalize_list(heap);
51427 			}
51428 			return;
51429 		}
51430 	}
51431 #endif  /* DUK_USE_FINALIZER_SUPPORT */
51432 
51433 	/* No need to finalize, free object via refzero_list. */
51434 
51435 	root = heap->refzero_list;
51436 
51437 	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
51438 	/* 'next' is left as GARBAGE. */
51439 	heap->refzero_list = hdr;
51440 
51441 	if (root == NULL) {
51442 		/* Object is now queued.  Refzero_list was NULL so
51443 		 * no-one is currently processing it; do it here.
51444 		 * With refzero processing just doing a cascade of
51445 		 * free calls, we can process it directly even when
51446 		 * NORZ macros are used: there are no side effects.
51447 		 */
51448 		duk__refcount_free_pending(heap);
51449 		DUK_ASSERT(heap->refzero_list == NULL);
51450 
51451 		/* Process finalizers only after the entire cascade
51452 		 * is finished.  In most cases there's nothing to
51453 		 * finalize, so fast path check to avoid a call.
51454 		 */
51455 #if defined(DUK_USE_FINALIZER_SUPPORT)
51456 		if (!skip_free_pending && DUK_UNLIKELY(heap->finalize_list != NULL)) {
51457 			duk_heap_process_finalize_list(heap);
51458 		}
51459 #endif
51460 	} else {
51461 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
51462 		DUK_HEAPHDR_SET_PREV(heap, root, hdr);
51463 
51464 		/* Object is now queued.  Because refzero_list was
51465 		 * non-NULL, it's already being processed by someone
51466 		 * in the C call stack, so we're done.
51467 		 */
51468 	}
51469 }
51470 
51471 #if defined(DUK_USE_FINALIZER_SUPPORT)
51472 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_refzero_check_fast(duk_hthread *thr) {
51473 	DUK_ASSERT(thr != NULL);
51474 	DUK_ASSERT(thr->heap != NULL);
51475 	DUK_ASSERT(thr->heap->refzero_list == NULL);  /* Processed to completion inline. */
51476 
51477 	if (DUK_UNLIKELY(thr->heap->finalize_list != NULL)) {
51478 		duk_heap_process_finalize_list(thr->heap);
51479 	}
51480 }
51481 
51482 DUK_INTERNAL void duk_refzero_check_slow(duk_hthread *thr) {
51483 	DUK_ASSERT(thr != NULL);
51484 	DUK_ASSERT(thr->heap != NULL);
51485 	DUK_ASSERT(thr->heap->refzero_list == NULL);  /* Processed to completion inline. */
51486 
51487 	if (DUK_UNLIKELY(thr->heap->finalize_list != NULL)) {
51488 		duk_heap_process_finalize_list(thr->heap);
51489 	}
51490 }
51491 #endif  /* DUK_USE_FINALIZER_SUPPORT */
51492 
51493 /*
51494  *  Refzero processing for duk_hstring.
51495  */
51496 
51497 DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hstring(duk_heap *heap, duk_hstring *str) {
51498 	DUK_ASSERT(heap != NULL);
51499 	DUK_ASSERT(heap->heap_thread != NULL);
51500 	DUK_ASSERT(str != NULL);
51501 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) str) == DUK_HTYPE_STRING);
51502 
51503 	duk_heap_strcache_string_remove(heap, str);
51504 	duk_heap_strtable_unlink(heap, str);
51505 	duk_free_hstring(heap, str);
51506 }
51507 
51508 /*
51509  *  Refzero processing for duk_hbuffer.
51510  */
51511 
51512 DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hbuffer(duk_heap *heap, duk_hbuffer *buf) {
51513 	DUK_ASSERT(heap != NULL);
51514 	DUK_ASSERT(heap->heap_thread != NULL);
51515 	DUK_ASSERT(buf != NULL);
51516 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) buf) == DUK_HTYPE_BUFFER);
51517 
51518 	DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap, (duk_heaphdr *) buf);
51519 	duk_free_hbuffer(heap, buf);
51520 }
51521 
51522 /*
51523  *  Incref and decref functions.
51524  *
51525  *  Decref may trigger immediate refzero handling, which may free and finalize
51526  *  an arbitrary number of objects (a "DECREF cascade").
51527  *
51528  *  Refzero handling is skipped entirely if (1) mark-and-sweep is running or
51529  *  (2) execution is paused in the debugger.  The objects are left in the heap,
51530  *  and will be freed by mark-and-sweep or eventual heap destruction.
51531  *
51532  *  This is necessary during mark-and-sweep because refcounts are also updated
51533  *  during the sweep phase (otherwise objects referenced by a swept object
51534  *  would have incorrect refcounts) which then calls here.  This could be
51535  *  avoided by using separate decref macros in mark-and-sweep; however,
51536  *  mark-and-sweep also calls finalizers which would use the ordinary decref
51537  *  macros anyway.
51538  *
51539  *  We can't process refzeros (= free objects) when the debugger is running
51540  *  as the debugger might make an object unreachable but still continue
51541  *  inspecting it (or even cause it to be pushed back).  So we must rely on
51542  *  mark-and-sweep to collect them.
51543  *
51544  *  The DUK__RZ_SUPPRESS_CHECK() condition is also used in heap destruction
51545  *  when running finalizers for remaining objects: the flag prevents objects
51546  *  from being moved around in heap linked lists while that's being done.
51547  *
51548  *  The suppress condition is important to performance.
51549  */
51550 
51551 #define DUK__RZ_SUPPRESS_ASSERT1() do { \
51552 		DUK_ASSERT(thr != NULL); \
51553 		DUK_ASSERT(thr->heap != NULL); \
51554 		/* When mark-and-sweep runs, heap_thread must exist. */ \
51555 		DUK_ASSERT(thr->heap->ms_running == 0 || thr->heap->heap_thread != NULL); \
51556 		/* In normal operation finalizers are executed with ms_running == 0 \
51557 		 * so we should never see ms_running == 1 and thr != heap_thread. \
51558 		 * In heap destruction finalizers are executed with ms_running != 0 \
51559 		 * to e.g. prevent refzero; a special value ms_running == 2 is used \
51560 		 * in that case so it can be distinguished from the normal runtime \
51561 		 * case, and allows a stronger assertion here (GH-2030). \
51562 		 */ \
51563 		DUK_ASSERT(!(thr->heap->ms_running == 1 && thr != thr->heap->heap_thread)); \
51564 		/* We may be called when the heap is initializing and we process \
51565 		 * refzeros normally, but mark-and-sweep and finalizers are prevented \
51566 		 * if that's the case. \
51567 		 */ \
51568 		DUK_ASSERT(thr->heap->heap_initializing == 0 || thr->heap->ms_prevent_count > 0); \
51569 		DUK_ASSERT(thr->heap->heap_initializing == 0 || thr->heap->pf_prevent_count > 0); \
51570 	} while (0)
51571 
51572 #if defined(DUK_USE_DEBUGGER_SUPPORT)
51573 #define DUK__RZ_SUPPRESS_ASSERT2() do { \
51574 		/* When debugger is paused, ms_running is set. */ \
51575 		DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || thr->heap->ms_running != 0); \
51576 	} while (0)
51577 #define DUK__RZ_SUPPRESS_COND()  (heap->ms_running != 0)
51578 #else
51579 #define DUK__RZ_SUPPRESS_ASSERT2() do { } while (0)
51580 #define DUK__RZ_SUPPRESS_COND()  (heap->ms_running != 0)
51581 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
51582 
51583 #define DUK__RZ_SUPPRESS_CHECK() do { \
51584 		DUK__RZ_SUPPRESS_ASSERT1(); \
51585 		DUK__RZ_SUPPRESS_ASSERT2(); \
51586 		if (DUK_UNLIKELY(DUK__RZ_SUPPRESS_COND())) { \
51587 			DUK_DDD(DUK_DDDPRINT("refzero handling suppressed (not even queued) when mark-and-sweep running, object: %p", (void *) h)); \
51588 			return; \
51589 		} \
51590 	} while (0)
51591 
51592 #define DUK__RZ_STRING() do { \
51593 		duk__refcount_refzero_hstring(heap, (duk_hstring *) h); \
51594 	} while (0)
51595 #define DUK__RZ_BUFFER() do { \
51596 		duk__refcount_refzero_hbuffer(heap, (duk_hbuffer *) h); \
51597 	} while (0)
51598 #define DUK__RZ_OBJECT() do { \
51599 		duk__refcount_refzero_hobject(heap, (duk_hobject *) h, skip_free_pending); \
51600 	} while (0)
51601 
51602 /* XXX: test the effect of inlining here vs. NOINLINE in refzero helpers */
51603 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
51604 #define DUK__RZ_INLINE DUK_ALWAYS_INLINE
51605 #else
51606 #define DUK__RZ_INLINE /*nop*/
51607 #endif
51608 
51609 DUK_LOCAL DUK__RZ_INLINE void duk__hstring_refzero_helper(duk_hthread *thr, duk_hstring *h) {
51610 	duk_heap *heap;
51611 
51612 	DUK_ASSERT(thr != NULL);
51613 	DUK_ASSERT(h != NULL);
51614 	heap = thr->heap;
51615 
51616 	DUK__RZ_SUPPRESS_CHECK();
51617 	DUK__RZ_STRING();
51618 }
51619 
51620 DUK_LOCAL DUK__RZ_INLINE void duk__hbuffer_refzero_helper(duk_hthread *thr, duk_hbuffer *h) {
51621 	duk_heap *heap;
51622 
51623 	DUK_ASSERT(thr != NULL);
51624 	DUK_ASSERT(h != NULL);
51625 	heap = thr->heap;
51626 
51627 	DUK__RZ_SUPPRESS_CHECK();
51628 	DUK__RZ_BUFFER();
51629 }
51630 
51631 DUK_LOCAL DUK__RZ_INLINE void duk__hobject_refzero_helper(duk_hthread *thr, duk_hobject *h, duk_bool_t skip_free_pending) {
51632 	duk_heap *heap;
51633 
51634 	DUK_ASSERT(thr != NULL);
51635 	DUK_ASSERT(h != NULL);
51636 	heap = thr->heap;
51637 
51638 	DUK__RZ_SUPPRESS_CHECK();
51639 	DUK__RZ_OBJECT();
51640 }
51641 
51642 DUK_LOCAL DUK__RZ_INLINE void duk__heaphdr_refzero_helper(duk_hthread *thr, duk_heaphdr *h, duk_bool_t skip_free_pending) {
51643 	duk_heap *heap;
51644 	duk_small_uint_t htype;
51645 
51646 	DUK_ASSERT(thr != NULL);
51647 	DUK_ASSERT(h != NULL);
51648 	heap = thr->heap;
51649 
51650 	htype = (duk_small_uint_t) DUK_HEAPHDR_GET_TYPE(h);
51651 	DUK_DDD(DUK_DDDPRINT("ms_running=%ld, heap_thread=%p", (long) thr->heap->ms_running, thr->heap->heap_thread));
51652 	DUK__RZ_SUPPRESS_CHECK();
51653 
51654 	switch (htype) {
51655 	case DUK_HTYPE_STRING:
51656 		/* Strings have no internal references but do have "weak"
51657 		 * references in the string cache.  Also note that strings
51658 		 * are not on the heap_allocated list like other heap
51659 		 * elements.
51660 		 */
51661 
51662 		DUK__RZ_STRING();
51663 		break;
51664 
51665 	case DUK_HTYPE_OBJECT:
51666 		/* Objects have internal references.  Must finalize through
51667 		 * the "refzero" work list.
51668 		 */
51669 
51670 		DUK__RZ_OBJECT();
51671 		break;
51672 
51673 	default:
51674 		/* Buffers have no internal references.  However, a dynamic
51675 		 * buffer has a separate allocation for the buffer.  This is
51676 		 * freed by duk_heap_free_heaphdr_raw().
51677 		 */
51678 
51679 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(h) == DUK_HTYPE_BUFFER);
51680 		DUK__RZ_BUFFER();
51681 		break;
51682 	}
51683 }
51684 
51685 DUK_INTERNAL DUK_NOINLINE void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h) {
51686 	duk__heaphdr_refzero_helper(thr, h, 0 /*skip_free_pending*/);
51687 }
51688 
51689 DUK_INTERNAL DUK_NOINLINE void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h) {
51690 	duk__heaphdr_refzero_helper(thr, h, 1 /*skip_free_pending*/);
51691 }
51692 
51693 DUK_INTERNAL DUK_NOINLINE void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h) {
51694 	duk__hstring_refzero_helper(thr, h);
51695 }
51696 
51697 DUK_INTERNAL DUK_NOINLINE void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h) {
51698 	duk__hbuffer_refzero_helper(thr, h);
51699 }
51700 
51701 DUK_INTERNAL DUK_NOINLINE void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h) {
51702 	duk__hobject_refzero_helper(thr, h, 0 /*skip_free_pending*/);
51703 }
51704 
51705 DUK_INTERNAL DUK_NOINLINE void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h) {
51706 	duk__hobject_refzero_helper(thr, h, 1 /*skip_free_pending*/);
51707 }
51708 
51709 #if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
51710 DUK_INTERNAL void duk_tval_incref(duk_tval *tv) {
51711 	DUK_ASSERT(tv != NULL);
51712 
51713 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
51714 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
51715 		DUK_ASSERT(h != NULL);
51716 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
51717 		DUK_ASSERT_DISABLE(h->h_refcount >= 0);
51718 		DUK_HEAPHDR_PREINC_REFCOUNT(h);
51719 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) != 0);  /* No wrapping. */
51720 	}
51721 }
51722 
51723 DUK_INTERNAL void duk_tval_decref(duk_hthread *thr, duk_tval *tv) {
51724 	DUK_ASSERT(thr != NULL);
51725 	DUK_ASSERT(tv != NULL);
51726 
51727 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
51728 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
51729 		DUK_ASSERT(h != NULL);
51730 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
51731 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
51732 #if 0
51733 		if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
51734 			return;
51735 		}
51736 		duk_heaphdr_refzero(thr, h);
51737 #else
51738 		duk_heaphdr_decref(thr, h);
51739 #endif
51740 	}
51741 }
51742 
51743 DUK_INTERNAL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv) {
51744 	DUK_ASSERT(thr != NULL);
51745 	DUK_ASSERT(tv != NULL);
51746 
51747 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
51748 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
51749 		DUK_ASSERT(h != NULL);
51750 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
51751 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
51752 #if 0
51753 		if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
51754 			return;
51755 		}
51756 		duk_heaphdr_refzero_norz(thr, h);
51757 #else
51758 		duk_heaphdr_decref_norz(thr, h);
51759 #endif
51760 	}
51761 }
51762 #endif  /* !DUK_USE_FAST_REFCOUNT_DEFAULT */
51763 
51764 #define DUK__DECREF_ASSERTS() do { \
51765 		DUK_ASSERT(thr != NULL); \
51766 		DUK_ASSERT(thr->heap != NULL); \
51767 		DUK_ASSERT(h != NULL); \
51768 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID((duk_heaphdr *) h)); \
51769 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) >= 1); \
51770 	} while (0)
51771 #if defined(DUK_USE_ROM_OBJECTS)
51772 #define DUK__INCREF_SHARED() do { \
51773 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
51774 			return; \
51775 		} \
51776 		DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
51777 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0);  /* No wrapping. */ \
51778 	} while (0)
51779 #define DUK__DECREF_SHARED() do { \
51780 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
51781 			return; \
51782 		} \
51783 		if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
51784 			return; \
51785 		} \
51786 	} while (0)
51787 #else
51788 #define DUK__INCREF_SHARED() do { \
51789 		DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
51790 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0);  /* No wrapping. */ \
51791 	} while (0)
51792 #define DUK__DECREF_SHARED() do { \
51793 		if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
51794 			return; \
51795 		} \
51796 	} while (0)
51797 #endif
51798 
51799 #if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
51800 /* This will in practice be inlined because it's just an INC instructions
51801  * and a bit test + INC when ROM objects are enabled.
51802  */
51803 DUK_INTERNAL void duk_heaphdr_incref(duk_heaphdr *h) {
51804 	DUK_ASSERT(h != NULL);
51805 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
51806 	DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);
51807 
51808 	DUK__INCREF_SHARED();
51809 }
51810 
51811 DUK_INTERNAL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h) {
51812 	DUK__DECREF_ASSERTS();
51813 	DUK__DECREF_SHARED();
51814 	duk_heaphdr_refzero(thr, h);
51815 
51816 	/* Forced mark-and-sweep when GC torture enabled; this could happen
51817 	 * on any DECREF (but not DECREF_NORZ).
51818 	 */
51819 	DUK_GC_TORTURE(thr->heap);
51820 }
51821 DUK_INTERNAL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h) {
51822 	DUK__DECREF_ASSERTS();
51823 	DUK__DECREF_SHARED();
51824 	duk_heaphdr_refzero_norz(thr, h);
51825 }
51826 #endif  /* !DUK_USE_FAST_REFCOUNT_DEFAULT */
51827 
51828 #if 0  /* Not needed. */
51829 DUK_INTERNAL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h) {
51830 	DUK__DECREF_ASSERTS();
51831 	DUK__DECREF_SHARED();
51832 	duk_hstring_refzero(thr, h);
51833 }
51834 DUK_INTERNAL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h) {
51835 	DUK__DECREF_ASSERTS();
51836 	DUK__DECREF_SHARED();
51837 	duk_hstring_refzero_norz(thr, h);
51838 }
51839 DUK_INTERNAL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h) {
51840 	DUK__DECREF_ASSERTS();
51841 	DUK__DECREF_SHARED();
51842 	duk_hbuffer_refzero(thr, h);
51843 }
51844 DUK_INTERNAL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h) {
51845 	DUK__DECREF_ASSERTS();
51846 	DUK__DECREF_SHARED();
51847 	duk_hbuffer_refzero_norz(thr, h);
51848 }
51849 DUK_INTERNAL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h) {
51850 	DUK__DECREF_ASSERTS();
51851 	DUK__DECREF_SHARED();
51852 	duk_hobject_refzero(thr, h);
51853 }
51854 DUK_INTERNAL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h) {
51855 	DUK__DECREF_ASSERTS();
51856 	DUK__DECREF_SHARED();
51857 	duk_hobject_refzero_norz(thr, h);
51858 }
51859 #endif
51860 
51861 #else  /* DUK_USE_REFERENCE_COUNTING */
51862 
51863 /* no refcounting */
51864 
51865 #endif  /* DUK_USE_REFERENCE_COUNTING */
51866 
51867 /* automatic undefs */
51868 #undef DUK__DECREF_ASSERTS
51869 #undef DUK__DECREF_SHARED
51870 #undef DUK__INCREF_SHARED
51871 #undef DUK__RZ_BUFFER
51872 #undef DUK__RZ_INLINE
51873 #undef DUK__RZ_OBJECT
51874 #undef DUK__RZ_STRING
51875 #undef DUK__RZ_SUPPRESS_ASSERT1
51876 #undef DUK__RZ_SUPPRESS_ASSERT2
51877 #undef DUK__RZ_SUPPRESS_CHECK
51878 #undef DUK__RZ_SUPPRESS_COND
51879 /*
51880  *  String cache.
51881  *
51882  *  Provides a cache to optimize indexed string lookups.  The cache keeps
51883  *  track of (byte offset, char offset) states for a fixed number of strings.
51884  *  Otherwise we'd need to scan from either end of the string, as we store
51885  *  strings in (extended) UTF-8.
51886  */
51887 
51888 /* #include duk_internal.h -> already included */
51889 
51890 /*
51891  *  Delete references to given hstring from the heap string cache.
51892  *
51893  *  String cache references are 'weak': they are not counted towards
51894  *  reference counts, nor serve as roots for mark-and-sweep.  When an
51895  *  object is about to be freed, such references need to be removed.
51896  */
51897 
51898 DUK_INTERNAL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h) {
51899 	duk_uint_t i;
51900 	for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
51901 		duk_strcache_entry *c = heap->strcache + i;
51902 		if (c->h == h) {
51903 			DUK_DD(DUK_DDPRINT("deleting weak strcache reference to hstring %p from heap %p",
51904 			                   (void *) h, (void *) heap));
51905 			c->h = NULL;
51906 
51907 			/* XXX: the string shouldn't appear twice, but we now loop to the
51908 			 * end anyway; if fixed, add a looping assertion to ensure there
51909 			 * is no duplicate.
51910 			 */
51911 		}
51912 	}
51913 }
51914 
51915 /*
51916  *  String scanning helpers
51917  *
51918  *  All bytes other than UTF-8 continuation bytes ([0x80,0xbf]) are
51919  *  considered to contribute a character.  This must match how string
51920  *  character length is computed.
51921  */
51922 
51923 DUK_LOCAL const duk_uint8_t *duk__scan_forwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
51924 	while (n > 0) {
51925 		for (;;) {
51926 			p++;
51927 			if (p >= q) {
51928 				return NULL;
51929 			}
51930 			if ((*p & 0xc0) != 0x80) {
51931 				break;
51932 			}
51933 		}
51934 		n--;
51935 	}
51936 	return p;
51937 }
51938 
51939 DUK_LOCAL const duk_uint8_t *duk__scan_backwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
51940 	while (n > 0) {
51941 		for (;;) {
51942 			p--;
51943 			if (p < q) {
51944 				return NULL;
51945 			}
51946 			if ((*p & 0xc0) != 0x80) {
51947 				break;
51948 			}
51949 		}
51950 		n--;
51951 	}
51952 	return p;
51953 }
51954 
51955 /*
51956  *  Convert char offset to byte offset
51957  *
51958  *  Avoid using the string cache if possible: for ASCII strings byte and
51959  *  char offsets are equal and for short strings direct scanning may be
51960  *  better than using the string cache (which may evict a more important
51961  *  entry).
51962  *
51963  *  Typing now assumes 32-bit string byte/char offsets (duk_uint_fast32_t).
51964  *  Better typing might be to use duk_size_t.
51965  *
51966  *  Caller should ensure 'char_offset' is within the string bounds [0,charlen]
51967  *  (endpoint is inclusive).  If this is not the case, no memory unsafe
51968  *  behavior will happen but an error will be thrown.
51969  */
51970 
51971 DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset) {
51972 	duk_heap *heap;
51973 	duk_strcache_entry *sce;
51974 	duk_uint_fast32_t byte_offset;
51975 	duk_uint_t i;
51976 	duk_bool_t use_cache;
51977 	duk_uint_fast32_t dist_start, dist_end, dist_sce;
51978 	duk_uint_fast32_t char_length;
51979 	const duk_uint8_t *p_start;
51980 	const duk_uint8_t *p_end;
51981 	const duk_uint8_t *p_found;
51982 
51983 	/*
51984 	 *  For ASCII strings, the answer is simple.
51985 	 */
51986 
51987 	if (DUK_LIKELY(DUK_HSTRING_IS_ASCII(h))) {
51988 		return char_offset;
51989 	}
51990 
51991 	char_length = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h);
51992 	DUK_ASSERT(char_offset <= char_length);
51993 
51994 	if (DUK_LIKELY(DUK_HSTRING_IS_ASCII(h))) {
51995 		/* Must recheck because the 'is ascii' flag may be set
51996 		 * lazily.  Alternatively, we could just compare charlen
51997 		 * to bytelen.
51998 		 */
51999 		return char_offset;
52000 	}
52001 
52002 	/*
52003 	 *  For non-ASCII strings, we need to scan forwards or backwards
52004 	 *  from some starting point.  The starting point may be the start
52005 	 *  or end of the string, or some cached midpoint in the string
52006 	 *  cache.
52007 	 *
52008 	 *  For "short" strings we simply scan without checking or updating
52009 	 *  the cache.  For longer strings we check and update the cache as
52010 	 *  necessary, inserting a new cache entry if none exists.
52011 	 */
52012 
52013 	DUK_DDD(DUK_DDDPRINT("non-ascii string %p, char_offset=%ld, clen=%ld, blen=%ld",
52014 	                     (void *) h, (long) char_offset,
52015 	                     (long) DUK_HSTRING_GET_CHARLEN(h),
52016 	                     (long) DUK_HSTRING_GET_BYTELEN(h)));
52017 
52018 	heap = thr->heap;
52019 	sce = NULL;
52020 	use_cache = (char_length > DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT);
52021 
52022 	if (use_cache) {
52023 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
52024 		DUK_DDD(DUK_DDDPRINT("stringcache before char2byte (using cache):"));
52025 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
52026 			duk_strcache_entry *c = heap->strcache + i;
52027 			DUK_DDD(DUK_DDDPRINT("  [%ld] -> h=%p, cidx=%ld, bidx=%ld",
52028 			                     (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
52029 		}
52030 #endif
52031 
52032 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
52033 			duk_strcache_entry *c = heap->strcache + i;
52034 
52035 			if (c->h == h) {
52036 				sce = c;
52037 				break;
52038 			}
52039 		}
52040 	}
52041 
52042 	/*
52043 	 *  Scan from shortest distance:
52044 	 *    - start of string
52045 	 *    - end of string
52046 	 *    - cache entry (if exists)
52047 	 */
52048 
52049 	DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h) >= char_offset);
52050 	dist_start = char_offset;
52051 	dist_end = char_length - char_offset;
52052 	dist_sce = 0; DUK_UNREF(dist_sce);  /* initialize for debug prints, needed if sce==NULL */
52053 
52054 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
52055 	p_end = (const duk_uint8_t *) (p_start + DUK_HSTRING_GET_BYTELEN(h));
52056 	p_found = NULL;
52057 
52058 	if (sce) {
52059 		if (char_offset >= sce->cidx) {
52060 			dist_sce = char_offset - sce->cidx;
52061 			if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
52062 				DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
52063 				                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
52064 				                     "scan forwards from sce",
52065 				                     (long) use_cache, (void *) (sce ? sce->h : NULL),
52066 				                     (sce ? (long) sce->cidx : (long) -1),
52067 				                     (sce ? (long) sce->bidx : (long) -1),
52068 				                     (long) dist_start, (long) dist_end, (long) dist_sce));
52069 
52070 				p_found = duk__scan_forwards(p_start + sce->bidx,
52071 				                             p_end,
52072 				                             dist_sce);
52073 				goto scan_done;
52074 			}
52075 		} else {
52076 			dist_sce = sce->cidx - char_offset;
52077 			if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
52078 				DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
52079 				                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
52080 				                     "scan backwards from sce",
52081 				                     (long) use_cache, (void *) (sce ? sce->h : NULL),
52082 				                     (sce ? (long) sce->cidx : (long) -1),
52083 				                     (sce ? (long) sce->bidx : (long) -1),
52084 				                     (long) dist_start, (long) dist_end, (long) dist_sce));
52085 
52086 				p_found = duk__scan_backwards(p_start + sce->bidx,
52087 				                              p_start,
52088 				                              dist_sce);
52089 				goto scan_done;
52090 			}
52091 		}
52092 	}
52093 
52094 	/* no sce, or sce scan not best */
52095 
52096 	if (dist_start <= dist_end) {
52097 		DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
52098 		                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
52099 		                     "scan forwards from string start",
52100 		                     (long) use_cache, (void *) (sce ? sce->h : NULL),
52101 		                     (sce ? (long) sce->cidx : (long) -1),
52102 		                     (sce ? (long) sce->bidx : (long) -1),
52103 		                     (long) dist_start, (long) dist_end, (long) dist_sce));
52104 
52105 		p_found = duk__scan_forwards(p_start,
52106 		                             p_end,
52107 		                             dist_start);
52108 	} else {
52109 		DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
52110 		                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
52111 		                     "scan backwards from string end",
52112 		                     (long) use_cache, (void *) (sce ? sce->h : NULL),
52113 		                     (sce ? (long) sce->cidx : (long) -1),
52114 		                     (sce ? (long) sce->bidx : (long) -1),
52115 		                     (long) dist_start, (long) dist_end, (long) dist_sce));
52116 
52117 		p_found = duk__scan_backwards(p_end,
52118 		                              p_start,
52119 		                              dist_end);
52120 	}
52121 
52122  scan_done:
52123 
52124 	if (DUK_UNLIKELY(p_found == NULL)) {
52125 		/* Scan error: this shouldn't normally happen; it could happen if
52126 		 * string is not valid UTF-8 data, and clen/blen are not consistent
52127 		 * with the scanning algorithm.
52128 		 */
52129 		goto scan_error;
52130 	}
52131 
52132 	DUK_ASSERT(p_found >= p_start);
52133 	DUK_ASSERT(p_found <= p_end);  /* may be equal */
52134 	byte_offset = (duk_uint32_t) (p_found - p_start);
52135 
52136 	DUK_DDD(DUK_DDDPRINT("-> string %p, cidx %ld -> bidx %ld",
52137 	                     (void *) h, (long) char_offset, (long) byte_offset));
52138 
52139 	/*
52140 	 *  Update cache entry (allocating if necessary), and move the
52141 	 *  cache entry to the first place (in an "LRU" policy).
52142 	 */
52143 
52144 	if (use_cache) {
52145 		/* update entry, allocating if necessary */
52146 		if (!sce) {
52147 			sce = heap->strcache + DUK_HEAP_STRCACHE_SIZE - 1;  /* take last entry */
52148 			sce->h = h;
52149 		}
52150 		DUK_ASSERT(sce != NULL);
52151 		sce->bidx = (duk_uint32_t) (p_found - p_start);
52152 		sce->cidx = (duk_uint32_t) char_offset;
52153 
52154 		/* LRU: move our entry to first */
52155 		if (sce > &heap->strcache[0]) {
52156 			/*
52157 			 *   A                  C
52158 			 *   B                  A
52159 			 *   C <- sce    ==>    B
52160 			 *   D                  D
52161 			 */
52162 			duk_strcache_entry tmp;
52163 
52164 			tmp = *sce;
52165 			duk_memmove((void *) (&heap->strcache[1]),
52166 			            (const void *) (&heap->strcache[0]),
52167 			            (size_t) (((char *) sce) - ((char *) &heap->strcache[0])));
52168 			heap->strcache[0] = tmp;
52169 
52170 			/* 'sce' points to the wrong entry here, but is no longer used */
52171 		}
52172 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
52173 		DUK_DDD(DUK_DDDPRINT("stringcache after char2byte (using cache):"));
52174 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
52175 			duk_strcache_entry *c = heap->strcache + i;
52176 			DUK_DDD(DUK_DDDPRINT("  [%ld] -> h=%p, cidx=%ld, bidx=%ld",
52177 			                     (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
52178 		}
52179 #endif
52180 	}
52181 
52182 	return byte_offset;
52183 
52184  scan_error:
52185 	DUK_ERROR_INTERNAL(thr);
52186 	DUK_WO_NORETURN(return 0;);
52187 }
52188 /*
52189  *  Heap string table handling, string interning.
52190  */
52191 
52192 /* #include duk_internal.h -> already included */
52193 
52194 /* Resize checks not needed if minsize == maxsize, typical for low memory
52195  * targets.
52196  */
52197 #define DUK__STRTAB_RESIZE_CHECK
52198 #if (DUK_USE_STRTAB_MINSIZE == DUK_USE_STRTAB_MAXSIZE)
52199 #undef DUK__STRTAB_RESIZE_CHECK
52200 #endif
52201 
52202 #if defined(DUK_USE_STRTAB_PTRCOMP)
52203 #define DUK__HEAPPTR_ENC16(heap,ptr)    DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (ptr))
52204 #define DUK__HEAPPTR_DEC16(heap,val)    DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (val))
52205 #define DUK__GET_STRTABLE(heap)         ((heap)->strtable16)
52206 #else
52207 #define DUK__HEAPPTR_ENC16(heap,ptr)    (ptr)
52208 #define DUK__HEAPPTR_DEC16(heap,val)    (val)
52209 #define DUK__GET_STRTABLE(heap)         ((heap)->strtable)
52210 #endif
52211 
52212 #define DUK__STRTAB_U32_MAX_STRLEN      10               /* 4'294'967'295 */
52213 
52214 /*
52215  *  Debug dump stringtable.
52216  */
52217 
52218 #if defined(DUK_USE_DEBUG)
52219 DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap) {
52220 #if defined(DUK_USE_STRTAB_PTRCOMP)
52221 	duk_uint16_t *strtable;
52222 #else
52223 	duk_hstring **strtable;
52224 #endif
52225 	duk_uint32_t i;
52226 	duk_hstring *h;
52227 	duk_size_t count_total = 0;
52228 	duk_size_t count_chain;
52229 	duk_size_t count_chain_min = DUK_SIZE_MAX;
52230 	duk_size_t count_chain_max = 0;
52231 	duk_size_t count_len[8];  /* chain lengths from 0 to 7 */
52232 
52233 	if (heap == NULL) {
52234 		DUK_D(DUK_DPRINT("string table, heap=NULL"));
52235 		return;
52236 	}
52237 
52238 	strtable = DUK__GET_STRTABLE(heap);
52239 	if (strtable == NULL) {
52240 		DUK_D(DUK_DPRINT("string table, strtab=NULL"));
52241 		return;
52242 	}
52243 
52244 	duk_memzero((void *) count_len, sizeof(count_len));
52245 	for (i = 0; i < heap->st_size; i++) {
52246 		h = DUK__HEAPPTR_DEC16(heap, strtable[i]);
52247 		count_chain = 0;
52248 		while (h != NULL) {
52249 			count_chain++;
52250 			h = h->hdr.h_next;
52251 		}
52252 		if (count_chain < sizeof(count_len) / sizeof(duk_size_t)) {
52253 			count_len[count_chain]++;
52254 		}
52255 		count_chain_max = (count_chain > count_chain_max ? count_chain : count_chain_max);
52256 		count_chain_min = (count_chain < count_chain_min ? count_chain : count_chain_min);
52257 		count_total += count_chain;
52258 	}
52259 
52260 	DUK_D(DUK_DPRINT("string table, strtab=%p, count=%lu, chain min=%lu max=%lu avg=%lf: "
52261 	                 "counts: %lu %lu %lu %lu %lu %lu %lu %lu ...",
52262 	                 (void *) heap->strtable, (unsigned long) count_total,
52263 	                 (unsigned long) count_chain_min, (unsigned long) count_chain_max,
52264 	                 (double) count_total / (double) heap->st_size,
52265 	                 (unsigned long) count_len[0], (unsigned long) count_len[1],
52266 	                 (unsigned long) count_len[2], (unsigned long) count_len[3],
52267 	                 (unsigned long) count_len[4], (unsigned long) count_len[5],
52268 	                 (unsigned long) count_len[6], (unsigned long) count_len[7]));
52269 }
52270 #endif  /* DUK_USE_DEBUG */
52271 
52272 /*
52273  *  Assertion helper to ensure strtable is populated correctly.
52274  */
52275 
52276 #if defined(DUK_USE_ASSERTIONS)
52277 DUK_LOCAL void duk__strtable_assert_checks(duk_heap *heap) {
52278 #if defined(DUK_USE_STRTAB_PTRCOMP)
52279 	duk_uint16_t *strtable;
52280 #else
52281 	duk_hstring **strtable;
52282 #endif
52283 	duk_uint32_t i;
52284 	duk_hstring *h;
52285 	duk_size_t count = 0;
52286 
52287 	DUK_ASSERT(heap != NULL);
52288 
52289 	strtable = DUK__GET_STRTABLE(heap);
52290 	if (strtable != NULL) {
52291 		DUK_ASSERT(heap->st_size != 0);
52292 		DUK_ASSERT(heap->st_mask == heap->st_size - 1);
52293 
52294 		for (i = 0; i < heap->st_size; i++) {
52295 			h = DUK__HEAPPTR_DEC16(heap, strtable[i]);
52296 			while (h != NULL) {
52297 				DUK_ASSERT((DUK_HSTRING_GET_HASH(h) & heap->st_mask) == i);
52298 				count++;
52299 				h = h->hdr.h_next;
52300 			}
52301 		}
52302 	} else {
52303 		DUK_ASSERT(heap->st_size == 0);
52304 		DUK_ASSERT(heap->st_mask == 0);
52305 	}
52306 
52307 #if defined(DUK__STRTAB_RESIZE_CHECK)
52308 	DUK_ASSERT(count == (duk_size_t) heap->st_count);
52309 #endif
52310 }
52311 #endif  /* DUK_USE_ASSERTIONS */
52312 
52313 /*
52314  *  Allocate and initialize a duk_hstring.
52315  *
52316  *  Returns a NULL if allocation or initialization fails for some reason.
52317  *
52318  *  The string won't be inserted into the string table and isn't tracked in
52319  *  any way (link pointers will be NULL).  The caller must place the string
52320  *  into the string table without any risk of a longjmp, otherwise the string
52321  *  is leaked.
52322  */
52323 
52324 DUK_LOCAL duk_hstring *duk__strtable_alloc_hstring(duk_heap *heap,
52325                                                    const duk_uint8_t *str,
52326                                                    duk_uint32_t blen,
52327                                                    duk_uint32_t strhash,
52328                                                    const duk_uint8_t *extdata) {
52329 	duk_hstring *res;
52330 	const duk_uint8_t *data;
52331 #if !defined(DUK_USE_HSTRING_ARRIDX)
52332 	duk_uarridx_t dummy;
52333 #endif
52334 
52335 	DUK_ASSERT(heap != NULL);
52336 	DUK_UNREF(extdata);
52337 
52338 #if defined(DUK_USE_STRLEN16)
52339 	/* If blen <= 0xffffUL, clen is also guaranteed to be <= 0xffffUL. */
52340 	if (blen > 0xffffUL) {
52341 		DUK_D(DUK_DPRINT("16-bit string blen/clen active and blen over 16 bits, reject intern"));
52342 		goto alloc_error;
52343 	}
52344 #endif
52345 
52346 	/* XXX: Memzeroing the allocated structure is not really necessary
52347 	 * because we could just initialize all fields explicitly (almost
52348 	 * all fields are initialized explicitly anyway).
52349 	 */
52350 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
52351 	if (extdata) {
52352 		res = (duk_hstring *) DUK_ALLOC(heap, sizeof(duk_hstring_external));
52353 		if (DUK_UNLIKELY(res == NULL)) {
52354 			goto alloc_error;
52355 		}
52356 		duk_memzero(res, sizeof(duk_hstring_external));
52357 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
52358 		DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
52359 #endif
52360 		DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, DUK_HSTRING_FLAG_EXTDATA);
52361 
52362 		DUK_ASSERT(extdata[blen] == 0);  /* Application responsibility. */
52363 		data = extdata;
52364 		((duk_hstring_external *) res)->extdata = extdata;
52365 	} else
52366 #endif  /* DUK_USE_HSTRING_EXTDATA && DUK_USE_EXTSTR_INTERN_CHECK */
52367 	{
52368 		duk_uint8_t *data_tmp;
52369 
52370 		/* NUL terminate for convenient C access */
52371 		DUK_ASSERT(sizeof(duk_hstring) + blen + 1 > blen);  /* No wrap, limits ensure. */
52372 		res = (duk_hstring *) DUK_ALLOC(heap, sizeof(duk_hstring) + blen + 1);
52373 		if (DUK_UNLIKELY(res == NULL)) {
52374 			goto alloc_error;
52375 		}
52376 		duk_memzero(res, sizeof(duk_hstring));
52377 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
52378 		DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
52379 #endif
52380 		DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0);
52381 
52382 		data_tmp = (duk_uint8_t *) (res + 1);
52383 		duk_memcpy(data_tmp, str, blen);
52384 		data_tmp[blen] = (duk_uint8_t) 0;
52385 		data = (const duk_uint8_t *) data_tmp;
52386 	}
52387 
52388 	DUK_HSTRING_SET_BYTELEN(res, blen);
52389 	DUK_HSTRING_SET_HASH(res, strhash);
52390 
52391 	DUK_ASSERT(!DUK_HSTRING_HAS_ARRIDX(res));
52392 #if defined(DUK_USE_HSTRING_ARRIDX)
52393 	res->arridx = duk_js_to_arrayindex_string(data, blen);
52394 	if (res->arridx != DUK_HSTRING_NO_ARRAY_INDEX) {
52395 #else
52396 	dummy = duk_js_to_arrayindex_string(data, blen);
52397 	if (dummy != DUK_HSTRING_NO_ARRAY_INDEX) {
52398 #endif
52399 		/* Array index strings cannot be symbol strings,
52400 		 * and they're always pure ASCII so blen == clen.
52401 		 */
52402 		DUK_HSTRING_SET_ARRIDX(res);
52403 		DUK_HSTRING_SET_ASCII(res);
52404 		DUK_ASSERT(duk_unicode_unvalidated_utf8_length(data, (duk_size_t) blen) == blen);
52405 	} else {
52406 		/* Because 'data' is NUL-terminated, we don't need a
52407 		 * blen > 0 check here.  For NUL (0x00) the symbol
52408 		 * checks will be false.
52409 		 */
52410 		if (DUK_UNLIKELY(data[0] >= 0x80U)) {
52411 			if (data[0] <= 0x81) {
52412 				DUK_HSTRING_SET_SYMBOL(res);
52413 			} else if (data[0] == 0x82U || data[0] == 0xffU) {
52414 				DUK_HSTRING_SET_HIDDEN(res);
52415 				DUK_HSTRING_SET_SYMBOL(res);
52416 			}
52417 		}
52418 
52419 		/* Using an explicit 'ASCII' flag has larger footprint (one call site
52420 		 * only) but is quite useful for the case when there's no explicit
52421 		 * 'clen' in duk_hstring.
52422 		 *
52423 		 * The flag is set lazily for RAM strings.
52424 		 */
52425 		DUK_ASSERT(!DUK_HSTRING_HAS_ASCII(res));
52426 
52427 #if defined(DUK_USE_HSTRING_LAZY_CLEN)
52428 		/* Charlen initialized to 0, updated on-the-fly. */
52429 #else
52430 		duk_hstring_init_charlen(res);  /* Also sets ASCII flag. */
52431 #endif
52432 	}
52433 
52434 	DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, has_arridx=%ld, has_extdata=%ld",
52435 	                     (unsigned long) DUK_HSTRING_GET_HASH(res),
52436 	                     (long) DUK_HSTRING_GET_BYTELEN(res),
52437 	                     (long) (DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0),
52438 	                     (long) (DUK_HSTRING_HAS_EXTDATA(res) ? 1 : 0)));
52439 
52440 	DUK_ASSERT(res != NULL);
52441 	return res;
52442 
52443  alloc_error:
52444 	return NULL;
52445 }
52446 
52447 /*
52448  *  Grow strtable allocation in-place.
52449  */
52450 
52451 #if defined(DUK__STRTAB_RESIZE_CHECK)
52452 DUK_LOCAL void duk__strtable_grow_inplace(duk_heap *heap) {
52453 	duk_uint32_t new_st_size;
52454 	duk_uint32_t old_st_size;
52455 	duk_uint32_t i;
52456 	duk_hstring *h;
52457 	duk_hstring *next;
52458 	duk_hstring *prev;
52459 #if defined(DUK_USE_STRTAB_PTRCOMP)
52460 	duk_uint16_t *new_ptr;
52461 	duk_uint16_t *new_ptr_high;
52462 #else
52463 	duk_hstring **new_ptr;
52464 	duk_hstring **new_ptr_high;
52465 #endif
52466 
52467 	DUK_DD(DUK_DDPRINT("grow in-place: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size * 2));
52468 
52469 	DUK_ASSERT(heap != NULL);
52470 	DUK_ASSERT(heap->st_resizing == 1);
52471 	DUK_ASSERT(heap->st_size >= 2);
52472 	DUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0);  /* 2^N */
52473 	DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
52474 
52475 	DUK_STATS_INC(heap, stats_strtab_resize_grow);
52476 
52477 	new_st_size = heap->st_size << 1U;
52478 	DUK_ASSERT(new_st_size > heap->st_size);  /* No overflow. */
52479 
52480 	/* Reallocate the strtable first and then work in-place to rehash
52481 	 * strings.  We don't need an indirect allocation here: even if GC
52482 	 * is triggered to satisfy the allocation, recursive strtable resize
52483 	 * is prevented by flags.  This is also why we don't need to use
52484 	 * DUK_REALLOC_INDIRECT().
52485 	 */
52486 
52487 #if defined(DUK_USE_STRTAB_PTRCOMP)
52488 	new_ptr = (duk_uint16_t *) DUK_REALLOC(heap, heap->strtable16, sizeof(duk_uint16_t) * new_st_size);
52489 #else
52490 	new_ptr = (duk_hstring **) DUK_REALLOC(heap, heap->strtable, sizeof(duk_hstring *) * new_st_size);
52491 #endif
52492 	if (DUK_UNLIKELY(new_ptr == NULL)) {
52493 		/* If realloc fails we can continue normally: the string table
52494 		 * won't "fill up" although chains will gradually get longer.
52495 		 * When string insertions continue, we'll quite soon try again
52496 		 * with no special handling.
52497 		 */
52498 		DUK_D(DUK_DPRINT("string table grow failed, ignoring"));
52499 		return;
52500 	}
52501 #if defined(DUK_USE_STRTAB_PTRCOMP)
52502 	heap->strtable16 = new_ptr;
52503 #else
52504 	heap->strtable = new_ptr;
52505 #endif
52506 
52507 	/* Rehash a single bucket into two separate ones.  When we grow
52508 	 * by x2 the highest 'new' bit determines whether a string remains
52509 	 * in its old position (bit is 0) or goes to a new one (bit is 1).
52510 	 */
52511 
52512 	old_st_size = heap->st_size;
52513 	new_ptr_high = new_ptr + old_st_size;
52514 	for (i = 0; i < old_st_size; i++) {
52515 		duk_hstring *new_root;
52516 		duk_hstring *new_root_high;
52517 
52518 		h = DUK__HEAPPTR_DEC16(heap, new_ptr[i]);
52519 		new_root = h;
52520 		new_root_high = NULL;
52521 
52522 		prev = NULL;
52523 		while (h != NULL) {
52524 			duk_uint32_t mask;
52525 
52526 			DUK_ASSERT((DUK_HSTRING_GET_HASH(h) & heap->st_mask) == i);
52527 			next = h->hdr.h_next;
52528 
52529 			/* Example: if previous size was 256, previous mask is 0xFF
52530 			 * and size is 0x100 which corresponds to the new bit that
52531 			 * comes into play.
52532 			 */
52533 			DUK_ASSERT(heap->st_mask == old_st_size - 1);
52534 			mask = old_st_size;
52535 			if (DUK_HSTRING_GET_HASH(h) & mask) {
52536 				if (prev != NULL) {
52537 					prev->hdr.h_next = h->hdr.h_next;
52538 				} else {
52539 					DUK_ASSERT(h == new_root);
52540 					new_root = h->hdr.h_next;
52541 				}
52542 
52543 				h->hdr.h_next = new_root_high;
52544 				new_root_high = h;
52545 			} else {
52546 				prev = h;
52547 			}
52548 			h = next;
52549 		}
52550 
52551 		new_ptr[i] = DUK__HEAPPTR_ENC16(heap, new_root);
52552 		new_ptr_high[i] = DUK__HEAPPTR_ENC16(heap, new_root_high);
52553 	}
52554 
52555 	heap->st_size = new_st_size;
52556 	heap->st_mask = new_st_size - 1;
52557 
52558 #if defined(DUK_USE_ASSERTIONS)
52559 	duk__strtable_assert_checks(heap);
52560 #endif
52561 }
52562 #endif  /* DUK__STRTAB_RESIZE_CHECK */
52563 
52564 /*
52565  *  Shrink strtable allocation in-place.
52566  */
52567 
52568 #if defined(DUK__STRTAB_RESIZE_CHECK)
52569 DUK_LOCAL void duk__strtable_shrink_inplace(duk_heap *heap) {
52570 	duk_uint32_t new_st_size;
52571 	duk_uint32_t i;
52572 	duk_hstring *h;
52573 	duk_hstring *other;
52574 	duk_hstring *root;
52575 #if defined(DUK_USE_STRTAB_PTRCOMP)
52576 	duk_uint16_t *old_ptr;
52577 	duk_uint16_t *old_ptr_high;
52578 	duk_uint16_t *new_ptr;
52579 #else
52580 	duk_hstring **old_ptr;
52581 	duk_hstring **old_ptr_high;
52582 	duk_hstring **new_ptr;
52583 #endif
52584 
52585 	DUK_DD(DUK_DDPRINT("shrink in-place: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size / 2));
52586 
52587 	DUK_ASSERT(heap != NULL);
52588 	DUK_ASSERT(heap->st_resizing == 1);
52589 	DUK_ASSERT(heap->st_size >= 2);
52590 	DUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0);  /* 2^N */
52591 	DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
52592 
52593 	DUK_STATS_INC(heap, stats_strtab_resize_shrink);
52594 
52595 	new_st_size = heap->st_size >> 1U;
52596 
52597 	/* Combine two buckets into a single one.  When we shrink, one hash
52598 	 * bit (highest) disappears.
52599 	 */
52600 	old_ptr = DUK__GET_STRTABLE(heap);
52601 	old_ptr_high = old_ptr + new_st_size;
52602 	for (i = 0; i < new_st_size; i++) {
52603 		h = DUK__HEAPPTR_DEC16(heap, old_ptr[i]);
52604 		other = DUK__HEAPPTR_DEC16(heap, old_ptr_high[i]);
52605 
52606 		if (h == NULL) {
52607 			/* First chain is empty, so use second one as is. */
52608 			root = other;
52609 		} else {
52610 			/* Find end of first chain, and link in the second. */
52611 			root = h;
52612 			while (h->hdr.h_next != NULL) {
52613 				h = h->hdr.h_next;
52614 			}
52615 			h->hdr.h_next = other;
52616 		}
52617 
52618 		old_ptr[i] = DUK__HEAPPTR_ENC16(heap, root);
52619 	}
52620 
52621 	heap->st_size = new_st_size;
52622 	heap->st_mask = new_st_size - 1;
52623 
52624 	/* The strtable is now consistent and we can realloc safely.  Even
52625 	 * if side effects cause string interning or removal the strtable
52626 	 * updates are safe.  Recursive resize has been prevented by caller.
52627 	 * This is also why we don't need to use DUK_REALLOC_INDIRECT().
52628 	 *
52629 	 * We assume a realloc() to a smaller size is guaranteed to succeed.
52630 	 * It would be relatively straightforward to handle the error by
52631 	 * essentially performing a "grow" step to recover.
52632 	 */
52633 
52634 #if defined(DUK_USE_STRTAB_PTRCOMP)
52635 	new_ptr = (duk_uint16_t *) DUK_REALLOC(heap, heap->strtable16, sizeof(duk_uint16_t) * new_st_size);
52636 	DUK_ASSERT(new_ptr != NULL);
52637 	heap->strtable16 = new_ptr;
52638 #else
52639 	new_ptr = (duk_hstring **) DUK_REALLOC(heap, heap->strtable, sizeof(duk_hstring *) * new_st_size);
52640 	DUK_ASSERT(new_ptr != NULL);
52641 	heap->strtable = new_ptr;
52642 #endif
52643 
52644 #if defined(DUK_USE_ASSERTIONS)
52645 	duk__strtable_assert_checks(heap);
52646 #endif
52647 }
52648 #endif  /* DUK__STRTAB_RESIZE_CHECK */
52649 
52650 /*
52651  *  Grow/shrink check.
52652  */
52653 
52654 #if defined(DUK__STRTAB_RESIZE_CHECK)
52655 DUK_LOCAL DUK_COLD DUK_NOINLINE void duk__strtable_resize_check(duk_heap *heap) {
52656 	duk_uint32_t load_factor;  /* fixed point */
52657 
52658 	DUK_ASSERT(heap != NULL);
52659 #if defined(DUK_USE_STRTAB_PTRCOMP)
52660 	DUK_ASSERT(heap->strtable16 != NULL);
52661 #else
52662 	DUK_ASSERT(heap->strtable != NULL);
52663 #endif
52664 
52665 	DUK_STATS_INC(heap, stats_strtab_resize_check);
52666 
52667 	/* Prevent recursive resizing. */
52668 	if (DUK_UNLIKELY(heap->st_resizing != 0U)) {
52669 		DUK_D(DUK_DPRINT("prevent recursive strtable resize"));
52670 		return;
52671 	}
52672 
52673 	heap->st_resizing = 1;
52674 
52675 	DUK_ASSERT(heap->st_size >= 16U);
52676 	DUK_ASSERT((heap->st_size >> 4U) >= 1);
52677 	load_factor = heap->st_count / (heap->st_size >> 4U);
52678 
52679 	DUK_DD(DUK_DDPRINT("resize check string table: size=%lu, count=%lu, load_factor=%lu (fixed point .4; float %lf)",
52680 	                   (unsigned long) heap->st_size, (unsigned long) heap->st_count,
52681 	                   (unsigned long) load_factor,
52682 	                   (double) heap->st_count / (double) heap->st_size));
52683 
52684 	if (load_factor >= DUK_USE_STRTAB_GROW_LIMIT) {
52685 		if (heap->st_size >= DUK_USE_STRTAB_MAXSIZE) {
52686 			DUK_DD(DUK_DDPRINT("want to grow strtable (based on load factor) but already maximum size"));
52687 		} else {
52688 			DUK_D(DUK_DPRINT("grow string table: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size * 2));
52689 #if defined(DUK_USE_DEBUG)
52690 			duk_heap_strtable_dump(heap);
52691 #endif
52692 			duk__strtable_grow_inplace(heap);
52693 		}
52694 	} else if (load_factor <= DUK_USE_STRTAB_SHRINK_LIMIT) {
52695 		if (heap->st_size <= DUK_USE_STRTAB_MINSIZE) {
52696 			DUK_DD(DUK_DDPRINT("want to shrink strtable (based on load factor) but already minimum size"));
52697 		} else {
52698 			DUK_D(DUK_DPRINT("shrink string table: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size / 2));
52699 #if defined(DUK_USE_DEBUG)
52700 			duk_heap_strtable_dump(heap);
52701 #endif
52702 			duk__strtable_shrink_inplace(heap);
52703 		}
52704 	} else {
52705 		DUK_DD(DUK_DDPRINT("no need for strtable resize"));
52706 	}
52707 
52708 	heap->st_resizing = 0;
52709 }
52710 #endif  /* DUK__STRTAB_RESIZE_CHECK */
52711 
52712 /*
52713  *  Torture grow/shrink: unconditionally grow and shrink back.
52714  */
52715 
52716 #if defined(DUK_USE_STRTAB_TORTURE) && defined(DUK__STRTAB_RESIZE_CHECK)
52717 DUK_LOCAL void duk__strtable_resize_torture(duk_heap *heap) {
52718 	duk_uint32_t old_st_size;
52719 
52720 	DUK_ASSERT(heap != NULL);
52721 
52722 	old_st_size = heap->st_size;
52723 	if (old_st_size >= DUK_USE_STRTAB_MAXSIZE) {
52724 		return;
52725 	}
52726 
52727 	heap->st_resizing = 1;
52728 	duk__strtable_grow_inplace(heap);
52729 	if (heap->st_size > old_st_size) {
52730 		duk__strtable_shrink_inplace(heap);
52731 	}
52732 	heap->st_resizing = 0;
52733 }
52734 #endif  /* DUK_USE_STRTAB_TORTURE && DUK__STRTAB_RESIZE_CHECK */
52735 
52736 /*
52737  *  Raw intern; string already checked not to be present.
52738  */
52739 
52740 DUK_LOCAL duk_hstring *duk__strtable_do_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
52741 	duk_hstring *res;
52742 	const duk_uint8_t *extdata;
52743 #if defined(DUK_USE_STRTAB_PTRCOMP)
52744 	duk_uint16_t *slot;
52745 #else
52746 	duk_hstring **slot;
52747 #endif
52748 
52749 	DUK_DDD(DUK_DDDPRINT("do_intern: heap=%p, str=%p, blen=%lu, strhash=%lx, st_size=%lu, st_count=%lu, load=%lf",
52750 	                     (void *) heap, (const void *) str, (unsigned long) blen, (unsigned long) strhash,
52751 	                     (unsigned long) heap->st_size, (unsigned long) heap->st_count,
52752 	                     (double) heap->st_count / (double) heap->st_size));
52753 
52754 	DUK_ASSERT(heap != NULL);
52755 
52756 	/* Prevent any side effects on the string table and the caller provided
52757 	 * str/blen arguments while interning is in progress.  For example, if
52758 	 * the caller provided str/blen from a dynamic buffer, a finalizer
52759 	 * might resize or modify that dynamic buffer, invalidating the call
52760 	 * arguments.
52761 	 *
52762 	 * While finalizers must be prevented, mark-and-sweep itself is fine.
52763 	 * Recursive string table resize is prevented explicitly here.
52764 	 */
52765 
52766 	heap->pf_prevent_count++;
52767 	DUK_ASSERT(heap->pf_prevent_count != 0);  /* Wrap. */
52768 
52769 #if defined(DUK_USE_STRTAB_TORTURE) && defined(DUK__STRTAB_RESIZE_CHECK)
52770 	duk__strtable_resize_torture(heap);
52771 #endif
52772 
52773 	/* String table grow/shrink check.  Because of chaining (and no
52774 	 * accumulation issues as with hash probe chains and DELETED
52775 	 * markers) there's never a mandatory need to resize right now.
52776 	 * Check for the resize only periodically, based on st_count
52777 	 * bit pattern.  Because string table removal doesn't do a shrink
52778 	 * check, we do that also here.
52779 	 *
52780 	 * Do the resize and possible grow/shrink before the new duk_hstring
52781 	 * has been allocated.  Otherwise we may trigger a GC when the result
52782 	 * duk_hstring is not yet strongly referenced.
52783 	 */
52784 
52785 #if defined(DUK__STRTAB_RESIZE_CHECK)
52786 	if (DUK_UNLIKELY((heap->st_count & DUK_USE_STRTAB_RESIZE_CHECK_MASK) == 0)) {
52787 		duk__strtable_resize_check(heap);
52788 	}
52789 #endif
52790 
52791 	/* External string check (low memory optimization). */
52792 
52793 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
52794 	extdata = (const duk_uint8_t *) DUK_USE_EXTSTR_INTERN_CHECK(heap->heap_udata, (void *) DUK_LOSE_CONST(str), (duk_size_t) blen);
52795 #else
52796 	extdata = (const duk_uint8_t *) NULL;
52797 #endif
52798 
52799 	/* Allocate and initialize string, not yet linked.  This may cause a
52800 	 * GC which may cause other strings to be interned and inserted into
52801 	 * the string table before we insert our string.  Finalizer execution
52802 	 * is disabled intentionally to avoid a finalizer from e.g. resizing
52803 	 * a buffer used as a data area for 'str'.
52804 	 */
52805 
52806 	res = duk__strtable_alloc_hstring(heap, str, blen, strhash, extdata);
52807 
52808 	/* Allow side effects again: GC must be avoided until duk_hstring
52809 	 * result (if successful) has been INCREF'd.
52810 	 */
52811 	DUK_ASSERT(heap->pf_prevent_count > 0);
52812 	heap->pf_prevent_count--;
52813 
52814 	/* Alloc error handling. */
52815 
52816 	if (DUK_UNLIKELY(res == NULL)) {
52817 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
52818 		if (extdata != NULL) {
52819 			DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) extdata);
52820 		}
52821 #endif
52822 		return NULL;
52823 	}
52824 
52825 	/* Insert into string table. */
52826 
52827 #if defined(DUK_USE_STRTAB_PTRCOMP)
52828 	slot = heap->strtable16 + (strhash & heap->st_mask);
52829 #else
52830 	slot = heap->strtable + (strhash & heap->st_mask);
52831 #endif
52832 	DUK_ASSERT(res->hdr.h_next == NULL);  /* This is the case now, but unnecessary zeroing/NULLing. */
52833 	res->hdr.h_next = DUK__HEAPPTR_DEC16(heap, *slot);
52834 	*slot = DUK__HEAPPTR_ENC16(heap, res);
52835 
52836 	/* Update string count only for successful inserts. */
52837 
52838 #if defined(DUK__STRTAB_RESIZE_CHECK)
52839 	heap->st_count++;
52840 #endif
52841 
52842 	/* The duk_hstring is in the string table but is not yet strongly
52843 	 * reachable.  Calling code MUST NOT make any allocations or other
52844 	 * side effects before the duk_hstring has been INCREF'd and made
52845 	 * reachable.
52846 	 */
52847 
52848 	return res;
52849 }
52850 
52851 /*
52852  *  Intern a string from str/blen, returning either an existing duk_hstring
52853  *  or adding a new one into the string table.  The input string does -not-
52854  *  need to be NUL terminated.
52855  *
52856  *  The input 'str' argument may point to a Duktape managed data area such as
52857  *  the data area of a dynamic buffer.  It's crucial to avoid any side effects
52858  *  that might affect the data area (e.g. resize the dynamic buffer, or write
52859  *  to the buffer) before the string is fully interned.
52860  */
52861 
52862 #if defined(DUK_USE_ROM_STRINGS)
52863 DUK_LOCAL duk_hstring *duk__strtab_romstring_lookup(duk_heap *heap, const duk_uint8_t *str, duk_size_t blen, duk_uint32_t strhash) {
52864 	duk_size_t lookup_hash;
52865 	duk_hstring *curr;
52866 
52867 	DUK_ASSERT(heap != NULL);
52868 	DUK_UNREF(heap);
52869 
52870 	lookup_hash = (blen << 4);
52871 	if (blen > 0) {
52872 		lookup_hash += str[0];
52873 	}
52874 	lookup_hash &= 0xff;
52875 
52876 	curr = (duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_lookup[lookup_hash]);
52877 	while (curr != NULL) {
52878 		/* Unsafe memcmp() because for zero blen, str may be NULL. */
52879 		if (strhash == DUK_HSTRING_GET_HASH(curr) &&
52880 		    blen == DUK_HSTRING_GET_BYTELEN(curr) &&
52881 		    duk_memcmp_unsafe((const void *) str, (const void *) DUK_HSTRING_GET_DATA(curr), blen) == 0) {
52882 			DUK_DDD(DUK_DDDPRINT("intern check: rom string: %!O, computed hash 0x%08lx, rom hash 0x%08lx",
52883 			                     curr, (unsigned long) strhash, (unsigned long) DUK_HSTRING_GET_HASH(curr)));
52884 			return curr;
52885 		}
52886 		curr = curr->hdr.h_next;
52887 	}
52888 
52889 	return NULL;
52890 }
52891 #endif  /* DUK_USE_ROM_STRINGS */
52892 
52893 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {
52894 	duk_uint32_t strhash;
52895 	duk_hstring *h;
52896 
52897 	DUK_DDD(DUK_DDDPRINT("intern check: heap=%p, str=%p, blen=%lu", (void *) heap, (const void *) str, (unsigned long) blen));
52898 
52899 	/* Preliminaries. */
52900 
52901 	/* XXX: maybe just require 'str != NULL' even for zero size? */
52902 	DUK_ASSERT(heap != NULL);
52903 	DUK_ASSERT(blen == 0 || str != NULL);
52904 	DUK_ASSERT(blen <= DUK_HSTRING_MAX_BYTELEN);  /* Caller is responsible for ensuring this. */
52905 	strhash = duk_heap_hashstring(heap, str, (duk_size_t) blen);
52906 
52907 	/* String table lookup. */
52908 
52909 	DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
52910 	DUK_ASSERT(heap->st_size > 0);
52911 	DUK_ASSERT(heap->st_size == heap->st_mask + 1);
52912 #if defined(DUK_USE_STRTAB_PTRCOMP)
52913 	h = DUK__HEAPPTR_DEC16(heap, heap->strtable16[strhash & heap->st_mask]);
52914 #else
52915 	h = heap->strtable[strhash & heap->st_mask];
52916 #endif
52917 	while (h != NULL) {
52918 		if (DUK_HSTRING_GET_HASH(h) == strhash &&
52919 		    DUK_HSTRING_GET_BYTELEN(h) == blen &&
52920 		    duk_memcmp_unsafe((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
52921 			/* Found existing entry. */
52922 			DUK_STATS_INC(heap, stats_strtab_intern_hit);
52923 			return h;
52924 		}
52925 		h = h->hdr.h_next;
52926 	}
52927 
52928 	/* ROM table lookup.  Because this lookup is slower, do it only after
52929 	 * RAM lookup.  This works because no ROM string is ever interned into
52930 	 * the RAM string table.
52931 	 */
52932 
52933 #if defined(DUK_USE_ROM_STRINGS)
52934 	h = duk__strtab_romstring_lookup(heap, str, blen, strhash);
52935 	if (h != NULL) {
52936 		DUK_STATS_INC(heap, stats_strtab_intern_hit);
52937 		return h;
52938 	}
52939 #endif
52940 
52941 	/* Not found in string table; insert. */
52942 
52943 	DUK_STATS_INC(heap, stats_strtab_intern_miss);
52944 	h = duk__strtable_do_intern(heap, str, blen, strhash);
52945 	return h;  /* may be NULL */
52946 }
52947 
52948 /*
52949  *  Intern a string from u32.
52950  */
52951 
52952 /* XXX: Could arrange some special handling because we know that the result
52953  * will have an arridx flag and an ASCII flag, won't need a clen check, etc.
52954  */
52955 
52956 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32(duk_heap *heap, duk_uint32_t val) {
52957 	duk_uint8_t buf[DUK__STRTAB_U32_MAX_STRLEN];
52958 	duk_uint8_t *p;
52959 
52960 	DUK_ASSERT(heap != NULL);
52961 
52962 	/* This is smaller and faster than a %lu sprintf. */
52963 	p = buf + sizeof(buf);
52964 	do {
52965 		p--;
52966 		*p = duk_lc_digits[val % 10];
52967 		val = val / 10;
52968 	} while (val != 0);  /* For val == 0, emit exactly one '0'. */
52969 	DUK_ASSERT(p >= buf);
52970 
52971 	return duk_heap_strtable_intern(heap, (const duk_uint8_t *) p, (duk_uint32_t) ((buf + sizeof(buf)) - p));
52972 }
52973 
52974 /*
52975  *  Checked convenience variants.
52976  *
52977  *  XXX: Because the main use case is for the checked variants, make them the
52978  *  main functionality and provide a safe variant separately (it is only needed
52979  *  during heap init).  The problem with that is that longjmp state and error
52980  *  creation must already be possible to throw.
52981  */
52982 
52983 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
52984 	duk_hstring *res;
52985 
52986 	DUK_ASSERT(thr != NULL);
52987 	DUK_ASSERT(thr->heap != NULL);
52988 	DUK_ASSERT(blen == 0 || str != NULL);
52989 
52990 	res = duk_heap_strtable_intern(thr->heap, str, blen);
52991 	if (DUK_UNLIKELY(res == NULL)) {
52992 		DUK_ERROR_ALLOC_FAILED(thr);
52993 		DUK_WO_NORETURN(return NULL;);
52994 	}
52995 	return res;
52996 }
52997 
52998 #if defined(DUK_USE_LITCACHE_SIZE)
52999 DUK_LOCAL duk_uint_t duk__strtable_litcache_key(const duk_uint8_t *str, duk_uint32_t blen) {
53000 	duk_uintptr_t key;
53001 
53002 	DUK_ASSERT(DUK_USE_LITCACHE_SIZE > 0);
53003 	DUK_ASSERT(DUK_IS_POWER_OF_TWO((duk_uint_t) DUK_USE_LITCACHE_SIZE));
53004 
53005 	key = (duk_uintptr_t) blen ^ (duk_uintptr_t) str;
53006 	key &= (duk_uintptr_t) (DUK_USE_LITCACHE_SIZE - 1);  /* Assumes size is power of 2. */
53007 	/* Due to masking, cast is in 32-bit range. */
53008 	DUK_ASSERT(key <= DUK_UINT_MAX);
53009 	return (duk_uint_t) key;
53010 }
53011 
53012 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_literal_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
53013 	duk_uint_t key;
53014 	duk_litcache_entry *ent;
53015 	duk_hstring *h;
53016 
53017 	/* Fast path check: literal exists in literal cache. */
53018 	key = duk__strtable_litcache_key(str, blen);
53019 	ent = thr->heap->litcache + key;
53020 	if (ent->addr == str) {
53021 		DUK_DD(DUK_DDPRINT("intern check for cached, pinned literal: str=%p, blen=%ld -> duk_hstring %!O",
53022 		                   (const void *) str, (long) blen, (duk_heaphdr *) ent->h));
53023 		DUK_ASSERT(ent->h != NULL);
53024 		DUK_ASSERT(DUK_HSTRING_HAS_PINNED_LITERAL(ent->h));
53025 		DUK_STATS_INC(thr->heap, stats_strtab_litcache_hit);
53026 		return ent->h;
53027 	}
53028 
53029 	/* Intern and update (overwrite) cache entry. */
53030 	h = duk_heap_strtable_intern_checked(thr, str, blen);
53031 	ent->addr = str;
53032 	ent->h = h;
53033 	DUK_STATS_INC(thr->heap, stats_strtab_litcache_miss);
53034 
53035 	/* Pin the duk_hstring until the next mark-and-sweep.  This means
53036 	 * litcache entries don't need to be invalidated until the next
53037 	 * mark-and-sweep as their target duk_hstring is not freed before
53038 	 * the mark-and-sweep happens.  The pin remains even if the literal
53039 	 * cache entry is overwritten, and is still useful to avoid string
53040 	 * table traffic.
53041 	 */
53042 	if (!DUK_HSTRING_HAS_PINNED_LITERAL(h)) {
53043 		DUK_DD(DUK_DDPRINT("pin duk_hstring because it is a literal: %!O", (duk_heaphdr *) h));
53044 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
53045 		DUK_HSTRING_INCREF(thr, h);
53046 		DUK_HSTRING_SET_PINNED_LITERAL(h);
53047 		DUK_STATS_INC(thr->heap, stats_strtab_litcache_pin);
53048 	}
53049 
53050 	return h;
53051 }
53052 #endif  /* DUK_USE_LITCACHE_SIZE */
53053 
53054 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val) {
53055 	duk_hstring *res;
53056 
53057 	DUK_ASSERT(thr != NULL);
53058 	DUK_ASSERT(thr->heap != NULL);
53059 
53060 	res = duk_heap_strtable_intern_u32(thr->heap, val);
53061 	if (DUK_UNLIKELY(res == NULL)) {
53062 		DUK_ERROR_ALLOC_FAILED(thr);
53063 		DUK_WO_NORETURN(return NULL;);
53064 	}
53065 	return res;
53066 }
53067 
53068 /*
53069  *  Remove (unlink) a string from the string table.
53070  *
53071  *  Just unlinks the duk_hstring, leaving link pointers as garbage.
53072  *  Caller must free the string itself.
53073  */
53074 
53075 #if defined(DUK_USE_REFERENCE_COUNTING)
53076 /* Unlink without a 'prev' pointer. */
53077 DUK_INTERNAL void duk_heap_strtable_unlink(duk_heap *heap, duk_hstring *h) {
53078 #if defined(DUK_USE_STRTAB_PTRCOMP)
53079 	duk_uint16_t *slot;
53080 #else
53081 	duk_hstring **slot;
53082 #endif
53083 	duk_hstring *other;
53084 	duk_hstring *prev;
53085 
53086 	DUK_DDD(DUK_DDDPRINT("remove: heap=%p, h=%p, blen=%lu, strhash=%lx",
53087 	                     (void *) heap, (void *) h,
53088 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_BYTELEN(h) : 0),
53089 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_HASH(h) : 0)));
53090 
53091 	DUK_ASSERT(heap != NULL);
53092 	DUK_ASSERT(h != NULL);
53093 
53094 #if defined(DUK__STRTAB_RESIZE_CHECK)
53095 	DUK_ASSERT(heap->st_count > 0);
53096 	heap->st_count--;
53097 #endif
53098 
53099 #if defined(DUK_USE_STRTAB_PTRCOMP)
53100 	slot = heap->strtable16 + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
53101 #else
53102 	slot = heap->strtable + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
53103 #endif
53104 	other = DUK__HEAPPTR_DEC16(heap, *slot);
53105 	DUK_ASSERT(other != NULL);  /* At least argument string is in the chain. */
53106 
53107 	prev = NULL;
53108 	while (other != h) {
53109 		prev = other;
53110 		other = other->hdr.h_next;
53111 		DUK_ASSERT(other != NULL);  /* We'll eventually find 'h'. */
53112 	}
53113 	if (prev != NULL) {
53114 		/* Middle of list. */
53115 		prev->hdr.h_next = h->hdr.h_next;
53116 	} else {
53117 		/* Head of list. */
53118 		*slot = DUK__HEAPPTR_ENC16(heap, h->hdr.h_next);
53119 	}
53120 
53121 	/* There's no resize check on a string free.  The next string
53122 	 * intern will do one.
53123 	 */
53124 }
53125 #endif  /* DUK_USE_REFERENCE_COUNTING */
53126 
53127 /* Unlink with a 'prev' pointer. */
53128 DUK_INTERNAL void duk_heap_strtable_unlink_prev(duk_heap *heap, duk_hstring *h, duk_hstring *prev) {
53129 #if defined(DUK_USE_STRTAB_PTRCOMP)
53130 	duk_uint16_t *slot;
53131 #else
53132 	duk_hstring **slot;
53133 #endif
53134 
53135 	DUK_DDD(DUK_DDDPRINT("remove: heap=%p, prev=%p, h=%p, blen=%lu, strhash=%lx",
53136 	                     (void *) heap, (void *) prev, (void *) h,
53137 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_BYTELEN(h) : 0),
53138 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_HASH(h) : 0)));
53139 
53140 	DUK_ASSERT(heap != NULL);
53141 	DUK_ASSERT(h != NULL);
53142 	DUK_ASSERT(prev == NULL || prev->hdr.h_next == h);
53143 
53144 #if defined(DUK__STRTAB_RESIZE_CHECK)
53145 	DUK_ASSERT(heap->st_count > 0);
53146 	heap->st_count--;
53147 #endif
53148 
53149 	if (prev != NULL) {
53150 		/* Middle of list. */
53151 		prev->hdr.h_next = h->hdr.h_next;
53152 	} else {
53153 		/* Head of list. */
53154 #if defined(DUK_USE_STRTAB_PTRCOMP)
53155 		slot = heap->strtable16 + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
53156 #else
53157 		slot = heap->strtable + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
53158 #endif
53159 		DUK_ASSERT(DUK__HEAPPTR_DEC16(heap, *slot) == h);
53160 		*slot = DUK__HEAPPTR_ENC16(heap, h->hdr.h_next);
53161 	}
53162 }
53163 
53164 /*
53165  *  Force string table resize check in mark-and-sweep.
53166  */
53167 
53168 DUK_INTERNAL void duk_heap_strtable_force_resize(duk_heap *heap) {
53169 	/* Does only one grow/shrink step if needed.  The heap->st_resizing
53170 	 * flag protects against recursive resizing.
53171 	 */
53172 
53173 	DUK_ASSERT(heap != NULL);
53174 	DUK_UNREF(heap);
53175 
53176 #if defined(DUK__STRTAB_RESIZE_CHECK)
53177 #if defined(DUK_USE_STRTAB_PTRCOMP)
53178 	if (heap->strtable16 != NULL) {
53179 #else
53180 	if (heap->strtable != NULL) {
53181 #endif
53182 		duk__strtable_resize_check(heap);
53183 	}
53184 #endif
53185 }
53186 
53187 /*
53188  *  Free strings in the string table and the string table itself.
53189  */
53190 
53191 DUK_INTERNAL void duk_heap_strtable_free(duk_heap *heap) {
53192 #if defined(DUK_USE_STRTAB_PTRCOMP)
53193 	duk_uint16_t *strtable;
53194 	duk_uint16_t *st;
53195 #else
53196 	duk_hstring **strtable;
53197 	duk_hstring **st;
53198 #endif
53199 	duk_hstring *h;
53200 
53201 	DUK_ASSERT(heap != NULL);
53202 
53203 #if defined(DUK_USE_ASSERTIONS)
53204 	duk__strtable_assert_checks(heap);
53205 #endif
53206 
53207 	/* Strtable can be NULL if heap init fails.  However, in that case
53208 	 * heap->st_size is 0, so strtable == strtable_end and we skip the
53209 	 * loop without a special check.
53210 	 */
53211 	strtable = DUK__GET_STRTABLE(heap);
53212 	st = strtable + heap->st_size;
53213 	DUK_ASSERT(strtable != NULL || heap->st_size == 0);
53214 
53215 	while (strtable != st) {
53216 		--st;
53217 		h = DUK__HEAPPTR_DEC16(heap, *st);
53218 		while (h) {
53219 			duk_hstring *h_next;
53220 			h_next = h->hdr.h_next;
53221 
53222 			/* Strings may have inner refs (extdata) in some cases. */
53223 			duk_free_hstring(heap, h);
53224 
53225 			h = h_next;
53226 		}
53227 	}
53228 
53229 	DUK_FREE(heap, strtable);
53230 }
53231 
53232 /* automatic undefs */
53233 #undef DUK__GET_STRTABLE
53234 #undef DUK__HEAPPTR_DEC16
53235 #undef DUK__HEAPPTR_ENC16
53236 #undef DUK__STRTAB_U32_MAX_STRLEN
53237 /*
53238  *  duk_heaphdr assertion helpers
53239  */
53240 
53241 /* #include duk_internal.h -> already included */
53242 
53243 #if defined(DUK_USE_ASSERTIONS)
53244 
53245 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
53246 DUK_INTERNAL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h) {
53247 	DUK_UNREF(heap);
53248 	if (h != NULL) {
53249 		duk_heaphdr *h_prev, *h_next;
53250 		h_prev = DUK_HEAPHDR_GET_PREV(heap, h);
53251 		h_next = DUK_HEAPHDR_GET_NEXT(heap, h);
53252 		DUK_ASSERT(h_prev == NULL || (DUK_HEAPHDR_GET_NEXT(heap, h_prev) == h));
53253 		DUK_ASSERT(h_next == NULL || (DUK_HEAPHDR_GET_PREV(heap, h_next) == h));
53254 	}
53255 }
53256 #else
53257 DUK_INTERNAL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h) {
53258 	DUK_UNREF(heap);
53259 	DUK_UNREF(h);
53260 }
53261 #endif
53262 
53263 DUK_INTERNAL void duk_heaphdr_assert_valid(duk_heaphdr *h) {
53264 	DUK_ASSERT(h != NULL);
53265 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
53266 }
53267 
53268 /* Assert validity of a heaphdr, including all subclasses. */
53269 DUK_INTERNAL void duk_heaphdr_assert_valid_subclassed(duk_heaphdr *h) {
53270 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
53271 	case DUK_HTYPE_OBJECT: {
53272 		duk_hobject *h_obj = (duk_hobject *) h;
53273 		DUK_HOBJECT_ASSERT_VALID(h_obj);
53274 		if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
53275 			DUK_HCOMPFUNC_ASSERT_VALID((duk_hcompfunc *) h_obj);
53276 		} else if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
53277 			DUK_HNATFUNC_ASSERT_VALID((duk_hnatfunc *) h_obj);
53278 		} else if (DUK_HOBJECT_IS_DECENV(h_obj)) {
53279 			DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) h_obj);
53280 		} else if (DUK_HOBJECT_IS_OBJENV(h_obj)) {
53281 			DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) h_obj);
53282 		} else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
53283 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
53284 			DUK_HBUFOBJ_ASSERT_VALID((duk_hbufobj *) h_obj);
53285 #endif
53286 		} else if (DUK_HOBJECT_IS_BOUNDFUNC(h_obj)) {
53287 			DUK_HBOUNDFUNC_ASSERT_VALID((duk_hboundfunc *) h_obj);
53288 		} else if (DUK_HOBJECT_IS_PROXY(h_obj)) {
53289 			DUK_HPROXY_ASSERT_VALID((duk_hproxy *) h_obj);
53290 		} else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
53291 			DUK_HTHREAD_ASSERT_VALID((duk_hthread *) h_obj);
53292 		} else {
53293 			/* Just a plain object. */
53294 			;
53295 		}
53296 		break;
53297 	}
53298 	case DUK_HTYPE_STRING: {
53299 		duk_hstring *h_str = (duk_hstring *) h;
53300 		DUK_HSTRING_ASSERT_VALID(h_str);
53301 		break;
53302 	}
53303 	case DUK_HTYPE_BUFFER: {
53304 		duk_hbuffer *h_buf = (duk_hbuffer *) h;
53305 		DUK_HBUFFER_ASSERT_VALID(h_buf);
53306 		break;
53307 	}
53308 	default: {
53309 		DUK_ASSERT(0);
53310 	}
53311 	}
53312 }
53313 
53314 #endif  /* DUK_USE_ASSERTIONS */
53315 /*
53316  *  Hobject allocation.
53317  *
53318  *  Provides primitive allocation functions for all object types (plain object,
53319  *  compiled function, native function, thread).  The object return is not yet
53320  *  in "heap allocated" list and has a refcount of zero, so caller must careful.
53321  */
53322 
53323 /* XXX: In most cases there's no need for plain allocation without pushing
53324  * to the value stack.  Maybe rework contract?
53325  */
53326 
53327 /* #include duk_internal.h -> already included */
53328 
53329 /*
53330  *  Helpers.
53331  */
53332 
53333 DUK_LOCAL void duk__init_object_parts(duk_heap *heap, duk_uint_t hobject_flags, duk_hobject *obj) {
53334 	DUK_ASSERT(obj != NULL);
53335 	/* Zeroed by caller. */
53336 
53337 	obj->hdr.h_flags = hobject_flags | DUK_HTYPE_OBJECT;
53338 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(&obj->hdr) == DUK_HTYPE_OBJECT);  /* Assume zero shift. */
53339 
53340 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53341 	DUK_HOBJECT_SET_PROTOTYPE(heap, obj, NULL);
53342 	DUK_HOBJECT_SET_PROPS(heap, obj, NULL);
53343 #endif
53344 #if defined(DUK_USE_HEAPPTR16)
53345 	/* Zero encoded pointer is required to match NULL. */
53346 	DUK_HEAPHDR_SET_NEXT(heap, &obj->hdr, NULL);
53347 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
53348 	DUK_HEAPHDR_SET_PREV(heap, &obj->hdr, NULL);
53349 #endif
53350 #endif
53351 	DUK_HEAPHDR_ASSERT_LINKS(heap, &obj->hdr);
53352 	DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &obj->hdr);
53353 
53354 	/* obj->props is intentionally left as NULL, and duk_hobject_props.c must deal
53355 	 * with this properly.  This is intentional: empty objects consume a minimum
53356 	 * amount of memory.  Further, an initial allocation might fail and cause
53357 	 * 'obj' to "leak" (require a mark-and-sweep) since it is not reachable yet.
53358 	 */
53359 }
53360 
53361 DUK_LOCAL void *duk__hobject_alloc_init(duk_hthread *thr, duk_uint_t hobject_flags, duk_size_t size) {
53362 	void *res;
53363 
53364 	res = (void *) DUK_ALLOC_CHECKED_ZEROED(thr, size);
53365 	DUK_ASSERT(res != NULL);
53366 	duk__init_object_parts(thr->heap, hobject_flags, (duk_hobject *) res);
53367 	return res;
53368 }
53369 
53370 /*
53371  *  Allocate an duk_hobject.
53372  *
53373  *  The allocated object has no allocation for properties; the caller may
53374  *  want to force a resize if a desired size is known.
53375  *
53376  *  The allocated object has zero reference count and is not reachable.
53377  *  The caller MUST make the object reachable and increase its reference
53378  *  count before invoking any operation that might require memory allocation.
53379  */
53380 
53381 DUK_INTERNAL duk_hobject *duk_hobject_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags) {
53382 	duk_hobject *res;
53383 
53384 	DUK_ASSERT(heap != NULL);
53385 
53386 	/* different memory layout, alloc size, and init */
53387 	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_COMPFUNC) == 0);
53388 	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_NATFUNC) == 0);
53389 	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_BOUNDFUNC) == 0);
53390 
53391 	res = (duk_hobject *) DUK_ALLOC_ZEROED(heap, sizeof(duk_hobject));
53392 	if (DUK_UNLIKELY(res == NULL)) {
53393 		return NULL;
53394 	}
53395 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(res));
53396 
53397 	duk__init_object_parts(heap, hobject_flags, res);
53398 
53399 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(res));
53400 	return res;
53401 }
53402 
53403 DUK_INTERNAL duk_hobject *duk_hobject_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53404 	duk_hobject *res;
53405 
53406 	res = (duk_hobject *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hobject));
53407 	return res;
53408 }
53409 
53410 DUK_INTERNAL duk_hcompfunc *duk_hcompfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53411 	duk_hcompfunc *res;
53412 
53413 	res = (duk_hcompfunc *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hcompfunc));
53414 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53415 #if defined(DUK_USE_HEAPPTR16)
53416 	/* NULL pointer is required to encode to zero, so memset is enough. */
53417 #else
53418 	res->data = NULL;
53419 	res->funcs = NULL;
53420 	res->bytecode = NULL;
53421 #endif
53422 	res->lex_env = NULL;
53423 	res->var_env = NULL;
53424 #endif
53425 
53426 	return res;
53427 }
53428 
53429 DUK_INTERNAL duk_hnatfunc *duk_hnatfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53430 	duk_hnatfunc *res;
53431 
53432 	res = (duk_hnatfunc *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hnatfunc));
53433 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53434 	res->func = NULL;
53435 #endif
53436 
53437 	return res;
53438 }
53439 
53440 DUK_INTERNAL duk_hboundfunc *duk_hboundfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
53441 	duk_hboundfunc *res;
53442 
53443 	res = (duk_hboundfunc *) DUK_ALLOC(heap, sizeof(duk_hboundfunc));
53444 	if (!res) {
53445 		return NULL;
53446 	}
53447 	duk_memzero(res, sizeof(duk_hboundfunc));
53448 
53449 	duk__init_object_parts(heap, hobject_flags, &res->obj);
53450 
53451 	DUK_TVAL_SET_UNDEFINED(&res->target);
53452 	DUK_TVAL_SET_UNDEFINED(&res->this_binding);
53453 
53454 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53455 	res->args = NULL;
53456 #endif
53457 
53458 	return res;
53459 }
53460 
53461 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
53462 DUK_INTERNAL duk_hbufobj *duk_hbufobj_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53463 	duk_hbufobj *res;
53464 
53465 	res = (duk_hbufobj *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hbufobj));
53466 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53467 	res->buf = NULL;
53468 	res->buf_prop = NULL;
53469 #endif
53470 
53471 	DUK_HBUFOBJ_ASSERT_VALID(res);
53472 	return res;
53473 }
53474 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
53475 
53476 /* Allocate a new thread.
53477  *
53478  * Leaves the built-ins array uninitialized.  The caller must either
53479  * initialize a new global context or share existing built-ins from
53480  * another thread.
53481  */
53482 DUK_INTERNAL duk_hthread *duk_hthread_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags) {
53483 	duk_hthread *res;
53484 
53485 	res = (duk_hthread *) DUK_ALLOC(heap, sizeof(duk_hthread));
53486 	if (DUK_UNLIKELY(res == NULL)) {
53487 		return NULL;
53488 	}
53489 	duk_memzero(res, sizeof(duk_hthread));
53490 
53491 	duk__init_object_parts(heap, hobject_flags, &res->obj);
53492 
53493 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53494 	res->ptr_curr_pc = NULL;
53495 	res->heap = NULL;
53496 	res->valstack = NULL;
53497 	res->valstack_end = NULL;
53498 	res->valstack_alloc_end = NULL;
53499 	res->valstack_bottom = NULL;
53500 	res->valstack_top = NULL;
53501 	res->callstack_curr = NULL;
53502 	res->resumer = NULL;
53503 	res->compile_ctx = NULL,
53504 #if defined(DUK_USE_HEAPPTR16)
53505 	res->strs16 = NULL;
53506 #else
53507 	res->strs = NULL;
53508 #endif
53509 	{
53510 		duk_small_uint_t i;
53511 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
53512 			res->builtins[i] = NULL;
53513 		}
53514 	}
53515 #endif
53516 	/* When nothing is running, API calls are in non-strict mode. */
53517 	DUK_ASSERT(res->strict == 0);
53518 
53519 	res->heap = heap;
53520 
53521 	/* XXX: Any reason not to merge duk_hthread_alloc.c here? */
53522 	return res;
53523 }
53524 
53525 DUK_INTERNAL duk_hthread *duk_hthread_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53526 	duk_hthread *res;
53527 
53528 	res = duk_hthread_alloc_unchecked(thr->heap, hobject_flags);
53529 	if (res == NULL) {
53530 		DUK_ERROR_ALLOC_FAILED(thr);
53531 		DUK_WO_NORETURN(return NULL;);
53532 	}
53533 	return res;
53534 }
53535 
53536 DUK_INTERNAL duk_harray *duk_harray_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53537 	duk_harray *res;
53538 
53539 	res = (duk_harray *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_harray));
53540 
53541 	DUK_ASSERT(res->length == 0);
53542 
53543 	return res;
53544 }
53545 
53546 DUK_INTERNAL duk_hdecenv *duk_hdecenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53547 	duk_hdecenv *res;
53548 
53549 	res = (duk_hdecenv *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hdecenv));
53550 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53551 	res->thread = NULL;
53552 	res->varmap = NULL;
53553 #endif
53554 
53555 	DUK_ASSERT(res->thread == NULL);
53556 	DUK_ASSERT(res->varmap == NULL);
53557 	DUK_ASSERT(res->regbase_byteoff == 0);
53558 
53559 	return res;
53560 }
53561 
53562 DUK_INTERNAL duk_hobjenv *duk_hobjenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53563 	duk_hobjenv *res;
53564 
53565 	res = (duk_hobjenv *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hobjenv));
53566 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53567 	res->target = NULL;
53568 #endif
53569 
53570 	DUK_ASSERT(res->target == NULL);
53571 
53572 	return res;
53573 }
53574 
53575 DUK_INTERNAL duk_hproxy *duk_hproxy_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53576 	duk_hproxy *res;
53577 
53578 	res = (duk_hproxy *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hproxy));
53579 
53580 	/* Leave ->target and ->handler uninitialized, as caller will always
53581 	 * explicitly initialize them before any side effects are possible.
53582 	 */
53583 
53584 	return res;
53585 }
53586 /*
53587  *  duk_hobject and subclass assertion helpers
53588  */
53589 
53590 /* #include duk_internal.h -> already included */
53591 
53592 #if defined(DUK_USE_ASSERTIONS)
53593 
53594 DUK_INTERNAL void duk_hobject_assert_valid(duk_hobject *h) {
53595 	DUK_ASSERT(h != NULL);
53596 	DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE(h) ||
53597 	           DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_FUNCTION);
53598 	DUK_ASSERT(!DUK_HOBJECT_IS_BUFOBJ(h) ||
53599 	           (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAYBUFFER ||
53600 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_DATAVIEW ||
53601 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_INT8ARRAY ||
53602 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT8ARRAY ||
53603 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY ||
53604 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_INT16ARRAY ||
53605 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT16ARRAY ||
53606 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_INT32ARRAY ||
53607 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT32ARRAY ||
53608 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_FLOAT32ARRAY ||
53609 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_FLOAT64ARRAY));
53610 	/* Object is an Array <=> object has exotic array behavior */
53611 	DUK_ASSERT((DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY && DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)) ||
53612 	           (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_ARRAY && !DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)));
53613 }
53614 
53615 DUK_INTERNAL void duk_harray_assert_valid(duk_harray *h) {
53616 	DUK_ASSERT(h != NULL);
53617 	DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) h));
53618 	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY((duk_hobject *) h));
53619 }
53620 
53621 DUK_INTERNAL void duk_hboundfunc_assert_valid(duk_hboundfunc *h) {
53622 	DUK_ASSERT(h != NULL);
53623 	DUK_ASSERT(DUK_HOBJECT_IS_BOUNDFUNC((duk_hobject *) h));
53624 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&h->target) ||
53625 	           (DUK_TVAL_IS_OBJECT(&h->target) &&
53626 	            DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(&h->target))));
53627 	DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&h->this_binding));
53628 	DUK_ASSERT(h->nargs == 0 || h->args != NULL);
53629 }
53630 
53631 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
53632 DUK_INTERNAL void duk_hbufobj_assert_valid(duk_hbufobj *h) {
53633 	DUK_ASSERT(h != NULL);
53634 	DUK_ASSERT(h->shift <= 3);
53635 	DUK_ASSERT(h->elem_type <= DUK_HBUFOBJ_ELEM_MAX);
53636 	DUK_ASSERT((h->shift == 0 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT8) ||
53637 	           (h->shift == 0 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT8CLAMPED) ||
53638 	           (h->shift == 0 && h->elem_type == DUK_HBUFOBJ_ELEM_INT8) ||
53639 	           (h->shift == 1 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT16) ||
53640 	           (h->shift == 1 && h->elem_type == DUK_HBUFOBJ_ELEM_INT16) ||
53641 	           (h->shift == 2 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT32) ||
53642 	           (h->shift == 2 && h->elem_type == DUK_HBUFOBJ_ELEM_INT32) ||
53643 	           (h->shift == 2 && h->elem_type == DUK_HBUFOBJ_ELEM_FLOAT32) ||
53644 	           (h->shift == 3 && h->elem_type == DUK_HBUFOBJ_ELEM_FLOAT64));
53645 	DUK_ASSERT(h->is_typedarray == 0 || h->is_typedarray == 1);
53646 	DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h));
53647 	if (h->buf == NULL) {
53648 		DUK_ASSERT(h->offset == 0);
53649 		DUK_ASSERT(h->length == 0);
53650 	} else {
53651 		/* No assertions for offset or length; in particular,
53652 		 * it's OK for length to be longer than underlying
53653 		 * buffer.  Just ensure they don't wrap when added.
53654 		 */
53655 		DUK_ASSERT(h->offset + h->length >= h->offset);
53656 	}
53657 }
53658 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
53659 
53660 DUK_INTERNAL void duk_hcompfunc_assert_valid(duk_hcompfunc *h) {
53661 	DUK_ASSERT(h != NULL);
53662 }
53663 
53664 DUK_INTERNAL void duk_hnatfunc_assert_valid(duk_hnatfunc *h) {
53665 	DUK_ASSERT(h != NULL);
53666 }
53667 
53668 DUK_INTERNAL void duk_hdecenv_assert_valid(duk_hdecenv *h) {
53669 	DUK_ASSERT(h != NULL);
53670 	DUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) h));
53671 	DUK_ASSERT(h->thread == NULL || h->varmap != NULL);
53672 }
53673 
53674 DUK_INTERNAL void duk_hobjenv_assert_valid(duk_hobjenv *h) {
53675 	DUK_ASSERT(h != NULL);
53676 	DUK_ASSERT(DUK_HOBJECT_IS_OBJENV((duk_hobject *) h));
53677 	DUK_ASSERT(h->target != NULL);
53678 	DUK_ASSERT(h->has_this == 0 || h->has_this == 1);
53679 }
53680 
53681 DUK_INTERNAL void duk_hproxy_assert_valid(duk_hproxy *h) {
53682 	DUK_ASSERT(h != NULL);
53683 	DUK_ASSERT(h->target != NULL);
53684 	DUK_ASSERT(h->handler != NULL);
53685 	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((duk_hobject *) h));
53686 }
53687 
53688 DUK_INTERNAL void duk_hthread_assert_valid(duk_hthread *thr) {
53689 	DUK_ASSERT(thr != NULL);
53690 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) thr) == DUK_HTYPE_OBJECT);
53691 	DUK_ASSERT(DUK_HOBJECT_IS_THREAD((duk_hobject *) thr));
53692 	DUK_ASSERT(thr->unused1 == 0);
53693 	DUK_ASSERT(thr->unused2 == 0);
53694 }
53695 
53696 DUK_INTERNAL void duk_ctx_assert_valid(duk_hthread *thr) {
53697 	DUK_ASSERT(thr != NULL);
53698 	DUK_HTHREAD_ASSERT_VALID(thr);
53699 	DUK_ASSERT(thr->valstack != NULL);
53700 	DUK_ASSERT(thr->valstack_bottom != NULL);
53701 	DUK_ASSERT(thr->valstack_top != NULL);
53702 	DUK_ASSERT(thr->valstack_end != NULL);
53703 	DUK_ASSERT(thr->valstack_alloc_end != NULL);
53704 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack);
53705 	DUK_ASSERT(thr->valstack_end >= thr->valstack);
53706 	DUK_ASSERT(thr->valstack_top >= thr->valstack);
53707 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
53708 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
53709 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
53710 }
53711 
53712 #endif  /* DUK_USE_ASSERTIONS */
53713 /*
53714  *  Object enumeration support.
53715  *
53716  *  Creates an internal enumeration state object to be used e.g. with for-in
53717  *  enumeration.  The state object contains a snapshot of target object keys
53718  *  and internal control state for enumeration.  Enumerator flags allow caller
53719  *  to e.g. request internal/non-enumerable properties, and to enumerate only
53720  *  "own" properties.
53721  *
53722  *  Also creates the result value for e.g. Object.keys() based on the same
53723  *  internal structure.
53724  *
53725  *  This snapshot-based enumeration approach is used to simplify enumeration:
53726  *  non-snapshot-based approaches are difficult to reconcile with mutating
53727  *  the enumeration target, running multiple long-lived enumerators at the
53728  *  same time, garbage collection details, etc.  The downside is that the
53729  *  enumerator object is memory inefficient especially for iterating arrays.
53730  */
53731 
53732 /* #include duk_internal.h -> already included */
53733 
53734 /* XXX: identify enumeration target with an object index (not top of stack) */
53735 
53736 /* First enumerated key index in enumerator object, must match exactly the
53737  * number of control properties inserted to the enumerator.
53738  */
53739 #define DUK__ENUM_START_INDEX  2
53740 
53741 /* Current implementation suffices for ES2015 for now because there's no symbol
53742  * sorting, so commented out for now.
53743  */
53744 
53745 /*
53746  *  Helper to sort enumeration keys using a callback for pairwise duk_hstring
53747  *  comparisons.  The keys are in the enumeration object entry part, starting
53748  *  from DUK__ENUM_START_INDEX, and the entry part is dense.  Entry part values
53749  *  are all "true", e.g. "1" -> true, "3" -> true, "foo" -> true, "2" -> true,
53750  *  so it suffices to just switch keys without switching values.
53751  *
53752  *  ES2015 [[OwnPropertyKeys]] enumeration order for ordinary objects:
53753  *  (1) array indices in ascending order,
53754  *  (2) non-array-index keys in insertion order, and
53755  *  (3) symbols in insertion order.
53756  *  http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys.
53757  *
53758  *  This rule is applied to "own properties" at each inheritance level;
53759  *  non-duplicate parent keys always follow child keys.  For example,
53760  *  an inherited array index will enumerate -after- a symbol in the
53761  *  child.
53762  *
53763  *  Insertion sort is used because (1) it's simple and compact, (2) works
53764  *  in-place, (3) minimizes operations if data is already nearly sorted,
53765  *  (4) doesn't reorder elements considered equal.
53766  *  http://en.wikipedia.org/wiki/Insertion_sort
53767  */
53768 
53769 /* Sort key, must hold array indices, "not array index" marker, and one more
53770  * higher value for symbols.
53771  */
53772 #if !defined(DUK_USE_SYMBOL_BUILTIN)
53773 typedef duk_uint32_t duk__sort_key_t;
53774 #elif defined(DUK_USE_64BIT_OPS)
53775 typedef duk_uint64_t duk__sort_key_t;
53776 #else
53777 typedef duk_double_t duk__sort_key_t;
53778 #endif
53779 
53780 /* Get sort key for a duk_hstring. */
53781 DUK_LOCAL duk__sort_key_t duk__hstring_sort_key(duk_hstring *x) {
53782 	duk__sort_key_t val;
53783 
53784 	/* For array indices [0,0xfffffffe] use the array index as is.
53785 	 * For strings, use 0xffffffff, the marker 'arridx' already in
53786 	 * duk_hstring.  For symbols, any value above 0xffffffff works,
53787 	 * as long as it is the same for all symbols; currently just add
53788 	 * the masked flag field into the arridx temporary.
53789 	 */
53790 	DUK_ASSERT(x != NULL);
53791 	DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(x) || DUK_HSTRING_GET_ARRIDX_FAST(x) == DUK_HSTRING_NO_ARRAY_INDEX);
53792 
53793 	val = (duk__sort_key_t) DUK_HSTRING_GET_ARRIDX_FAST(x);
53794 
53795 #if defined(DUK_USE_SYMBOL_BUILTIN)
53796 	val = val + (duk__sort_key_t) (DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) x) & DUK_HSTRING_FLAG_SYMBOL);
53797 #endif
53798 
53799 	return (duk__sort_key_t) val;
53800 }
53801 
53802 /* Insert element 'b' after element 'a'? */
53803 DUK_LOCAL duk_bool_t duk__sort_compare_es6(duk_hstring *a, duk_hstring *b, duk__sort_key_t val_b) {
53804 	duk__sort_key_t val_a;
53805 
53806 	DUK_ASSERT(a != NULL);
53807 	DUK_ASSERT(b != NULL);
53808 	DUK_UNREF(b);  /* Not actually needed now, val_b suffices. */
53809 
53810 	val_a = duk__hstring_sort_key(a);
53811 
53812 	if (val_a > val_b) {
53813 		return 0;
53814 	} else {
53815 		return 1;
53816 	}
53817 }
53818 
53819 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) {
53820 	duk_hstring **keys;
53821 	duk_int_fast32_t idx;
53822 
53823 	DUK_ASSERT(h_obj != NULL);
53824 	DUK_ASSERT(idx_start >= DUK__ENUM_START_INDEX);
53825 	DUK_ASSERT(idx_end >= idx_start);
53826 	DUK_UNREF(thr);
53827 
53828 	if (idx_end <= idx_start + 1) {
53829 		return;  /* Zero or one element(s). */
53830 	}
53831 
53832 	keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, h_obj);
53833 
53834 	for (idx = idx_start + 1; idx < idx_end; idx++) {
53835 		duk_hstring *h_curr;
53836 		duk_int_fast32_t idx_insert;
53837 		duk__sort_key_t val_curr;
53838 
53839 		h_curr = keys[idx];
53840 		DUK_ASSERT(h_curr != NULL);
53841 
53842 		/* Scan backwards for insertion place.  This works very well
53843 		 * when the elements are nearly in order which is the common
53844 		 * (and optimized for) case.
53845 		 */
53846 
53847 		val_curr = duk__hstring_sort_key(h_curr);  /* Remains same during scanning. */
53848 		for (idx_insert = idx - 1; idx_insert >= idx_start; idx_insert--) {
53849 			duk_hstring *h_insert;
53850 			h_insert = keys[idx_insert];
53851 			DUK_ASSERT(h_insert != NULL);
53852 
53853 			if (duk__sort_compare_es6(h_insert, h_curr, val_curr)) {
53854 				break;
53855 			}
53856 		}
53857 		/* If we're out of indices, idx_insert == idx_start - 1 and idx_insert++
53858 		 * brings us back to idx_start.
53859 		 */
53860 		idx_insert++;
53861 		DUK_ASSERT(idx_insert >= 0 && idx_insert <= idx);
53862 
53863 		/*        .-- p_insert   .-- p_curr
53864 		 *        v              v
53865 		 *  | ... | insert | ... | curr
53866 		 */
53867 
53868 		/* This could also done when the keys are in order, i.e.
53869 		 * idx_insert == idx.  The result would be an unnecessary
53870 		 * memmove() but we use an explicit check because the keys
53871 		 * are very often in order already.
53872 		 */
53873 		if (idx != idx_insert) {
53874 			duk_memmove((void *) (keys + idx_insert + 1),
53875 			            (const void *) (keys + idx_insert),
53876 			            ((size_t) (idx - idx_insert) * sizeof(duk_hstring *)));
53877 			keys[idx_insert] = h_curr;
53878 		}
53879 	}
53880 }
53881 
53882 /*
53883  *  Create an internal enumerator object E, which has its keys ordered
53884  *  to match desired enumeration ordering.  Also initialize internal control
53885  *  properties for enumeration.
53886  *
53887  *  Note: if an array was used to hold enumeration keys instead, an array
53888  *  scan would be needed to eliminate duplicates found in the prototype chain.
53889  */
53890 
53891 DUK_LOCAL void duk__add_enum_key(duk_hthread *thr, duk_hstring *k) {
53892 	/* 'k' may be unreachable on entry so must push without any
53893 	 * potential for GC.
53894 	 */
53895 	duk_push_hstring(thr, k);
53896 	duk_push_true(thr);
53897 	duk_put_prop(thr, -3);
53898 }
53899 
53900 DUK_LOCAL void duk__add_enum_key_stridx(duk_hthread *thr, duk_small_uint_t stridx) {
53901 	duk__add_enum_key(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
53902 }
53903 
53904 DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint_t enum_flags) {
53905 	duk_hobject *enum_target;
53906 	duk_hobject *curr;
53907 	duk_hobject *res;
53908 #if defined(DUK_USE_ES6_PROXY)
53909 	duk_hobject *h_proxy_target;
53910 	duk_hobject *h_proxy_handler;
53911 	duk_hobject *h_trap_result;
53912 #endif
53913 	duk_uint_fast32_t i, len;  /* used for array, stack, and entry indices */
53914 	duk_uint_fast32_t sort_start_index;
53915 
53916 	DUK_ASSERT(thr != NULL);
53917 
53918 	enum_target = duk_require_hobject(thr, -1);
53919 	DUK_ASSERT(enum_target != NULL);
53920 
53921 	duk_push_bare_object(thr);
53922 	res = duk_known_hobject(thr, -1);
53923 
53924 	/* [enum_target res] */
53925 
53926 	/* Target must be stored so that we can recheck whether or not
53927 	 * keys still exist when we enumerate.  This is not done if the
53928 	 * enumeration result comes from a proxy trap as there is no
53929 	 * real object to check against.
53930 	 */
53931 	duk_push_hobject(thr, enum_target);
53932 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_TARGET);  /* Target is bare, plain put OK. */
53933 
53934 	/* Initialize index so that we skip internal control keys. */
53935 	duk_push_int(thr, DUK__ENUM_START_INDEX);
53936 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_NEXT);  /* Target is bare, plain put OK. */
53937 
53938 	/*
53939 	 *  Proxy object handling
53940 	 */
53941 
53942 #if defined(DUK_USE_ES6_PROXY)
53943 	if (DUK_LIKELY((enum_flags & DUK_ENUM_NO_PROXY_BEHAVIOR) != 0)) {
53944 		goto skip_proxy;
53945 	}
53946 	if (DUK_LIKELY(!duk_hobject_proxy_check(enum_target,
53947 	                                        &h_proxy_target,
53948 	                                        &h_proxy_handler))) {
53949 		goto skip_proxy;
53950 	}
53951 
53952 	/* XXX: share code with Object.keys() Proxy handling */
53953 
53954 	/* In ES2015 for-in invoked the "enumerate" trap; in ES2016 "enumerate"
53955 	 * has been obsoleted and "ownKeys" is used instead.
53956 	 */
53957 	DUK_DDD(DUK_DDDPRINT("proxy enumeration"));
53958 	duk_push_hobject(thr, h_proxy_handler);
53959 	if (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_OWN_KEYS)) {
53960 		/* No need to replace the 'enum_target' value in stack, only the
53961 		 * enum_target reference.  This also ensures that the original
53962 		 * enum target is reachable, which keeps the proxy and the proxy
53963 		 * target reachable.  We do need to replace the internal _Target.
53964 		 */
53965 		DUK_DDD(DUK_DDDPRINT("no ownKeys trap, enumerate proxy target instead"));
53966 		DUK_DDD(DUK_DDDPRINT("h_proxy_target=%!O", (duk_heaphdr *) h_proxy_target));
53967 		enum_target = h_proxy_target;
53968 
53969 		duk_push_hobject(thr, enum_target);  /* -> [ ... enum_target res handler undefined target ] */
53970 		duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_INT_TARGET);  /* Target is bare, plain put OK. */
53971 
53972 		duk_pop_2(thr);  /* -> [ ... enum_target res ] */
53973 		goto skip_proxy;
53974 	}
53975 
53976 	/* [ ... enum_target res handler trap ] */
53977 	duk_insert(thr, -2);
53978 	duk_push_hobject(thr, h_proxy_target);    /* -> [ ... enum_target res trap handler target ] */
53979 	duk_call_method(thr, 1 /*nargs*/);        /* -> [ ... enum_target res trap_result ] */
53980 	h_trap_result = duk_require_hobject(thr, -1);
53981 	DUK_UNREF(h_trap_result);
53982 
53983 	duk_proxy_ownkeys_postprocess(thr, h_proxy_target, enum_flags);
53984 	/* -> [ ... enum_target res trap_result keys_array ] */
53985 
53986 	/* Copy cleaned up trap result keys into the enumerator object. */
53987 	/* XXX: result is a dense array; could make use of that. */
53988 	DUK_ASSERT(duk_is_array(thr, -1));
53989 	len = (duk_uint_fast32_t) duk_get_length(thr, -1);
53990 	for (i = 0; i < len; i++) {
53991 		(void) duk_get_prop_index(thr, -1, (duk_uarridx_t) i);
53992 		DUK_ASSERT(duk_is_string(thr, -1));  /* postprocess cleaned up */
53993 		/* [ ... enum_target res trap_result keys_array val ] */
53994 		duk_push_true(thr);
53995 		/* [ ... enum_target res trap_result keys_array val true ] */
53996 		duk_put_prop(thr, -5);
53997 	}
53998 	/* [ ... enum_target res trap_result keys_array ] */
53999 	duk_pop_2(thr);
54000 	duk_remove_m2(thr);
54001 
54002 	/* [ ... res ] */
54003 
54004 	/* The internal _Target property is kept pointing to the original
54005 	 * enumeration target (the proxy object), so that the enumerator
54006 	 * 'next' operation can read property values if so requested.  The
54007 	 * fact that the _Target is a proxy disables key existence check
54008 	 * during enumeration.
54009 	 */
54010 	DUK_DDD(DUK_DDDPRINT("proxy enumeration, final res: %!O", (duk_heaphdr *) res));
54011 	goto compact_and_return;
54012 
54013  skip_proxy:
54014 #endif  /* DUK_USE_ES6_PROXY */
54015 
54016 	curr = enum_target;
54017 	sort_start_index = DUK__ENUM_START_INDEX;
54018 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(res) == DUK__ENUM_START_INDEX);
54019 	while (curr) {
54020 		duk_uint_fast32_t sort_end_index;
54021 #if !defined(DUK_USE_PREFER_SIZE)
54022 		duk_bool_t need_sort = 0;
54023 #endif
54024 		duk_bool_t cond;
54025 
54026 		/* Enumeration proceeds by inheritance level.  Virtual
54027 		 * properties need to be handled specially, followed by
54028 		 * array part, and finally entry part.
54029 		 *
54030 		 * If there are array index keys in the entry part or any
54031 		 * other risk of the ES2015 [[OwnPropertyKeys]] order being
54032 		 * violated, need_sort is set and an explicit ES2015 sort is
54033 		 * done for the inheritance level.
54034 		 */
54035 
54036 		/* XXX: inheriting from proxy */
54037 
54038 		/*
54039 		 *  Virtual properties.
54040 		 *
54041 		 *  String and buffer indices are virtual and always enumerable,
54042 		 *  'length' is virtual and non-enumerable.  Array and arguments
54043 		 *  object props have special behavior but are concrete.
54044 		 *
54045 		 *  String and buffer objects don't have an array part so as long
54046 		 *  as virtual array index keys are enumerated first, we don't
54047 		 *  need to set need_sort.
54048 		 */
54049 
54050 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
54051 		cond = DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr) || DUK_HOBJECT_IS_BUFOBJ(curr);
54052 #else
54053 		cond = DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr);
54054 #endif
54055 		cond = cond && !(enum_flags & DUK_ENUM_EXCLUDE_STRINGS);
54056 		if (cond) {
54057 			duk_bool_t have_length = 1;
54058 
54059 			/* String and buffer enumeration behavior is identical now,
54060 			 * so use shared handler.
54061 			 */
54062 			if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr)) {
54063 				duk_hstring *h_val;
54064 				h_val = duk_hobject_get_internal_value_string(thr->heap, curr);
54065 				DUK_ASSERT(h_val != NULL);  /* string objects must not created without internal value */
54066 				len = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_val);
54067 			}
54068 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
54069 			else {
54070 				duk_hbufobj *h_bufobj;
54071 				DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ(curr));
54072 				h_bufobj = (duk_hbufobj *) curr;
54073 
54074 				if (h_bufobj == NULL || !h_bufobj->is_typedarray) {
54075 					/* Zero length seems like a good behavior for neutered buffers.
54076 					 * ArrayBuffer (non-view) and DataView don't have index properties
54077 					 * or .length property.
54078 					 */
54079 					len = 0;
54080 					have_length = 0;
54081 				} else {
54082 					/* There's intentionally no check for
54083 					 * current underlying buffer length.
54084 					 */
54085 					len = (duk_uint_fast32_t) (h_bufobj->length >> h_bufobj->shift);
54086 				}
54087 			}
54088 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
54089 
54090 			for (i = 0; i < len; i++) {
54091 				duk_hstring *k;
54092 
54093 				/* This is a bit fragile: the string is not
54094 				 * reachable until it is pushed by the helper.
54095 				 */
54096 				k = duk_heap_strtable_intern_u32_checked(thr, (duk_uint32_t) i);
54097 				DUK_ASSERT(k);
54098 
54099 				duk__add_enum_key(thr, k);
54100 
54101 				/* [enum_target res] */
54102 			}
54103 
54104 			/* 'length' and other virtual properties are not
54105 			 * enumerable, but are included if non-enumerable
54106 			 * properties are requested.
54107 			 */
54108 
54109 			if (have_length && (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
54110 				duk__add_enum_key_stridx(thr, DUK_STRIDX_LENGTH);
54111 			}
54112 		}
54113 
54114 		/*
54115 		 *  Array part
54116 		 */
54117 
54118 		cond = !(enum_flags & DUK_ENUM_EXCLUDE_STRINGS);
54119 		if (cond) {
54120 			for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(curr); i++) {
54121 				duk_hstring *k;
54122 				duk_tval *tv;
54123 
54124 				tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, curr, i);
54125 				if (DUK_TVAL_IS_UNUSED(tv)) {
54126 					continue;
54127 				}
54128 				k = duk_heap_strtable_intern_u32_checked(thr, (duk_uint32_t) i);  /* Fragile reachability. */
54129 				DUK_ASSERT(k);
54130 
54131 				duk__add_enum_key(thr, k);
54132 
54133 				/* [enum_target res] */
54134 			}
54135 
54136 			if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(curr)) {
54137 				/* Array .length comes after numeric indices. */
54138 				if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
54139 					duk__add_enum_key_stridx(thr, DUK_STRIDX_LENGTH);
54140 				}
54141 			}
54142 		}
54143 
54144 		/*
54145 		 *  Entries part
54146 		 */
54147 
54148 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(curr); i++) {
54149 			duk_hstring *k;
54150 
54151 			k = DUK_HOBJECT_E_GET_KEY(thr->heap, curr, i);
54152 			if (!k) {
54153 				continue;
54154 			}
54155 			if (!(enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) &&
54156 			    !DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(thr->heap, curr, i)) {
54157 				continue;
54158 			}
54159 			if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(k))) {
54160 				if (!(enum_flags & DUK_ENUM_INCLUDE_HIDDEN) &&
54161 				    DUK_HSTRING_HAS_HIDDEN(k)) {
54162 					continue;
54163 				}
54164 				if (!(enum_flags & DUK_ENUM_INCLUDE_SYMBOLS)) {
54165 					continue;
54166 				}
54167 #if !defined(DUK_USE_PREFER_SIZE)
54168 				need_sort = 1;
54169 #endif
54170 			} else {
54171 				DUK_ASSERT(!DUK_HSTRING_HAS_HIDDEN(k));  /* would also have symbol flag */
54172 				if (enum_flags & DUK_ENUM_EXCLUDE_STRINGS) {
54173 					continue;
54174 				}
54175 			}
54176 			if (DUK_HSTRING_HAS_ARRIDX(k)) {
54177 				/* This in currently only possible if the
54178 				 * object has no array part: the array part
54179 				 * is exhaustive when it is present.
54180 				 */
54181 #if !defined(DUK_USE_PREFER_SIZE)
54182 				need_sort = 1;
54183 #endif
54184 			} else {
54185 				if (enum_flags & DUK_ENUM_ARRAY_INDICES_ONLY) {
54186 					continue;
54187 				}
54188 			}
54189 
54190 			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, curr, i) ||
54191 			           !DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE_PTR(thr->heap, curr, i)->v));
54192 
54193 			duk__add_enum_key(thr, k);
54194 
54195 			/* [enum_target res] */
54196 		}
54197 
54198 		/* Sort enumerated keys according to ES2015 requirements for
54199 		 * the "inheritance level" just processed.  This is far from
54200 		 * optimal, ES2015 semantics could be achieved more efficiently
54201 		 * by handling array index string keys (and symbol keys)
54202 		 * specially above in effect doing the sort inline.
54203 		 *
54204 		 * Skip the sort if array index sorting is requested because
54205 		 * we must consider all keys, also inherited, so an explicit
54206 		 * sort is done for the whole result after we're done with the
54207 		 * prototype chain.
54208 		 *
54209 		 * Also skip the sort if need_sort == 0, i.e. we know for
54210 		 * certain that the enumerated order is already correct.
54211 		 */
54212 		sort_end_index = DUK_HOBJECT_GET_ENEXT(res);
54213 
54214 		if (!(enum_flags & DUK_ENUM_SORT_ARRAY_INDICES)) {
54215 #if defined(DUK_USE_PREFER_SIZE)
54216 			duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) sort_start_index, (duk_int_fast32_t) sort_end_index);
54217 #else
54218 			if (need_sort) {
54219 				DUK_DDD(DUK_DDDPRINT("need to sort"));
54220 				duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) sort_start_index, (duk_int_fast32_t) sort_end_index);
54221 			} else {
54222 				DUK_DDD(DUK_DDDPRINT("no need to sort"));
54223 			}
54224 #endif
54225 		}
54226 
54227 		sort_start_index = sort_end_index;
54228 
54229 		if (enum_flags & DUK_ENUM_OWN_PROPERTIES_ONLY) {
54230 			break;
54231 		}
54232 
54233 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
54234 	}
54235 
54236 	/* [enum_target res] */
54237 
54238 	duk_remove_m2(thr);
54239 
54240 	/* [res] */
54241 
54242 	if (enum_flags & DUK_ENUM_SORT_ARRAY_INDICES) {
54243 		/* Some E5/E5.1 algorithms require that array indices are iterated
54244 		 * in a strictly ascending order.  This is the case for e.g.
54245 		 * Array.prototype.forEach() and JSON.stringify() PropertyList
54246 		 * handling.  The caller can request an explicit sort in these
54247 		 * cases.
54248 		 */
54249 
54250 		/* Sort to ES2015 order which works for pure array incides but
54251 		 * also for mixed keys.
54252 		 */
54253 		duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) DUK__ENUM_START_INDEX, (duk_int_fast32_t) DUK_HOBJECT_GET_ENEXT(res));
54254 	}
54255 
54256 #if defined(DUK_USE_ES6_PROXY)
54257  compact_and_return:
54258 #endif
54259 	/* compact; no need to seal because object is internal */
54260 	duk_hobject_compact_props(thr, res);
54261 
54262 	DUK_DDD(DUK_DDDPRINT("created enumerator object: %!iT", (duk_tval *) duk_get_tval(thr, -1)));
54263 }
54264 
54265 /*
54266  *  Returns non-zero if a key and/or value was enumerated, and:
54267  *
54268  *   [enum] -> [key]        (get_value == 0)
54269  *   [enum] -> [key value]  (get_value == 1)
54270  *
54271  *  Returns zero without pushing anything on the stack otherwise.
54272  */
54273 DUK_INTERNAL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t get_value) {
54274 	duk_hobject *e;
54275 	duk_hobject *enum_target;
54276 	duk_hstring *res = NULL;
54277 	duk_uint_fast32_t idx;
54278 	duk_bool_t check_existence;
54279 
54280 	DUK_ASSERT(thr != NULL);
54281 
54282 	/* [... enum] */
54283 
54284 	e = duk_require_hobject(thr, -1);
54285 
54286 	/* XXX use get tval ptr, more efficient */
54287 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_NEXT);
54288 	idx = (duk_uint_fast32_t) duk_require_uint(thr, -1);
54289 	duk_pop(thr);
54290 	DUK_DDD(DUK_DDDPRINT("enumeration: index is: %ld", (long) idx));
54291 
54292 	/* Enumeration keys are checked against the enumeration target (to see
54293 	 * that they still exist).  In the proxy enumeration case _Target will
54294 	 * be the proxy, and checking key existence against the proxy is not
54295 	 * required (or sensible, as the keys may be fully virtual).
54296 	 */
54297 	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_TARGET);
54298 	enum_target = duk_require_hobject(thr, -1);
54299 	DUK_ASSERT(enum_target != NULL);
54300 #if defined(DUK_USE_ES6_PROXY)
54301 	check_existence = (!DUK_HOBJECT_IS_PROXY(enum_target));
54302 #else
54303 	check_existence = 1;
54304 #endif
54305 	duk_pop(thr);  /* still reachable */
54306 
54307 	DUK_DDD(DUK_DDDPRINT("getting next enum value, enum_target=%!iO, enumerator=%!iT",
54308 	                     (duk_heaphdr *) enum_target, (duk_tval *) duk_get_tval(thr, -1)));
54309 
54310 	/* no array part */
54311 	for (;;) {
54312 		duk_hstring *k;
54313 
54314 		if (idx >= DUK_HOBJECT_GET_ENEXT(e)) {
54315 			DUK_DDD(DUK_DDDPRINT("enumeration: ran out of elements"));
54316 			break;
54317 		}
54318 
54319 		/* we know these because enum objects are internally created */
54320 		k = DUK_HOBJECT_E_GET_KEY(thr->heap, e, idx);
54321 		DUK_ASSERT(k != NULL);
54322 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, e, idx));
54323 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE(thr->heap, e, idx).v));
54324 
54325 		idx++;
54326 
54327 		/* recheck that the property still exists */
54328 		if (check_existence && !duk_hobject_hasprop_raw(thr, enum_target, k)) {
54329 			DUK_DDD(DUK_DDDPRINT("property deleted during enumeration, skip"));
54330 			continue;
54331 		}
54332 
54333 		DUK_DDD(DUK_DDDPRINT("enumeration: found element, key: %!O", (duk_heaphdr *) k));
54334 		res = k;
54335 		break;
54336 	}
54337 
54338 	DUK_DDD(DUK_DDDPRINT("enumeration: updating next index to %ld", (long) idx));
54339 
54340 	duk_push_u32(thr, (duk_uint32_t) idx);
54341 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_NEXT);
54342 
54343 	/* [... enum] */
54344 
54345 	if (res) {
54346 		duk_push_hstring(thr, res);
54347 		if (get_value) {
54348 			duk_push_hobject(thr, enum_target);
54349 			duk_dup_m2(thr);       /* -> [... enum key enum_target key] */
54350 			duk_get_prop(thr, -2); /* -> [... enum key enum_target val] */
54351 			duk_remove_m2(thr);    /* -> [... enum key val] */
54352 			duk_remove(thr, -3);   /* -> [... key val] */
54353 		} else {
54354 			duk_remove_m2(thr);    /* -> [... key] */
54355 		}
54356 		return 1;
54357 	} else {
54358 		duk_pop(thr);  /* -> [...] */
54359 		return 0;
54360 	}
54361 }
54362 
54363 /*
54364  *  Get enumerated keys in an ECMAScript array.  Matches Object.keys() behavior
54365  *  described in E5 Section 15.2.3.14.
54366  */
54367 
54368 DUK_INTERNAL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_small_uint_t enum_flags) {
54369 	duk_hobject *e;
54370 	duk_hstring **keys;
54371 	duk_tval *tv;
54372 	duk_uint_fast32_t count;
54373 
54374 	DUK_ASSERT(thr != NULL);
54375 	DUK_ASSERT(duk_get_hobject(thr, -1) != NULL);
54376 
54377 	/* Create a temporary enumerator to get the (non-duplicated) key list;
54378 	 * the enumerator state is initialized without being needed, but that
54379 	 * has little impact.
54380 	 */
54381 
54382 	duk_hobject_enumerator_create(thr, enum_flags);
54383 	e = duk_known_hobject(thr, -1);
54384 
54385 	/* [enum_target enum res] */
54386 
54387 	/* Create dense result array to exact size. */
54388 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(e) >= DUK__ENUM_START_INDEX);
54389 	count = (duk_uint32_t) (DUK_HOBJECT_GET_ENEXT(e) - DUK__ENUM_START_INDEX);
54390 
54391 	/* XXX: uninit would be OK */
54392 	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count);
54393 	DUK_ASSERT(count == 0 || tv != NULL);
54394 	DUK_ASSERT(!duk_is_bare_object(thr, -1));
54395 
54396 	/* Fill result array, no side effects. */
54397 
54398 	keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, e);
54399 	keys += DUK__ENUM_START_INDEX;
54400 
54401 	while (count-- > 0) {
54402 		duk_hstring *k;
54403 
54404 		k = *keys++;
54405 		DUK_ASSERT(k != NULL);  /* enumerator must have no keys deleted */
54406 
54407 		DUK_TVAL_SET_STRING(tv, k);
54408 		tv++;
54409 		DUK_HSTRING_INCREF(thr, k);
54410 	}
54411 
54412 	/* [enum_target enum res] */
54413 	duk_remove_m2(thr);
54414 
54415 	/* [enum_target res] */
54416 
54417 	return 1;  /* return 1 to allow callers to tail call */
54418 }
54419 
54420 /* automatic undefs */
54421 #undef DUK__ENUM_START_INDEX
54422 /*
54423  *  Misc support functions
54424  */
54425 
54426 /* #include duk_internal.h -> already included */
54427 
54428 DUK_INTERNAL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p, duk_bool_t ignore_loop) {
54429 	duk_uint_t sanity;
54430 
54431 	DUK_ASSERT(thr != NULL);
54432 
54433 	/* False if the object is NULL or the prototype 'p' is NULL.
54434 	 * In particular, false if both are NULL (don't compare equal).
54435 	 */
54436 	if (h == NULL || p == NULL) {
54437 		return 0;
54438 	}
54439 
54440 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
54441 	do {
54442 		if (h == p) {
54443 			return 1;
54444 		}
54445 
54446 		if (sanity-- == 0) {
54447 			if (ignore_loop) {
54448 				break;
54449 			} else {
54450 				DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
54451 				DUK_WO_NORETURN(return 0;);
54452 			}
54453 		}
54454 		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
54455 	} while (h);
54456 
54457 	return 0;
54458 }
54459 
54460 DUK_INTERNAL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p) {
54461 #if defined(DUK_USE_REFERENCE_COUNTING)
54462 	duk_hobject *tmp;
54463 
54464 	DUK_ASSERT(h);
54465 	tmp = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
54466 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
54467 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, p);  /* avoid problems if p == h->prototype */
54468 	DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
54469 #else
54470 	DUK_ASSERT(h);
54471 	DUK_UNREF(thr);
54472 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
54473 #endif
54474 }
54475 /*
54476  *  Helpers for creating and querying pc2line debug data, which
54477  *  converts a bytecode program counter to a source line number.
54478  *
54479  *  The run-time pc2line data is bit-packed, and documented in:
54480  *
54481  *    doc/function-objects.rst
54482  */
54483 
54484 /* #include duk_internal.h -> already included */
54485 
54486 #if defined(DUK_USE_PC2LINE)
54487 
54488 /* Generate pc2line data for an instruction sequence, leaving a buffer on stack top. */
54489 DUK_INTERNAL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length) {
54490 	duk_hbuffer_dynamic *h_buf;
54491 	duk_bitencoder_ctx be_ctx_alloc;
54492 	duk_bitencoder_ctx *be_ctx = &be_ctx_alloc;
54493 	duk_uint32_t *hdr;
54494 	duk_size_t new_size;
54495 	duk_uint_fast32_t num_header_entries;
54496 	duk_uint_fast32_t curr_offset;
54497 	duk_int_fast32_t curr_line, next_line, diff_line;
54498 	duk_uint_fast32_t curr_pc;
54499 	duk_uint_fast32_t hdr_index;
54500 
54501 	DUK_ASSERT(length <= DUK_COMPILER_MAX_BYTECODE_LENGTH);
54502 
54503 	num_header_entries = (length + DUK_PC2LINE_SKIP - 1) / DUK_PC2LINE_SKIP;
54504 	curr_offset = (duk_uint_fast32_t) (sizeof(duk_uint32_t) + num_header_entries * sizeof(duk_uint32_t) * 2);
54505 
54506 	duk_push_dynamic_buffer(thr, (duk_size_t) curr_offset);
54507 	h_buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, -1);
54508 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buf) && !DUK_HBUFFER_HAS_EXTERNAL(h_buf));
54509 
54510 	hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
54511 	DUK_ASSERT(hdr != NULL);
54512 	hdr[0] = (duk_uint32_t) length;  /* valid pc range is [0, length[ */
54513 
54514 	curr_pc = 0U;
54515 	while (curr_pc < length) {
54516 		new_size = (duk_size_t) (curr_offset + DUK_PC2LINE_MAX_DIFF_LENGTH);
54517 		duk_hbuffer_resize(thr, h_buf, new_size);
54518 
54519 		hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
54520 		DUK_ASSERT(hdr != NULL);
54521 		DUK_ASSERT(curr_pc < length);
54522 		hdr_index = 1 + (curr_pc / DUK_PC2LINE_SKIP) * 2;
54523 		curr_line = (duk_int_fast32_t) instrs[curr_pc].line;
54524 		hdr[hdr_index + 0] = (duk_uint32_t) curr_line;
54525 		hdr[hdr_index + 1] = (duk_uint32_t) curr_offset;
54526 
54527 #if 0
54528 		DUK_DDD(DUK_DDDPRINT("hdr[%ld]: pc=%ld line=%ld offset=%ld",
54529 		                     (long) (curr_pc / DUK_PC2LINE_SKIP),
54530 		                     (long) curr_pc,
54531 		                     (long) hdr[hdr_index + 0],
54532 		                     (long) hdr[hdr_index + 1]));
54533 #endif
54534 
54535 		duk_memzero(be_ctx, sizeof(*be_ctx));
54536 		be_ctx->data = ((duk_uint8_t *) hdr) + curr_offset;
54537 		be_ctx->length = (duk_size_t) DUK_PC2LINE_MAX_DIFF_LENGTH;
54538 
54539 		for (;;) {
54540 			curr_pc++;
54541 			if ( ((curr_pc % DUK_PC2LINE_SKIP) == 0) ||  /* end of diff run */
54542 			     (curr_pc >= length) ) {                 /* end of bytecode */
54543 				break;
54544 			}
54545 			DUK_ASSERT(curr_pc < length);
54546 			next_line = (duk_int32_t) instrs[curr_pc].line;
54547 			diff_line = next_line - curr_line;
54548 
54549 #if 0
54550 			DUK_DDD(DUK_DDDPRINT("curr_line=%ld, next_line=%ld -> diff_line=%ld",
54551 			                     (long) curr_line, (long) next_line, (long) diff_line));
54552 #endif
54553 
54554 			if (diff_line == 0) {
54555 				/* 0 */
54556 				duk_be_encode(be_ctx, 0, 1);
54557 			} else if (diff_line >= 1 && diff_line <= 4) {
54558 				/* 1 0 <2 bits> */
54559 				duk_be_encode(be_ctx, (duk_uint32_t) ((0x02 << 2) + (diff_line - 1)), 4);
54560 			} else if (diff_line >= -0x80 && diff_line <= 0x7f) {
54561 				/* 1 1 0 <8 bits> */
54562 				DUK_ASSERT(diff_line + 0x80 >= 0 && diff_line + 0x80 <= 0xff);
54563 				duk_be_encode(be_ctx, (duk_uint32_t) ((0x06 << 8) + (diff_line + 0x80)), 11);
54564 			} else {
54565 				/* 1 1 1 <32 bits>
54566 				 * Encode in two parts to avoid bitencode 24-bit limitation
54567 				 */
54568 				duk_be_encode(be_ctx, (duk_uint32_t) ((0x07 << 16) + ((next_line >> 16) & 0xffff)), 19);
54569 				duk_be_encode(be_ctx, (duk_uint32_t) (next_line & 0xffff), 16);
54570 			}
54571 
54572 			curr_line = next_line;
54573 		}
54574 
54575 		duk_be_finish(be_ctx);
54576 		DUK_ASSERT(!be_ctx->truncated);
54577 
54578 		/* be_ctx->offset == length of encoded bitstream */
54579 		curr_offset += (duk_uint_fast32_t) be_ctx->offset;
54580 	}
54581 
54582 	/* compact */
54583 	new_size = (duk_size_t) curr_offset;
54584 	duk_hbuffer_resize(thr, h_buf, new_size);
54585 
54586 	(void) duk_to_fixed_buffer(thr, -1, NULL);
54587 
54588 	DUK_DDD(DUK_DDDPRINT("final pc2line data: pc_limit=%ld, length=%ld, %lf bits/opcode --> %!ixT",
54589 	                     (long) length, (long) new_size, (double) new_size * 8.0 / (double) length,
54590 	                     (duk_tval *) duk_get_tval(thr, -1)));
54591 }
54592 
54593 /* PC is unsigned.  If caller does PC arithmetic and gets a negative result,
54594  * it will map to a large PC which is out of bounds and causes a zero to be
54595  * returned.
54596  */
54597 DUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk_hbuffer_fixed *buf, duk_uint_fast32_t pc) {
54598 	duk_bitdecoder_ctx bd_ctx_alloc;
54599 	duk_bitdecoder_ctx *bd_ctx = &bd_ctx_alloc;
54600 	duk_uint32_t *hdr;
54601 	duk_uint_fast32_t start_offset;
54602 	duk_uint_fast32_t pc_limit;
54603 	duk_uint_fast32_t hdr_index;
54604 	duk_uint_fast32_t pc_base;
54605 	duk_uint_fast32_t n;
54606 	duk_uint_fast32_t curr_line;
54607 
54608 	DUK_ASSERT(buf != NULL);
54609 	DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) buf) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) buf));
54610 	DUK_UNREF(thr);
54611 
54612 	/*
54613 	 *  Use the index in the header to find the right starting point
54614 	 */
54615 
54616 	hdr_index = pc / DUK_PC2LINE_SKIP;
54617 	pc_base = hdr_index * DUK_PC2LINE_SKIP;
54618 	n = pc - pc_base;
54619 
54620 	if (DUK_HBUFFER_FIXED_GET_SIZE(buf) <= sizeof(duk_uint32_t)) {
54621 		DUK_DD(DUK_DDPRINT("pc2line lookup failed: buffer is smaller than minimal header"));
54622 		goto pc2line_error;
54623 	}
54624 
54625 	hdr = (duk_uint32_t *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, buf);
54626 	pc_limit = hdr[0];
54627 	if (pc >= pc_limit) {
54628 		/* Note: pc is unsigned and cannot be negative */
54629 		DUK_DD(DUK_DDPRINT("pc2line lookup failed: pc out of bounds (pc=%ld, limit=%ld)",
54630 		                   (long) pc, (long) pc_limit));
54631 		goto pc2line_error;
54632 	}
54633 
54634 	curr_line = hdr[1 + hdr_index * 2];
54635 	start_offset = hdr[1 + hdr_index * 2 + 1];
54636 	if ((duk_size_t) start_offset > DUK_HBUFFER_FIXED_GET_SIZE(buf)) {
54637 		DUK_DD(DUK_DDPRINT("pc2line lookup failed: start_offset out of bounds (start_offset=%ld, buffer_size=%ld)",
54638 		                   (long) start_offset, (long) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) buf)));
54639 		goto pc2line_error;
54640 	}
54641 
54642 	/*
54643 	 *  Iterate the bitstream (line diffs) until PC is reached
54644 	 */
54645 
54646 	duk_memzero(bd_ctx, sizeof(*bd_ctx));
54647 	bd_ctx->data = ((duk_uint8_t *) hdr) + start_offset;
54648 	bd_ctx->length = (duk_size_t) (DUK_HBUFFER_FIXED_GET_SIZE(buf) - start_offset);
54649 
54650 #if 0
54651 	DUK_DDD(DUK_DDDPRINT("pc2line lookup: pc=%ld -> hdr_index=%ld, pc_base=%ld, n=%ld, start_offset=%ld",
54652 	                     (long) pc, (long) hdr_index, (long) pc_base, (long) n, (long) start_offset));
54653 #endif
54654 
54655 	while (n > 0) {
54656 #if 0
54657 		DUK_DDD(DUK_DDDPRINT("lookup: n=%ld, curr_line=%ld", (long) n, (long) curr_line));
54658 #endif
54659 
54660 		if (duk_bd_decode_flag(bd_ctx)) {
54661 			if (duk_bd_decode_flag(bd_ctx)) {
54662 				if (duk_bd_decode_flag(bd_ctx)) {
54663 					/* 1 1 1 <32 bits> */
54664 					duk_uint_fast32_t t;
54665 					t = duk_bd_decode(bd_ctx, 16);  /* workaround: max nbits = 24 now */
54666 					t = (t << 16) + duk_bd_decode(bd_ctx, 16);
54667 					curr_line = t;
54668 				} else {
54669 					/* 1 1 0 <8 bits> */
54670 					duk_uint_fast32_t t;
54671 					t = duk_bd_decode(bd_ctx, 8);
54672 					curr_line = curr_line + t - 0x80;
54673 				}
54674 			} else {
54675 				/* 1 0 <2 bits> */
54676 				duk_uint_fast32_t t;
54677 				t = duk_bd_decode(bd_ctx, 2);
54678 				curr_line = curr_line + t + 1;
54679 			}
54680 		} else {
54681 			/* 0: no change */
54682 		}
54683 
54684 		n--;
54685 	}
54686 
54687 	DUK_DDD(DUK_DDDPRINT("pc2line lookup result: pc %ld -> line %ld", (long) pc, (long) curr_line));
54688 	return curr_line;
54689 
54690  pc2line_error:
54691 	DUK_D(DUK_DPRINT("pc2line conversion failed for pc=%ld", (long) pc));
54692 	return 0;
54693 }
54694 
54695 DUK_INTERNAL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_idx_t idx_func, duk_uint_fast32_t pc) {
54696 	duk_hbuffer_fixed *pc2line;
54697 	duk_uint_fast32_t line;
54698 
54699 	/* XXX: now that pc2line is used by the debugger quite heavily in
54700 	 * checked execution, this should be optimized to avoid value stack
54701 	 * and perhaps also implement some form of pc2line caching (see
54702 	 * future work in debugger.rst).
54703 	 */
54704 
54705 	duk_xget_owndataprop_stridx_short(thr, idx_func, DUK_STRIDX_INT_PC2LINE);
54706 	pc2line = (duk_hbuffer_fixed *) (void *) duk_get_hbuffer(thr, -1);
54707 	if (pc2line != NULL) {
54708 		DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) pc2line) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) pc2line));
54709 		line = duk__hobject_pc2line_query_raw(thr, pc2line, (duk_uint_fast32_t) pc);
54710 	} else {
54711 		line = 0;
54712 	}
54713 	duk_pop(thr);
54714 
54715 	return line;
54716 }
54717 
54718 #endif  /* DUK_USE_PC2LINE */
54719 /*
54720  *  duk_hobject property access functionality.
54721  *
54722  *  This is very central functionality for size, performance, and compliance.
54723  *  It is also rather intricate; see hobject-algorithms.rst for discussion on
54724  *  the algorithms and memory-management.rst for discussion on refcounts and
54725  *  side effect issues.
54726  *
54727  *  Notes:
54728  *
54729  *    - It might be tempting to assert "refcount nonzero" for objects
54730  *      being operated on, but that's not always correct: objects with
54731  *      a zero refcount may be operated on by the refcount implementation
54732  *      (finalization) for instance.  Hence, no refcount assertions are made.
54733  *
54734  *    - Many operations (memory allocation, identifier operations, etc)
54735  *      may cause arbitrary side effects (e.g. through GC and finalization).
54736  *      These side effects may invalidate duk_tval pointers which point to
54737  *      areas subject to reallocation (like value stack).  Heap objects
54738  *      themselves have stable pointers.  Holding heap object pointers or
54739  *      duk_tval copies is not problematic with respect to side effects;
54740  *      care must be taken when holding and using argument duk_tval pointers.
54741  *
54742  *    - If a finalizer is executed, it may operate on the the same object
54743  *      we're currently dealing with.  For instance, the finalizer might
54744  *      delete a certain property which has already been looked up and
54745  *      confirmed to exist.  Ideally finalizers would be disabled if GC
54746  *      happens during property access.  At the moment property table realloc
54747  *      disables finalizers, and all DECREFs may cause arbitrary changes so
54748  *      handle DECREF carefully.
54749  *
54750  *    - The order of operations for a DECREF matters.  When DECREF is executed,
54751  *      the entire object graph must be consistent; note that a refzero may
54752  *      lead to a mark-and-sweep through a refcount finalizer.  Use NORZ macros
54753  *      and an explicit DUK_REFZERO_CHECK_xxx() if achieving correct order is hard.
54754  */
54755 
54756 /*
54757  *  XXX: array indices are mostly typed as duk_uint32_t here; duk_uarridx_t
54758  *  might be more appropriate.
54759  */
54760 
54761 /* #include duk_internal.h -> already included */
54762 
54763 /*
54764  *  Local defines
54765  */
54766 
54767 #define DUK__NO_ARRAY_INDEX             DUK_HSTRING_NO_ARRAY_INDEX
54768 
54769 /* Marker values for hash part. */
54770 #define DUK__HASH_UNUSED                DUK_HOBJECT_HASHIDX_UNUSED
54771 #define DUK__HASH_DELETED               DUK_HOBJECT_HASHIDX_DELETED
54772 
54773 /* Valstack space that suffices for all local calls, excluding any recursion
54774  * into ECMAScript or Duktape/C calls (Proxy, getters, etc).
54775  */
54776 #define DUK__VALSTACK_SPACE             10
54777 
54778 /* Valstack space allocated especially for proxy lookup which does a
54779  * recursive property lookup.
54780  */
54781 #define DUK__VALSTACK_PROXY_LOOKUP      20
54782 
54783 /*
54784  *  Local prototypes
54785  */
54786 
54787 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);
54788 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);
54789 DUK_LOCAL_DECL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc);
54790 
54791 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);
54792 DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj);
54793 
54794 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);
54795 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);
54796 
54797 DUK_LOCAL_DECL void duk__abandon_array_part(duk_hthread *thr, duk_hobject *obj);
54798 DUK_LOCAL_DECL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx);
54799 
54800 /*
54801  *  Misc helpers
54802  */
54803 
54804 /* Convert a duk_tval number (caller checks) to a 32-bit index.  Returns
54805  * DUK__NO_ARRAY_INDEX if the number is not whole or not a valid array
54806  * index.
54807  */
54808 /* XXX: for fastints, could use a variant which assumes a double duk_tval
54809  * (and doesn't need to check for fastint again).
54810  */
54811 DUK_LOCAL duk_uint32_t duk__tval_number_to_arr_idx(duk_tval *tv) {
54812 	duk_double_t dbl;
54813 	duk_uint32_t idx;
54814 
54815 	DUK_ASSERT(tv != NULL);
54816 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
54817 
54818 	/* -0 is accepted here as index 0 because ToString(-0) == "0" which is
54819 	 * in canonical form and thus an array index.
54820 	 */
54821 	dbl = DUK_TVAL_GET_NUMBER(tv);
54822 	idx = (duk_uint32_t) dbl;
54823 	if ((duk_double_t) idx == dbl) {
54824 	        /* Is whole and within 32 bit range.  If the value happens to be 0xFFFFFFFF,
54825 		 * it's not a valid array index but will then match DUK__NO_ARRAY_INDEX.
54826 		 */
54827 		return idx;
54828 	}
54829 	return DUK__NO_ARRAY_INDEX;
54830 }
54831 
54832 #if defined(DUK_USE_FASTINT)
54833 /* Convert a duk_tval fastint (caller checks) to a 32-bit index. */
54834 DUK_LOCAL duk_uint32_t duk__tval_fastint_to_arr_idx(duk_tval *tv) {
54835 	duk_int64_t t;
54836 
54837 	DUK_ASSERT(tv != NULL);
54838 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
54839 
54840 	t = DUK_TVAL_GET_FASTINT(tv);
54841 	if (((duk_uint64_t) t & ~DUK_U64_CONSTANT(0xffffffff)) != 0) {
54842 		/* Catches >0x100000000 and negative values. */
54843 		return DUK__NO_ARRAY_INDEX;
54844 	}
54845 
54846 	/* If the value happens to be 0xFFFFFFFF, it's not a valid array index
54847 	 * but will then match DUK__NO_ARRAY_INDEX.
54848 	 */
54849 	return (duk_uint32_t) t;
54850 }
54851 #endif  /* DUK_USE_FASTINT */
54852 
54853 /* Convert a duk_tval on the value stack (in a trusted index we don't validate)
54854  * to a string or symbol using ES2015 ToPropertyKey():
54855  * http://www.ecma-international.org/ecma-262/6.0/#sec-topropertykey.
54856  *
54857  * Also check if it's a valid array index and return that (or DUK__NO_ARRAY_INDEX
54858  * if not).
54859  */
54860 DUK_LOCAL duk_uint32_t duk__to_property_key(duk_hthread *thr, duk_idx_t idx, duk_hstring **out_h) {
54861 	duk_uint32_t arr_idx;
54862 	duk_hstring *h;
54863 	duk_tval *tv_dst;
54864 
54865 	DUK_ASSERT(thr != NULL);
54866 	DUK_ASSERT(out_h != NULL);
54867 	DUK_ASSERT(duk_is_valid_index(thr, idx));
54868 	DUK_ASSERT(idx < 0);
54869 
54870 	/* XXX: The revised ES2015 ToPropertyKey() handling (ES5.1 was just
54871 	 * ToString()) involves a ToPrimitive(), a symbol check, and finally
54872 	 * a ToString().  Figure out the best way to have a good fast path
54873 	 * but still be compliant and share code.
54874 	 */
54875 
54876 	tv_dst = DUK_GET_TVAL_NEGIDX(thr, idx);  /* intentionally unvalidated */
54877 	if (DUK_TVAL_IS_STRING(tv_dst)) {
54878 		/* Most important path: strings and plain symbols are used as
54879 		 * is.  For symbols the array index check below is unnecessary
54880 		 * (they're never valid array indices) but checking that the
54881 		 * string is a symbol would make the plain string path slower
54882 		 * unnecessarily.
54883 		 */
54884 		h = DUK_TVAL_GET_STRING(tv_dst);
54885 	} else {
54886 		h = duk_to_property_key_hstring(thr, idx);
54887 	}
54888 	DUK_ASSERT(h != NULL);
54889 	*out_h = h;
54890 
54891 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(h);
54892 	return arr_idx;
54893 }
54894 
54895 DUK_LOCAL duk_uint32_t duk__push_tval_to_property_key(duk_hthread *thr, duk_tval *tv_key, duk_hstring **out_h) {
54896 	duk_push_tval(thr, tv_key);  /* XXX: could use an unsafe push here */
54897 	return duk__to_property_key(thr, -1, out_h);
54898 }
54899 
54900 /* String is an own (virtual) property of a plain buffer. */
54901 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) {
54902 	DUK_UNREF(thr);
54903 
54904 	/* Virtual index properties.  Checking explicitly for
54905 	 * 'arr_idx != DUK__NO_ARRAY_INDEX' is not necessary
54906 	 * because DUK__NO_ARRAY_INDEXi is always larger than
54907 	 * maximum allowed buffer size.
54908 	 */
54909 	DUK_ASSERT(DUK__NO_ARRAY_INDEX >= DUK_HBUFFER_GET_SIZE(buf));
54910 	if (arr_idx < DUK_HBUFFER_GET_SIZE(buf)) {
54911 		return 1;
54912 	}
54913 
54914 	/* Other virtual properties. */
54915 	return (key == DUK_HTHREAD_STRING_LENGTH(thr));
54916 }
54917 
54918 /*
54919  *  Helpers for managing property storage size
54920  */
54921 
54922 /* Get default hash part size for a certain entry part size. */
54923 #if defined(DUK_USE_HOBJECT_HASH_PART)
54924 DUK_LOCAL duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size) {
54925 	DUK_ASSERT(e_size <= DUK_HOBJECT_MAX_PROPERTIES);
54926 
54927 	if (e_size >= DUK_USE_HOBJECT_HASH_PROP_LIMIT) {
54928 		duk_uint32_t res;
54929 		duk_uint32_t tmp;
54930 
54931 		/* Hash size should be 2^N where N is chosen so that 2^N is
54932 		 * larger than e_size.  Extra shifting is used to ensure hash
54933 		 * is relatively sparse.
54934 		 */
54935 		tmp = e_size;
54936 		res = 2;  /* Result will be 2 ** (N + 1). */
54937 		while (tmp >= 0x40) {
54938 			tmp >>= 6;
54939 			res <<= 6;
54940 		}
54941 		while (tmp != 0) {
54942 			tmp >>= 1;
54943 			res <<= 1;
54944 		}
54945 		DUK_ASSERT((DUK_HOBJECT_MAX_PROPERTIES << 2U) > DUK_HOBJECT_MAX_PROPERTIES);  /* Won't wrap, even shifted by 2. */
54946 		DUK_ASSERT(res > e_size);
54947 		return res;
54948 	} else {
54949 		return 0;
54950 	}
54951 }
54952 #endif  /* USE_PROP_HASH_PART */
54953 
54954 /* Get minimum entry part growth for a certain size. */
54955 DUK_LOCAL duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size) {
54956 	duk_uint32_t res;
54957 
54958 	res = (e_size + DUK_USE_HOBJECT_ENTRY_MINGROW_ADD) / DUK_USE_HOBJECT_ENTRY_MINGROW_DIVISOR;
54959 	DUK_ASSERT(res >= 1);  /* important for callers */
54960 	return res;
54961 }
54962 
54963 /* Get minimum array part growth for a certain size. */
54964 DUK_LOCAL duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size) {
54965 	duk_uint32_t res;
54966 
54967 	res = (a_size + DUK_USE_HOBJECT_ARRAY_MINGROW_ADD) / DUK_USE_HOBJECT_ARRAY_MINGROW_DIVISOR;
54968 	DUK_ASSERT(res >= 1);  /* important for callers */
54969 	return res;
54970 }
54971 
54972 /* Count actually used entry part entries (non-NULL keys). */
54973 DUK_LOCAL duk_uint32_t duk__count_used_e_keys(duk_hthread *thr, duk_hobject *obj) {
54974 	duk_uint_fast32_t i;
54975 	duk_uint_fast32_t n = 0;
54976 	duk_hstring **e;
54977 
54978 	DUK_ASSERT(obj != NULL);
54979 	DUK_UNREF(thr);
54980 
54981 	e = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, obj);
54982 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
54983 		if (*e++) {
54984 			n++;
54985 		}
54986 	}
54987 	return (duk_uint32_t) n;
54988 }
54989 
54990 /* Count actually used array part entries and array minimum size.
54991  * NOTE: 'out_min_size' can be computed much faster by starting from the
54992  * end and breaking out early when finding first used entry, but this is
54993  * not needed now.
54994  */
54995 DUK_LOCAL void duk__compute_a_stats(duk_hthread *thr, duk_hobject *obj, duk_uint32_t *out_used, duk_uint32_t *out_min_size) {
54996 	duk_uint_fast32_t i;
54997 	duk_uint_fast32_t used = 0;
54998 	duk_uint_fast32_t highest_idx = (duk_uint_fast32_t) -1;  /* see below */
54999 	duk_tval *a;
55000 
55001 	DUK_ASSERT(obj != NULL);
55002 	DUK_ASSERT(out_used != NULL);
55003 	DUK_ASSERT(out_min_size != NULL);
55004 	DUK_UNREF(thr);
55005 
55006 	a = DUK_HOBJECT_A_GET_BASE(thr->heap, obj);
55007 	for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
55008 		duk_tval *tv = a++;
55009 		if (!DUK_TVAL_IS_UNUSED(tv)) {
55010 			used++;
55011 			highest_idx = i;
55012 		}
55013 	}
55014 
55015 	/* Initial value for highest_idx is -1 coerced to unsigned.  This
55016 	 * is a bit odd, but (highest_idx + 1) will then wrap to 0 below
55017 	 * for out_min_size as intended.
55018 	 */
55019 
55020 	*out_used = (duk_uint32_t) used;
55021 	*out_min_size = (duk_uint32_t) (highest_idx + 1);  /* 0 if no used entries */
55022 }
55023 
55024 /* Check array density and indicate whether or not the array part should be abandoned. */
55025 DUK_LOCAL duk_bool_t duk__abandon_array_density_check(duk_uint32_t a_used, duk_uint32_t a_size) {
55026 	/*
55027 	 *  Array abandon check; abandon if:
55028 	 *
55029 	 *    new_used / new_size < limit
55030 	 *    new_used < limit * new_size        || limit is 3 bits fixed point
55031 	 *    new_used < limit' / 8 * new_size   || *8
55032 	 *    8*new_used < limit' * new_size     || :8
55033 	 *    new_used < limit' * (new_size / 8)
55034 	 *
55035 	 *  Here, new_used = a_used, new_size = a_size.
55036 	 *
55037 	 *  Note: some callers use approximate values for a_used and/or a_size
55038 	 *  (e.g. dropping a '+1' term).  This doesn't affect the usefulness
55039 	 *  of the check, but may confuse debugging.
55040 	 */
55041 
55042 	return (a_used < DUK_USE_HOBJECT_ARRAY_ABANDON_LIMIT * (a_size >> 3));
55043 }
55044 
55045 /* Fast check for extending array: check whether or not a slow density check is required. */
55046 DUK_LOCAL duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, duk_uint32_t old_size) {
55047 	/*
55048 	 *  In a fast check we assume old_size equals old_used (i.e., existing
55049 	 *  array is fully dense).
55050 	 *
55051 	 *  Slow check if:
55052 	 *
55053 	 *    (new_size - old_size) / old_size > limit
55054 	 *    new_size - old_size > limit * old_size
55055 	 *    new_size > (1 + limit) * old_size        || limit' is 3 bits fixed point
55056 	 *    new_size > (1 + (limit' / 8)) * old_size || * 8
55057 	 *    8 * new_size > (8 + limit') * old_size   || : 8
55058 	 *    new_size > (8 + limit') * (old_size / 8)
55059 	 *    new_size > limit'' * (old_size / 8)      || limit'' = 9 -> max 25% increase
55060 	 *    arr_idx + 1 > limit'' * (old_size / 8)
55061 	 *
55062 	 *  This check doesn't work well for small values, so old_size is rounded
55063 	 *  up for the check (and the '+ 1' of arr_idx can be ignored in practice):
55064 	 *
55065 	 *    arr_idx > limit'' * ((old_size + 7) / 8)
55066 	 */
55067 
55068 	return (arr_idx > DUK_USE_HOBJECT_ARRAY_FAST_RESIZE_LIMIT * ((old_size + 7) >> 3));
55069 }
55070 
55071 DUK_LOCAL duk_bool_t duk__abandon_array_check(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj) {
55072 	duk_uint32_t min_size;
55073 	duk_uint32_t old_used;
55074 	duk_uint32_t old_size;
55075 
55076 	if (!duk__abandon_array_slow_check_required(arr_idx, DUK_HOBJECT_GET_ASIZE(obj))) {
55077 		DUK_DDD(DUK_DDDPRINT("=> fast resize is OK"));
55078 		return 0;
55079 	}
55080 
55081 	duk__compute_a_stats(thr, obj, &old_used, &old_size);
55082 
55083 	DUK_DDD(DUK_DDDPRINT("abandon check, array stats: old_used=%ld, old_size=%ld, arr_idx=%ld",
55084 	                     (long) old_used, (long) old_size, (long) arr_idx));
55085 
55086 	min_size = arr_idx + 1;
55087 #if defined(DUK_USE_OBJSIZES16)
55088 	if (min_size > DUK_UINT16_MAX) {
55089 		goto do_abandon;
55090 	}
55091 #endif
55092 	DUK_UNREF(min_size);
55093 
55094 	/* Note: intentionally use approximations to shave a few instructions:
55095 	 *   a_used = old_used  (accurate: old_used + 1)
55096 	 *   a_size = arr_idx   (accurate: arr_idx + 1)
55097 	 */
55098 	if (duk__abandon_array_density_check(old_used, arr_idx)) {
55099 		DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
55100 		                   "decided to abandon array part (would become too sparse)"));
55101 
55102 		/* Abandoning requires a props allocation resize and
55103 		 * 'rechecks' the valstack, invalidating any existing
55104 		 * valstack value pointers.
55105 		 */
55106 		goto do_abandon;
55107 	}
55108 
55109 	DUK_DDD(DUK_DDDPRINT("=> decided to keep array part"));
55110 	return 0;
55111 
55112  do_abandon:
55113 	duk__abandon_array_part(thr, obj);
55114 	DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
55115 	return 1;
55116 }
55117 
55118 DUK_LOCAL duk_tval *duk__obtain_arridx_slot_slowpath(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj) {
55119 	/*
55120 	 *  Array needs to grow, but we don't want it becoming too sparse.
55121 	 *  If it were to become sparse, abandon array part, moving all
55122 	 *  array entries into the entries part (for good).
55123 	 *
55124 	 *  Since we don't keep track of actual density (used vs. size) of
55125 	 *  the array part, we need to estimate somehow.  The check is made
55126 	 *  in two parts:
55127 	 *
55128 	 *    - Check whether the resize need is small compared to the
55129 	 *      current size (relatively); if so, resize without further
55130 	 *      checking (essentially we assume that the original part is
55131 	 *      "dense" so that the result would be dense enough).
55132 	 *
55133 	 *    - Otherwise, compute the resize using an actual density
55134 	 *      measurement based on counting the used array entries.
55135 	 */
55136 
55137 	DUK_DDD(DUK_DDDPRINT("write to new array requires array resize, decide whether to do a "
55138 	                     "fast resize without abandon check (arr_idx=%ld, old_size=%ld)",
55139 	                     (long) arr_idx, (long) DUK_HOBJECT_GET_ASIZE(obj)));
55140 
55141 	if (DUK_UNLIKELY(duk__abandon_array_check(thr, arr_idx, obj) != 0)) {
55142 		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
55143 		return NULL;
55144 	}
55145 
55146 	DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
55147 	                   "decided to extend current allocation"));
55148 
55149 	/* In principle it's possible to run out of memory extending the
55150 	 * array but with the allocation going through if we were to abandon
55151 	 * the array part and try again.  In practice this should be rare
55152 	 * because abandoned arrays have a higher per-entry footprint.
55153 	 */
55154 
55155 	duk__grow_props_for_array_item(thr, obj, arr_idx);
55156 
55157 	DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(obj));
55158 	DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
55159 	return DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
55160 }
55161 
55162 DUK_LOCAL DUK_INLINE duk_tval *duk__obtain_arridx_slot(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj) {
55163 	if (DUK_LIKELY(arr_idx < DUK_HOBJECT_GET_ASIZE(obj))) {
55164 		return DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
55165 	} else {
55166 		return duk__obtain_arridx_slot_slowpath(thr, arr_idx, obj);
55167 	}
55168 }
55169 
55170 /*
55171  *  Proxy helpers
55172  */
55173 
55174 #if defined(DUK_USE_ES6_PROXY)
55175 DUK_INTERNAL duk_bool_t duk_hobject_proxy_check(duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler) {
55176 	duk_hproxy *h_proxy;
55177 
55178 	DUK_ASSERT(obj != NULL);
55179 	DUK_ASSERT(out_target != NULL);
55180 	DUK_ASSERT(out_handler != NULL);
55181 
55182 	/* Caller doesn't need to check exotic proxy behavior (but does so for
55183 	 * some fast paths).
55184 	 */
55185 	if (DUK_LIKELY(!DUK_HOBJECT_IS_PROXY(obj))) {
55186 		return 0;
55187 	}
55188 	h_proxy = (duk_hproxy *) obj;
55189 	DUK_HPROXY_ASSERT_VALID(h_proxy);
55190 
55191 	DUK_ASSERT(h_proxy->handler != NULL);
55192 	DUK_ASSERT(h_proxy->target != NULL);
55193 	*out_handler = h_proxy->handler;
55194 	*out_target = h_proxy->target;
55195 
55196 	return 1;
55197 }
55198 #endif  /* DUK_USE_ES6_PROXY */
55199 
55200 /* Get Proxy target object.  If the argument is not a Proxy, return it as is.
55201  * If a Proxy is revoked, an error is thrown.
55202  */
55203 #if defined(DUK_USE_ES6_PROXY)
55204 DUK_INTERNAL duk_hobject *duk_hobject_resolve_proxy_target(duk_hobject *obj) {
55205 	DUK_ASSERT(obj != NULL);
55206 
55207 	/* Resolve Proxy targets until Proxy chain ends.  No explicit check for
55208 	 * a Proxy loop: user code cannot create such a loop (it would only be
55209 	 * possible by editing duk_hproxy references directly).
55210 	 */
55211 
55212 	while (DUK_HOBJECT_IS_PROXY(obj)) {
55213 		duk_hproxy *h_proxy;
55214 
55215 		h_proxy = (duk_hproxy *) obj;
55216 		DUK_HPROXY_ASSERT_VALID(h_proxy);
55217 		obj = h_proxy->target;
55218 		DUK_ASSERT(obj != NULL);
55219 	}
55220 
55221 	DUK_ASSERT(obj != NULL);
55222 	return obj;
55223 }
55224 #endif  /* DUK_USE_ES6_PROXY */
55225 
55226 #if defined(DUK_USE_ES6_PROXY)
55227 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) {
55228 	duk_hobject *h_handler;
55229 
55230 	DUK_ASSERT(thr != NULL);
55231 	DUK_ASSERT(obj != NULL);
55232 	DUK_ASSERT(tv_key != NULL);
55233 	DUK_ASSERT(out_target != NULL);
55234 
55235 	if (!duk_hobject_proxy_check(obj, out_target, &h_handler)) {
55236 		return 0;
55237 	}
55238 	DUK_ASSERT(*out_target != NULL);
55239 	DUK_ASSERT(h_handler != NULL);
55240 
55241 	/* XXX: At the moment Duktape accesses internal keys like _Finalizer using a
55242 	 * normal property set/get which would allow a proxy handler to interfere with
55243 	 * such behavior and to get access to internal key strings.  This is not a problem
55244 	 * as such because internal key strings can be created in other ways too (e.g.
55245 	 * through buffers).  The best fix is to change Duktape internal lookups to
55246 	 * skip proxy behavior.  Until that, internal property accesses bypass the
55247 	 * proxy and are applied to the target (as if the handler did not exist).
55248 	 * This has some side effects, see test-bi-proxy-internal-keys.js.
55249 	 */
55250 
55251 	if (DUK_TVAL_IS_STRING(tv_key)) {
55252 		duk_hstring *h_key = (duk_hstring *) DUK_TVAL_GET_STRING(tv_key);
55253 		DUK_ASSERT(h_key != NULL);
55254 		if (DUK_HSTRING_HAS_HIDDEN(h_key)) {
55255 			/* Symbol accesses must go through proxy lookup in ES2015.
55256 			 * Hidden symbols behave like Duktape 1.x internal keys
55257 			 * and currently won't.
55258 			 */
55259 			DUK_DDD(DUK_DDDPRINT("hidden key, skip proxy handler and apply to target"));
55260 			return 0;
55261 		}
55262 	}
55263 
55264 	/* The handler is looked up with a normal property lookup; it may be an
55265 	 * accessor or the handler object itself may be a proxy object.  If the
55266 	 * handler is a proxy, we need to extend the valstack as we make a
55267 	 * recursive proxy check without a function call in between (in fact
55268 	 * there is no limit to the potential recursion here).
55269 	 *
55270 	 * (For sanity, proxy creation rejects another proxy object as either
55271 	 * the handler or the target at the moment so recursive proxy cases
55272 	 * are not realized now.)
55273 	 */
55274 
55275 	/* XXX: C recursion limit if proxies are allowed as handler/target values */
55276 
55277 	duk_require_stack(thr, DUK__VALSTACK_PROXY_LOOKUP);
55278 	duk_push_hobject(thr, h_handler);
55279 	if (duk_get_prop_stridx_short(thr, -1, stridx_trap)) {
55280 		/* -> [ ... handler trap ] */
55281 		duk_insert(thr, -2);  /* -> [ ... trap handler ] */
55282 
55283 		/* stack prepped for func call: [ ... trap handler ] */
55284 		return 1;
55285 	} else {
55286 		duk_pop_2_unsafe(thr);
55287 		return 0;
55288 	}
55289 }
55290 #endif  /* DUK_USE_ES6_PROXY */
55291 
55292 /*
55293  *  Reallocate property allocation, moving properties to the new allocation.
55294  *
55295  *  Includes key compaction, rehashing, and can also optionally abandon
55296  *  the array part, 'migrating' array entries into the beginning of the
55297  *  new entry part.
55298  *
55299  *  There is no support for in-place reallocation or just compacting keys
55300  *  without resizing the property allocation.  This is intentional to keep
55301  *  code size minimal, but would be useful future work.
55302  *
55303  *  The implementation is relatively straightforward, except for the array
55304  *  abandonment process.  Array abandonment requires that new string keys
55305  *  are interned, which may trigger GC.  All keys interned so far must be
55306  *  reachable for GC at all times and correctly refcounted for; valstack is
55307  *  used for that now.
55308  *
55309  *  Also, a GC triggered during this reallocation process must not interfere
55310  *  with the object being resized.  This is currently controlled by preventing
55311  *  finalizers (as they may affect ANY object) and object compaction in
55312  *  mark-and-sweep.  It would suffice to protect only this particular object
55313  *  from compaction, however.  DECREF refzero cascades are side effect free
55314  *  and OK.
55315  *
55316  *  Note: because we need to potentially resize the valstack (as part
55317  *  of abandoning the array part), any tval pointers to the valstack
55318  *  will become invalid after this call.
55319  */
55320 
55321 DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
55322                                             duk_hobject *obj,
55323                                             duk_uint32_t new_e_size,
55324                                             duk_uint32_t new_a_size,
55325                                             duk_uint32_t new_h_size,
55326                                             duk_bool_t abandon_array) {
55327 	duk_small_uint_t prev_ms_base_flags;
55328 	duk_uint32_t new_alloc_size;
55329 	duk_uint32_t new_e_size_adjusted;
55330 	duk_uint8_t *new_p;
55331 	duk_hstring **new_e_k;
55332 	duk_propvalue *new_e_pv;
55333 	duk_uint8_t *new_e_f;
55334 	duk_tval *new_a;
55335 	duk_uint32_t *new_h;
55336 	duk_uint32_t new_e_next;
55337 	duk_uint_fast32_t i;
55338 	duk_size_t array_copy_size;
55339 #if defined(DUK_USE_ASSERTIONS)
55340 	duk_bool_t prev_error_not_allowed;
55341 #endif
55342 
55343 	DUK_ASSERT(thr != NULL);
55344 	DUK_ASSERT(obj != NULL);
55345 	DUK_ASSERT(!abandon_array || new_a_size == 0);  /* if abandon_array, new_a_size must be 0 */
55346 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || (DUK_HOBJECT_GET_ESIZE(obj) == 0 && DUK_HOBJECT_GET_ASIZE(obj) == 0));
55347 	DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size);  /* required to guarantee success of rehashing,
55348 	                                                           * intentionally use unadjusted new_e_size
55349 	                                                           */
55350 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
55351 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
55352 
55353 	DUK_STATS_INC(thr->heap, stats_object_realloc_props);
55354 
55355 	/*
55356 	 *  Pre resize assertions.
55357 	 */
55358 
55359 #if defined(DUK_USE_ASSERTIONS)
55360 	/* XXX: pre-checks (such as no duplicate keys) */
55361 #endif
55362 
55363 	/*
55364 	 *  For property layout 1, tweak e_size to ensure that the whole entry
55365 	 *  part (key + val + flags) is a suitable multiple for alignment
55366 	 *  (platform specific).
55367 	 *
55368 	 *  Property layout 2 does not require this tweaking and is preferred
55369 	 *  on low RAM platforms requiring alignment.
55370 	 */
55371 
55372 #if defined(DUK_USE_HOBJECT_LAYOUT_2) || defined(DUK_USE_HOBJECT_LAYOUT_3)
55373 	DUK_DDD(DUK_DDDPRINT("using layout 2 or 3, no need to pad e_size: %ld", (long) new_e_size));
55374 	new_e_size_adjusted = new_e_size;
55375 #elif defined(DUK_USE_HOBJECT_LAYOUT_1) && (DUK_HOBJECT_ALIGN_TARGET == 1)
55376 	DUK_DDD(DUK_DDDPRINT("using layout 1, but no need to pad e_size: %ld", (long) new_e_size));
55377 	new_e_size_adjusted = new_e_size;
55378 #elif defined(DUK_USE_HOBJECT_LAYOUT_1) && ((DUK_HOBJECT_ALIGN_TARGET == 4) || (DUK_HOBJECT_ALIGN_TARGET == 8))
55379 	new_e_size_adjusted = (new_e_size + (duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U) &
55380 	                      (~((duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U));
55381 	DUK_DDD(DUK_DDDPRINT("using layout 1, and alignment target is %ld, adjusted e_size: %ld -> %ld",
55382 	                     (long) DUK_HOBJECT_ALIGN_TARGET, (long) new_e_size, (long) new_e_size_adjusted));
55383 	DUK_ASSERT(new_e_size_adjusted >= new_e_size);
55384 #else
55385 #error invalid hobject layout defines
55386 #endif
55387 
55388 	/*
55389 	 *  Debug logging after adjustment.
55390 	 */
55391 
55392 	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 "
55393 	                     "{e_size=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
55394 	                     (void *) obj,
55395 	                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
55396 	                                                       DUK_HOBJECT_GET_ASIZE(obj),
55397 	                                                       DUK_HOBJECT_GET_HSIZE(obj)),
55398 	                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size),
55399 	                     (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
55400 	                     (long) DUK_HOBJECT_GET_ESIZE(obj),
55401 	                     (long) DUK_HOBJECT_GET_ENEXT(obj),
55402 	                     (long) DUK_HOBJECT_GET_ASIZE(obj),
55403 	                     (long) DUK_HOBJECT_GET_HSIZE(obj),
55404 	                     (long) new_e_size_adjusted,
55405 	                     (long) new_a_size,
55406 	                     (long) new_h_size,
55407 	                     (long) abandon_array,
55408 	                     (long) new_e_size));
55409 
55410 	/*
55411 	 *  Property count check.  This is the only point where we ensure that
55412 	 *  we don't get more (allocated) property space that we can handle.
55413 	 *  There aren't hard limits as such, but some algorithms may fail
55414 	 *  if we get too close to the 4G property limit.
55415 	 *
55416 	 *  Since this works based on allocation size (not actually used size),
55417 	 *  the limit is a bit approximate but good enough in practice.
55418 	 */
55419 
55420 	if (new_e_size_adjusted + new_a_size > DUK_HOBJECT_MAX_PROPERTIES) {
55421 		DUK_ERROR_ALLOC_FAILED(thr);
55422 		DUK_WO_NORETURN(return;);
55423 	}
55424 #if defined(DUK_USE_OBJSIZES16)
55425 	if (new_e_size_adjusted > DUK_UINT16_MAX || new_a_size > DUK_UINT16_MAX) {
55426 		/* If caller gave us sizes larger than what we can store,
55427 		 * fail memory safely with an internal error rather than
55428 		 * truncating the sizes.
55429 		 */
55430 		DUK_ERROR_INTERNAL(thr);
55431 		DUK_WO_NORETURN(return;);
55432 	}
55433 #endif
55434 
55435 	/*
55436 	 *  Compute new alloc size and alloc new area.
55437 	 *
55438 	 *  The new area is not tracked in the heap at all, so it's critical
55439 	 *  we get to free/keep it in a controlled manner.
55440 	 */
55441 
55442 #if defined(DUK_USE_ASSERTIONS)
55443 	/* Whole path must be error throw free, but we may be called from
55444 	 * within error handling so can't assert for error_not_allowed == 0.
55445 	 */
55446 	prev_error_not_allowed = thr->heap->error_not_allowed;
55447 	thr->heap->error_not_allowed = 1;
55448 #endif
55449 	prev_ms_base_flags = thr->heap->ms_base_flags;
55450 	thr->heap->ms_base_flags |=
55451 	        DUK_MS_FLAG_NO_OBJECT_COMPACTION;      /* Avoid attempt to compact the current object (all objects really). */
55452 	thr->heap->pf_prevent_count++;                 /* Avoid finalizers. */
55453 	DUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */
55454 
55455 	new_alloc_size = DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size);
55456 	DUK_DDD(DUK_DDDPRINT("new hobject allocation size is %ld", (long) new_alloc_size));
55457 	if (new_alloc_size == 0) {
55458 		DUK_ASSERT(new_e_size_adjusted == 0);
55459 		DUK_ASSERT(new_a_size == 0);
55460 		DUK_ASSERT(new_h_size == 0);
55461 		new_p = NULL;
55462 	} else {
55463 		/* Alloc may trigger mark-and-sweep but no compaction, and
55464 		 * cannot throw.
55465 		 */
55466 #if 0  /* XXX: inject test */
55467 		if (1) {
55468 			new_p = NULL;
55469 			goto alloc_failed;
55470 		}
55471 #endif
55472 		new_p = (duk_uint8_t *) DUK_ALLOC(thr->heap, new_alloc_size);
55473 		if (new_p == NULL) {
55474 			/* NULL always indicates alloc failure because
55475 			 * new_alloc_size > 0.
55476 			 */
55477 			goto alloc_failed;
55478 		}
55479 	}
55480 
55481 	/* Set up pointers to the new property area: this is hidden behind a macro
55482 	 * because it is memory layout specific.
55483 	 */
55484 	DUK_HOBJECT_P_SET_REALLOC_PTRS(new_p, new_e_k, new_e_pv, new_e_f, new_a, new_h,
55485 	                               new_e_size_adjusted, new_a_size, new_h_size);
55486 	DUK_UNREF(new_h);  /* happens when hash part dropped */
55487 	new_e_next = 0;
55488 
55489 	/* if new_p == NULL, all of these pointers are NULL */
55490 	DUK_ASSERT((new_p != NULL) ||
55491 	           (new_e_k == NULL && new_e_pv == NULL && new_e_f == NULL &&
55492 	            new_a == NULL && new_h == NULL));
55493 
55494 	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",
55495 	                     (long) new_alloc_size, (void *) new_e_k, (void *) new_e_pv, (void *) new_e_f,
55496 	                     (void *) new_a, (void *) new_h));
55497 
55498 	/*
55499 	 *  Migrate array part to start of entries if requested.
55500 	 *
55501 	 *  Note: from an enumeration perspective the order of entry keys matters.
55502 	 *  Array keys should appear wherever they appeared before the array abandon
55503 	 *  operation.  (This no longer matters much because keys are ES2015 sorted.)
55504 	 */
55505 
55506 	if (abandon_array) {
55507 		/* Assuming new_a_size == 0, and that entry part contains
55508 		 * no conflicting keys, refcounts do not need to be adjusted for
55509 		 * the values, as they remain exactly the same.
55510 		 *
55511 		 * The keys, however, need to be interned, incref'd, and be
55512 		 * reachable for GC.  Any intern attempt may trigger a GC and
55513 		 * claim any non-reachable strings, so every key must be reachable
55514 		 * at all times.  Refcounts must be correct to satisfy refcount
55515 		 * assertions.
55516 		 *
55517 		 * A longjmp must not occur here, as the new_p allocation would
55518 		 * leak.  Refcounts would come out correctly as the interned
55519 		 * strings are valstack tracked.
55520 		 */
55521 		DUK_ASSERT(new_a_size == 0);
55522 
55523 		DUK_STATS_INC(thr->heap, stats_object_abandon_array);
55524 
55525 		for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
55526 			duk_tval *tv1;
55527 			duk_tval *tv2;
55528 			duk_hstring *key;
55529 
55530 			DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
55531 
55532 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
55533 			if (DUK_TVAL_IS_UNUSED(tv1)) {
55534 				continue;
55535 			}
55536 
55537 			DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
55538 			           new_e_pv != NULL && new_e_f != NULL);
55539 
55540 			/*
55541 			 *  Intern key via the valstack to ensure reachability behaves
55542 			 *  properly.  We must avoid longjmp's here so use non-checked
55543 			 *  primitives.
55544 			 *
55545 			 *  Note: duk_check_stack() potentially reallocs the valstack,
55546 			 *  invalidating any duk_tval pointers to valstack.  Callers
55547 			 *  must be careful.
55548 			 */
55549 
55550 #if 0  /* XXX: inject test */
55551 			if (1) {
55552 				goto abandon_error;
55553 			}
55554 #endif
55555 			/* Never shrinks; auto-adds DUK_VALSTACK_INTERNAL_EXTRA, which
55556 			 * is generous.
55557 			 */
55558 			if (!duk_check_stack(thr, 1)) {
55559 				goto abandon_error;
55560 			}
55561 			DUK_ASSERT_VALSTACK_SPACE(thr, 1);
55562 			key = duk_heap_strtable_intern_u32(thr->heap, (duk_uint32_t) i);
55563 			if (key == NULL) {
55564 				goto abandon_error;
55565 			}
55566 			duk_push_hstring(thr, key);  /* keep key reachable for GC etc; guaranteed not to fail */
55567 
55568 			/* Key is now reachable in the valstack, don't INCREF
55569 			 * the new allocation yet (we'll steal the refcounts
55570 			 * from the value stack once all keys are done).
55571 			 */
55572 
55573 			new_e_k[new_e_next] = key;
55574 			tv2 = &new_e_pv[new_e_next].v;  /* array entries are all plain values */
55575 			DUK_TVAL_SET_TVAL(tv2, tv1);
55576 			new_e_f[new_e_next] = DUK_PROPDESC_FLAG_WRITABLE |
55577 			                      DUK_PROPDESC_FLAG_ENUMERABLE |
55578 			                      DUK_PROPDESC_FLAG_CONFIGURABLE;
55579 			new_e_next++;
55580 
55581 			/* Note: new_e_next matches pushed temp key count, and nothing can
55582 			 * fail above between the push and this point.
55583 			 */
55584 		}
55585 
55586 		/* Steal refcounts from value stack. */
55587 		DUK_DDD(DUK_DDDPRINT("abandon array: pop %ld key temps from valstack", (long) new_e_next));
55588 		duk_pop_n_nodecref_unsafe(thr, (duk_idx_t) new_e_next);
55589 	}
55590 
55591 	/*
55592 	 *  Copy keys and values in the entry part (compacting them at the same time).
55593 	 */
55594 
55595 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
55596 		duk_hstring *key;
55597 
55598 		DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
55599 
55600 		key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
55601 		if (key == NULL) {
55602 			continue;
55603 		}
55604 
55605 		DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
55606 		           new_e_pv != NULL && new_e_f != NULL);
55607 
55608 		new_e_k[new_e_next] = key;
55609 		new_e_pv[new_e_next] = DUK_HOBJECT_E_GET_VALUE(thr->heap, obj, i);
55610 		new_e_f[new_e_next] = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
55611 		new_e_next++;
55612 	}
55613 	/* the entries [new_e_next, new_e_size_adjusted[ are left uninitialized on purpose (ok, not gc reachable) */
55614 
55615 	/*
55616 	 *  Copy array elements to new array part.  If the new array part is
55617 	 *  larger, initialize the unused entries as UNUSED because they are
55618 	 *  GC reachable.
55619 	 */
55620 
55621 #if defined(DUK_USE_ASSERTIONS)
55622 	/* Caller must have decref'd values above new_a_size (if that is necessary). */
55623 	if (!abandon_array) {
55624 		for (i = new_a_size; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
55625 			duk_tval *tv;
55626 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
55627 			DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
55628 		}
55629 	}
55630 #endif
55631 	if (new_a_size > DUK_HOBJECT_GET_ASIZE(obj)) {
55632 		array_copy_size = sizeof(duk_tval) * DUK_HOBJECT_GET_ASIZE(obj);
55633 	} else {
55634 		array_copy_size = sizeof(duk_tval) * new_a_size;
55635 	}
55636 
55637 	DUK_ASSERT(new_a != NULL || array_copy_size == 0U);
55638 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || array_copy_size == 0U);
55639 	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) > 0 || array_copy_size == 0U);
55640 	duk_memcpy_unsafe((void *) new_a,
55641 	                  (const void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj),
55642 	                  array_copy_size);
55643 
55644 	for (i = DUK_HOBJECT_GET_ASIZE(obj); i < new_a_size; i++) {
55645 		duk_tval *tv = &new_a[i];
55646 		DUK_TVAL_SET_UNUSED(tv);
55647 	}
55648 
55649 	/*
55650 	 *  Rebuild the hash part always from scratch (guaranteed to finish
55651 	 *  as long as caller gave consistent parameters).
55652 	 *
55653 	 *  Any resize of hash part requires rehashing.  In addition, by rehashing
55654 	 *  get rid of any elements marked deleted (DUK__HASH_DELETED) which is critical
55655 	 *  to ensuring the hash part never fills up.
55656 	 */
55657 
55658 #if defined(DUK_USE_HOBJECT_HASH_PART)
55659 	if (new_h_size == 0) {
55660 		DUK_DDD(DUK_DDDPRINT("no hash part, no rehash"));
55661 	} else {
55662 		duk_uint32_t mask;
55663 
55664 		DUK_ASSERT(new_h != NULL);
55665 
55666 		/* fill new_h with u32 0xff = UNUSED */
55667 		DUK_ASSERT(new_h_size > 0);
55668 		duk_memset(new_h, 0xff, sizeof(duk_uint32_t) * new_h_size);
55669 
55670 		DUK_ASSERT(new_e_next <= new_h_size);  /* equality not actually possible */
55671 
55672 		mask = new_h_size - 1;
55673 		for (i = 0; i < new_e_next; i++) {
55674 			duk_hstring *key = new_e_k[i];
55675 			duk_uint32_t j, step;
55676 
55677 			DUK_ASSERT(key != NULL);
55678 			j = DUK_HSTRING_GET_HASH(key) & mask;
55679 			step = 1;  /* Cache friendly but clustering prone. */
55680 
55681 			for (;;) {
55682 				DUK_ASSERT(new_h[j] != DUK__HASH_DELETED);  /* should never happen */
55683 				if (new_h[j] == DUK__HASH_UNUSED) {
55684 					DUK_DDD(DUK_DDDPRINT("rebuild hit %ld -> %ld", (long) j, (long) i));
55685 					new_h[j] = (duk_uint32_t) i;
55686 					break;
55687 				}
55688 				DUK_DDD(DUK_DDDPRINT("rebuild miss %ld, step %ld", (long) j, (long) step));
55689 				j = (j + step) & mask;
55690 
55691 				/* Guaranteed to finish (hash is larger than #props). */
55692 			}
55693 		}
55694 	}
55695 #endif  /* DUK_USE_HOBJECT_HASH_PART */
55696 
55697 	/*
55698 	 *  Nice debug log.
55699 	 */
55700 
55701 	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 "
55702 	                   "{p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
55703 	                   (void *) obj,
55704 	                   (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
55705 	                                                     DUK_HOBJECT_GET_ASIZE(obj),
55706 	                                                     DUK_HOBJECT_GET_HSIZE(obj)),
55707 	                   (long) new_alloc_size,
55708 	                   (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
55709 	                   (long) DUK_HOBJECT_GET_ESIZE(obj),
55710 	                   (long) DUK_HOBJECT_GET_ENEXT(obj),
55711 	                   (long) DUK_HOBJECT_GET_ASIZE(obj),
55712 	                   (long) DUK_HOBJECT_GET_HSIZE(obj),
55713 	                   (void *) new_p,
55714 	                   (long) new_e_size_adjusted,
55715 	                   (long) new_e_next,
55716 	                   (long) new_a_size,
55717 	                   (long) new_h_size,
55718 	                   (long) abandon_array,
55719 	                   (long) new_e_size));
55720 
55721 	/*
55722 	 *  All done, switch properties ('p') allocation to new one.
55723 	 */
55724 
55725 	DUK_FREE_CHECKED(thr, DUK_HOBJECT_GET_PROPS(thr->heap, obj));  /* NULL obj->p is OK */
55726 	DUK_HOBJECT_SET_PROPS(thr->heap, obj, new_p);
55727 	DUK_HOBJECT_SET_ESIZE(obj, new_e_size_adjusted);
55728 	DUK_HOBJECT_SET_ENEXT(obj, new_e_next);
55729 	DUK_HOBJECT_SET_ASIZE(obj, new_a_size);
55730 	DUK_HOBJECT_SET_HSIZE(obj, new_h_size);
55731 
55732 	/* Clear array part flag only after switching. */
55733 	if (abandon_array) {
55734 		DUK_HOBJECT_CLEAR_ARRAY_PART(obj);
55735 	}
55736 
55737 	DUK_DDD(DUK_DDDPRINT("resize result: %!O", (duk_heaphdr *) obj));
55738 
55739 	DUK_ASSERT(thr->heap->pf_prevent_count > 0);
55740 	thr->heap->pf_prevent_count--;
55741 	thr->heap->ms_base_flags = prev_ms_base_flags;
55742 #if defined(DUK_USE_ASSERTIONS)
55743 	DUK_ASSERT(thr->heap->error_not_allowed == 1);
55744 	thr->heap->error_not_allowed = prev_error_not_allowed;
55745 #endif
55746 
55747 	/*
55748 	 *  Post resize assertions.
55749 	 */
55750 
55751 #if defined(DUK_USE_ASSERTIONS)
55752 	/* XXX: post-checks (such as no duplicate keys) */
55753 #endif
55754 	return;
55755 
55756 	/*
55757 	 *  Abandon array failed.  We don't need to DECREF anything
55758 	 *  because the references in the new allocation are not
55759 	 *  INCREF'd until abandon is complete.  The string interned
55760 	 *  keys are on the value stack and are handled normally by
55761 	 *  unwind.
55762 	 */
55763 
55764  abandon_error:
55765  alloc_failed:
55766 	DUK_D(DUK_DPRINT("object property table resize failed"));
55767 
55768 	DUK_FREE_CHECKED(thr, new_p);  /* OK for NULL. */
55769 
55770 	thr->heap->pf_prevent_count--;
55771 	thr->heap->ms_base_flags = prev_ms_base_flags;
55772 #if defined(DUK_USE_ASSERTIONS)
55773 	DUK_ASSERT(thr->heap->error_not_allowed == 1);
55774 	thr->heap->error_not_allowed = prev_error_not_allowed;
55775 #endif
55776 
55777 	DUK_ERROR_ALLOC_FAILED(thr);
55778 	DUK_WO_NORETURN(return;);
55779 }
55780 
55781 /*
55782  *  Helpers to resize properties allocation on specific needs.
55783  */
55784 
55785 DUK_INTERNAL void duk_hobject_resize_entrypart(duk_hthread *thr,
55786                                                duk_hobject *obj,
55787                                                duk_uint32_t new_e_size) {
55788 	duk_uint32_t old_e_size;
55789 	duk_uint32_t new_a_size;
55790 	duk_uint32_t new_h_size;
55791 
55792 	DUK_ASSERT(thr != NULL);
55793 	DUK_ASSERT(obj != NULL);
55794 
55795 	old_e_size = DUK_HOBJECT_GET_ESIZE(obj);
55796 	if (old_e_size > new_e_size) {
55797 		new_e_size = old_e_size;
55798 	}
55799 #if defined(DUK_USE_HOBJECT_HASH_PART)
55800 	new_h_size = duk__get_default_h_size(new_e_size);
55801 #else
55802 	new_h_size = 0;
55803 #endif
55804 	new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
55805 
55806 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
55807 }
55808 
55809 /* Grow entry part allocation for one additional entry. */
55810 DUK_LOCAL void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject *obj) {
55811 	duk_uint32_t old_e_used;  /* actually used, non-NULL entries */
55812 	duk_uint32_t new_e_size_minimum;
55813 	duk_uint32_t new_e_size;
55814 	duk_uint32_t new_a_size;
55815 	duk_uint32_t new_h_size;
55816 
55817 	DUK_ASSERT(thr != NULL);
55818 	DUK_ASSERT(obj != NULL);
55819 
55820 	/* Duktape 0.11.0 and prior tried to optimize the resize by not
55821 	 * counting the number of actually used keys prior to the resize.
55822 	 * This worked mostly well but also caused weird leak-like behavior
55823 	 * as in: test-bug-object-prop-alloc-unbounded.js.  So, now we count
55824 	 * the keys explicitly to compute the new entry part size.
55825 	 */
55826 
55827 	old_e_used = duk__count_used_e_keys(thr, obj);
55828 	new_e_size_minimum = old_e_used + 1;
55829 	new_e_size = old_e_used + duk__get_min_grow_e(old_e_used);
55830 #if defined(DUK_USE_HOBJECT_HASH_PART)
55831 	new_h_size = duk__get_default_h_size(new_e_size);
55832 #else
55833 	new_h_size = 0;
55834 #endif
55835 	new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
55836 
55837 #if defined(DUK_USE_OBJSIZES16)
55838 	if (new_e_size > DUK_UINT16_MAX) {
55839 		new_e_size = DUK_UINT16_MAX;
55840 	}
55841 	if (new_h_size > DUK_UINT16_MAX) {
55842 		new_h_size = DUK_UINT16_MAX;
55843 	}
55844 	if (new_a_size > DUK_UINT16_MAX) {
55845 		new_a_size = DUK_UINT16_MAX;
55846 	}
55847 #endif
55848 	DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size);
55849 
55850 	if (!(new_e_size >= new_e_size_minimum)) {
55851 		DUK_ERROR_ALLOC_FAILED(thr);
55852 		DUK_WO_NORETURN(return;);
55853 	}
55854 
55855 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
55856 }
55857 
55858 /* Grow array part for a new highest array index. */
55859 DUK_LOCAL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx) {
55860 	duk_uint32_t new_e_size;
55861 	duk_uint32_t new_a_size;
55862 	duk_uint32_t new_a_size_minimum;
55863 	duk_uint32_t new_h_size;
55864 
55865 	DUK_ASSERT(thr != NULL);
55866 	DUK_ASSERT(obj != NULL);
55867 	DUK_ASSERT(highest_arr_idx >= DUK_HOBJECT_GET_ASIZE(obj));
55868 
55869 	new_e_size = DUK_HOBJECT_GET_ESIZE(obj);
55870 	new_h_size = DUK_HOBJECT_GET_HSIZE(obj);
55871 	new_a_size_minimum = highest_arr_idx + 1;
55872 	new_a_size = highest_arr_idx + duk__get_min_grow_a(highest_arr_idx);
55873 	DUK_ASSERT(new_a_size >= highest_arr_idx + 1);  /* duk__get_min_grow_a() is always >= 1 */
55874 
55875 #if defined(DUK_USE_OBJSIZES16)
55876 	if (new_e_size > DUK_UINT16_MAX) {
55877 		new_e_size = DUK_UINT16_MAX;
55878 	}
55879 	if (new_h_size > DUK_UINT16_MAX) {
55880 		new_h_size = DUK_UINT16_MAX;
55881 	}
55882 	if (new_a_size > DUK_UINT16_MAX) {
55883 		new_a_size = DUK_UINT16_MAX;
55884 	}
55885 #endif
55886 
55887 	if (!(new_a_size >= new_a_size_minimum)) {
55888 		DUK_ERROR_ALLOC_FAILED(thr);
55889 		DUK_WO_NORETURN(return;);
55890 	}
55891 
55892 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
55893 }
55894 
55895 /* Abandon array part, moving array entries into entries part.
55896  * This requires a props resize, which is a heavy operation.
55897  * We also compact the entries part while we're at it, although
55898  * this is not strictly required.
55899  */
55900 DUK_LOCAL void duk__abandon_array_part(duk_hthread *thr, duk_hobject *obj) {
55901 	duk_uint32_t new_e_size_minimum;
55902 	duk_uint32_t new_e_size;
55903 	duk_uint32_t new_a_size;
55904 	duk_uint32_t new_h_size;
55905 	duk_uint32_t e_used;  /* actually used, non-NULL keys */
55906 	duk_uint32_t a_used;
55907 	duk_uint32_t a_size;
55908 
55909 	DUK_ASSERT(thr != NULL);
55910 	DUK_ASSERT(obj != NULL);
55911 
55912 	e_used = duk__count_used_e_keys(thr, obj);
55913 	duk__compute_a_stats(thr, obj, &a_used, &a_size);
55914 
55915 	/*
55916 	 *  Must guarantee all actually used array entries will fit into
55917 	 *  new entry part.  Add one growth step to ensure we don't run out
55918 	 *  of space right away.
55919 	 */
55920 
55921 	new_e_size_minimum = e_used + a_used;
55922 	new_e_size = new_e_size_minimum + duk__get_min_grow_e(new_e_size_minimum);
55923 	new_a_size = 0;
55924 #if defined(DUK_USE_HOBJECT_HASH_PART)
55925 	new_h_size = duk__get_default_h_size(new_e_size);
55926 #else
55927 	new_h_size = 0;
55928 #endif
55929 
55930 #if defined(DUK_USE_OBJSIZES16)
55931 	if (new_e_size > DUK_UINT16_MAX) {
55932 		new_e_size = DUK_UINT16_MAX;
55933 	}
55934 	if (new_h_size > DUK_UINT16_MAX) {
55935 		new_h_size = DUK_UINT16_MAX;
55936 	}
55937 	if (new_a_size > DUK_UINT16_MAX) {
55938 		new_a_size = DUK_UINT16_MAX;
55939 	}
55940 #endif
55941 
55942 	if (!(new_e_size >= new_e_size_minimum)) {
55943 		DUK_ERROR_ALLOC_FAILED(thr);
55944 		DUK_WO_NORETURN(return;);
55945 	}
55946 
55947 	DUK_DD(DUK_DDPRINT("abandon array part for hobject %p, "
55948 	                   "array stats before: e_used=%ld, a_used=%ld, a_size=%ld; "
55949 	                   "resize to e_size=%ld, a_size=%ld, h_size=%ld",
55950 	                   (void *) obj, (long) e_used, (long) a_used, (long) a_size,
55951 	                   (long) new_e_size, (long) new_a_size, (long) new_h_size));
55952 
55953 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 1);
55954 }
55955 
55956 /*
55957  *  Compact an object.  Minimizes allocation size for objects which are
55958  *  not likely to be extended.  This is useful for internal and non-
55959  *  extensible objects, but can also be called for non-extensible objects.
55960  *  May abandon the array part if it is computed to be too sparse.
55961  *
55962  *  This call is relatively expensive, as it needs to scan both the
55963  *  entries and the array part.
55964  *
55965  *  The call may fail due to allocation error.
55966  */
55967 
55968 DUK_INTERNAL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj) {
55969 	duk_uint32_t e_size;       /* currently used -> new size */
55970 	duk_uint32_t a_size;       /* currently required */
55971 	duk_uint32_t a_used;       /* actually used */
55972 	duk_uint32_t h_size;
55973 	duk_bool_t abandon_array;
55974 
55975 	DUK_ASSERT(thr != NULL);
55976 	DUK_ASSERT(obj != NULL);
55977 
55978 #if defined(DUK_USE_ROM_OBJECTS)
55979 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
55980 		DUK_DD(DUK_DDPRINT("ignore attempt to compact a rom object"));
55981 		return;
55982 	}
55983 #endif
55984 
55985 	e_size = duk__count_used_e_keys(thr, obj);
55986 	duk__compute_a_stats(thr, obj, &a_used, &a_size);
55987 
55988 	DUK_DD(DUK_DDPRINT("compacting hobject, used e keys %ld, used a keys %ld, min a size %ld, "
55989 	                   "resized array density would be: %ld/%ld = %lf",
55990 	                   (long) e_size, (long) a_used, (long) a_size,
55991 	                   (long) a_used, (long) a_size,
55992 	                   (double) a_used / (double) a_size));
55993 
55994 	if (duk__abandon_array_density_check(a_used, a_size)) {
55995 		DUK_DD(DUK_DDPRINT("decided to abandon array during compaction, a_used=%ld, a_size=%ld",
55996 		                   (long) a_used, (long) a_size));
55997 		abandon_array = 1;
55998 		e_size += a_used;
55999 		a_size = 0;
56000 	} else {
56001 		DUK_DD(DUK_DDPRINT("decided to keep array during compaction"));
56002 		abandon_array = 0;
56003 	}
56004 
56005 #if defined(DUK_USE_HOBJECT_HASH_PART)
56006 	if (e_size >= DUK_USE_HOBJECT_HASH_PROP_LIMIT) {
56007 		h_size = duk__get_default_h_size(e_size);
56008 	} else {
56009 		h_size = 0;
56010 	}
56011 #else
56012 	h_size = 0;
56013 #endif
56014 
56015 	DUK_DD(DUK_DDPRINT("compacting hobject -> new e_size %ld, new a_size=%ld, new h_size=%ld, abandon_array=%ld",
56016 	                   (long) e_size, (long) a_size, (long) h_size, (long) abandon_array));
56017 
56018 	duk_hobject_realloc_props(thr, obj, e_size, a_size, h_size, abandon_array);
56019 }
56020 
56021 /*
56022  *  Find an existing key from entry part either by linear scan or by
56023  *  using the hash index (if it exists).
56024  *
56025  *  Sets entry index (and possibly the hash index) to output variables,
56026  *  which allows the caller to update the entry and hash entries in-place.
56027  *  If entry is not found, both values are set to -1.  If entry is found
56028  *  but there is no hash part, h_idx is set to -1.
56029  */
56030 
56031 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) {
56032 	DUK_ASSERT(obj != NULL);
56033 	DUK_ASSERT(key != NULL);
56034 	DUK_ASSERT(e_idx != NULL);
56035 	DUK_ASSERT(h_idx != NULL);
56036 	DUK_UNREF(heap);
56037 
56038 	if (DUK_LIKELY(DUK_HOBJECT_GET_HSIZE(obj) == 0))
56039 	{
56040 		/* Linear scan: more likely because most objects are small.
56041 		 * This is an important fast path.
56042 		 *
56043 		 * XXX: this might be worth inlining for property lookups.
56044 		 */
56045 		duk_uint_fast32_t i;
56046 		duk_uint_fast32_t n;
56047 		duk_hstring **h_keys_base;
56048 		DUK_DDD(DUK_DDDPRINT("duk_hobject_find_entry() using linear scan for lookup"));
56049 
56050 		h_keys_base = DUK_HOBJECT_E_GET_KEY_BASE(heap, obj);
56051 		n = DUK_HOBJECT_GET_ENEXT(obj);
56052 		for (i = 0; i < n; i++) {
56053 			if (h_keys_base[i] == key) {
56054 				*e_idx = (duk_int_t) i;
56055 				*h_idx = -1;
56056 				return 1;
56057 			}
56058 		}
56059 	}
56060 #if defined(DUK_USE_HOBJECT_HASH_PART)
56061 	else
56062 	{
56063 		/* hash lookup */
56064 		duk_uint32_t n;
56065 		duk_uint32_t i, step;
56066 		duk_uint32_t *h_base;
56067 		duk_uint32_t mask;
56068 
56069 		DUK_DDD(DUK_DDDPRINT("duk_hobject_find_entry() using hash part for lookup"));
56070 
56071 		h_base = DUK_HOBJECT_H_GET_BASE(heap, obj);
56072 		n = DUK_HOBJECT_GET_HSIZE(obj);
56073 		mask = n - 1;
56074 		i = DUK_HSTRING_GET_HASH(key) & mask;
56075 		step = 1;  /* Cache friendly but clustering prone. */
56076 
56077 		for (;;) {
56078 			duk_uint32_t t;
56079 
56080 			DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
56081 			DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
56082 			t = h_base[i];
56083 			DUK_ASSERT(t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED ||
56084 			           (t < DUK_HOBJECT_GET_ESIZE(obj)));  /* t >= 0 always true, unsigned */
56085 
56086 			if (t == DUK__HASH_UNUSED) {
56087 				break;
56088 			} else if (t == DUK__HASH_DELETED) {
56089 				DUK_DDD(DUK_DDDPRINT("lookup miss (deleted) i=%ld, t=%ld",
56090 				                     (long) i, (long) t));
56091 			} else {
56092 				DUK_ASSERT(t < DUK_HOBJECT_GET_ESIZE(obj));
56093 				if (DUK_HOBJECT_E_GET_KEY(heap, obj, t) == key) {
56094 					DUK_DDD(DUK_DDDPRINT("lookup hit i=%ld, t=%ld -> key %p",
56095 					                     (long) i, (long) t, (void *) key));
56096 					*e_idx = (duk_int_t) t;
56097 					*h_idx = (duk_int_t) i;
56098 					return 1;
56099 				}
56100 				DUK_DDD(DUK_DDDPRINT("lookup miss i=%ld, t=%ld",
56101 				                     (long) i, (long) t));
56102 			}
56103 			i = (i + step) & mask;
56104 
56105 			/* Guaranteed to finish (hash is larger than #props). */
56106 		}
56107 	}
56108 #endif  /* DUK_USE_HOBJECT_HASH_PART */
56109 
56110 	/* Not found, leave e_idx and h_idx unset. */
56111 	return 0;
56112 }
56113 
56114 /* For internal use: get non-accessor entry value */
56115 DUK_INTERNAL duk_tval *duk_hobject_find_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key) {
56116 	duk_int_t e_idx;
56117 	duk_int_t h_idx;
56118 
56119 	DUK_ASSERT(obj != NULL);
56120 	DUK_ASSERT(key != NULL);
56121 	DUK_UNREF(heap);
56122 
56123 	if (duk_hobject_find_entry(heap, obj, key, &e_idx, &h_idx)) {
56124 		DUK_ASSERT(e_idx >= 0);
56125 		if (!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
56126 			return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
56127 		}
56128 	}
56129 	return NULL;
56130 }
56131 
56132 DUK_INTERNAL duk_tval *duk_hobject_find_entry_tval_ptr_stridx(duk_heap *heap, duk_hobject *obj, duk_small_uint_t stridx) {
56133 	return duk_hobject_find_entry_tval_ptr(heap, obj, DUK_HEAP_GET_STRING(heap, stridx));
56134 }
56135 
56136 /* For internal use: get non-accessor entry value and attributes */
56137 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) {
56138 	duk_int_t e_idx;
56139 	duk_int_t h_idx;
56140 
56141 	DUK_ASSERT(obj != NULL);
56142 	DUK_ASSERT(key != NULL);
56143 	DUK_ASSERT(out_attrs != NULL);
56144 	DUK_UNREF(heap);
56145 
56146 	if (duk_hobject_find_entry(heap, obj, key, &e_idx, &h_idx)) {
56147 		DUK_ASSERT(e_idx >= 0);
56148 		if (!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
56149 			*out_attrs = DUK_HOBJECT_E_GET_FLAGS(heap, obj, e_idx);
56150 			return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
56151 		}
56152 	}
56153 	/* If not found, out_attrs is left unset. */
56154 	return NULL;
56155 }
56156 
56157 /* For internal use: get array part value */
56158 DUK_INTERNAL duk_tval *duk_hobject_find_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i) {
56159 	duk_tval *tv;
56160 
56161 	DUK_ASSERT(obj != NULL);
56162 	DUK_UNREF(heap);
56163 
56164 	if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
56165 		return NULL;
56166 	}
56167 	if (i >= DUK_HOBJECT_GET_ASIZE(obj)) {
56168 		return NULL;
56169 	}
56170 	tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, obj, i);
56171 	return tv;
56172 }
56173 
56174 /*
56175  *  Allocate and initialize a new entry, resizing the properties allocation
56176  *  if necessary.  Returns entry index (e_idx) or throws an error if alloc fails.
56177  *
56178  *  Sets the key of the entry (increasing the key's refcount), and updates
56179  *  the hash part if it exists.  Caller must set value and flags, and update
56180  *  the entry value refcount.  A decref for the previous value is not necessary.
56181  */
56182 
56183 DUK_LOCAL duk_int_t duk__hobject_alloc_entry_checked(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
56184 	duk_uint32_t idx;
56185 
56186 	DUK_ASSERT(thr != NULL);
56187 	DUK_ASSERT(obj != NULL);
56188 	DUK_ASSERT(key != NULL);
56189 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) <= DUK_HOBJECT_GET_ESIZE(obj));
56190 
56191 #if defined(DUK_USE_ASSERTIONS)
56192 	/* key must not already exist in entry part */
56193 	{
56194 		duk_uint_fast32_t i;
56195 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
56196 			DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != key);
56197 		}
56198 	}
56199 #endif
56200 
56201 	if (DUK_HOBJECT_GET_ENEXT(obj) >= DUK_HOBJECT_GET_ESIZE(obj)) {
56202 		/* only need to guarantee 1 more slot, but allocation growth is in chunks */
56203 		DUK_DDD(DUK_DDDPRINT("entry part full, allocate space for one more entry"));
56204 		duk__grow_props_for_new_entry_item(thr, obj);
56205 	}
56206 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) < DUK_HOBJECT_GET_ESIZE(obj));
56207 	idx = DUK_HOBJECT_POSTINC_ENEXT(obj);
56208 
56209 	/* previous value is assumed to be garbage, so don't touch it */
56210 	DUK_HOBJECT_E_SET_KEY(thr->heap, obj, idx, key);
56211 	DUK_HSTRING_INCREF(thr, key);
56212 
56213 #if defined(DUK_USE_HOBJECT_HASH_PART)
56214 	if (DUK_UNLIKELY(DUK_HOBJECT_GET_HSIZE(obj) > 0)) {
56215 		duk_uint32_t n, mask;
56216 		duk_uint32_t i, step;
56217 		duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
56218 
56219 		n = DUK_HOBJECT_GET_HSIZE(obj);
56220 		mask = n - 1;
56221 		i = DUK_HSTRING_GET_HASH(key) & mask;
56222 		step = 1;  /* Cache friendly but clustering prone. */
56223 
56224 		for (;;) {
56225 			duk_uint32_t t = h_base[i];
56226 			if (t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED) {
56227 				DUK_DDD(DUK_DDDPRINT("duk__hobject_alloc_entry_checked() inserted key into hash part, %ld -> %ld",
56228 				                     (long) i, (long) idx));
56229 				DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
56230 				DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
56231 				DUK_ASSERT_DISABLE(idx >= 0);
56232 				DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
56233 				h_base[i] = idx;
56234 				break;
56235 			}
56236 			DUK_DDD(DUK_DDDPRINT("duk__hobject_alloc_entry_checked() miss %ld", (long) i));
56237 			i = (i + step) & mask;
56238 
56239 			/* Guaranteed to finish (hash is larger than #props). */
56240 		}
56241 	}
56242 #endif  /* DUK_USE_HOBJECT_HASH_PART */
56243 
56244 	/* Note: we could return the hash index here too, but it's not
56245 	 * needed right now.
56246 	 */
56247 
56248 	DUK_ASSERT_DISABLE(idx >= 0);
56249 	DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
56250 	DUK_ASSERT(idx < DUK_HOBJECT_GET_ENEXT(obj));
56251 	return (duk_int_t) idx;
56252 }
56253 
56254 /*
56255  *  Object internal value
56256  *
56257  *  Returned value is guaranteed to be reachable / incref'd, caller does not need
56258  *  to incref OR decref.  No proxies or accessors are invoked, no prototype walk.
56259  */
56260 
56261 DUK_INTERNAL duk_tval *duk_hobject_get_internal_value_tval_ptr(duk_heap *heap, duk_hobject *obj) {
56262 	return duk_hobject_find_entry_tval_ptr_stridx(heap, obj, DUK_STRIDX_INT_VALUE);
56263 }
56264 
56265 DUK_LOCAL duk_heaphdr *duk_hobject_get_internal_value_heaphdr(duk_heap *heap, duk_hobject *obj) {
56266 	duk_tval *tv;
56267 
56268 	DUK_ASSERT(heap != NULL);
56269 	DUK_ASSERT(obj != NULL);
56270 
56271 	tv = duk_hobject_get_internal_value_tval_ptr(heap, obj);
56272 	if (tv != NULL) {
56273 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
56274 		DUK_ASSERT(h != NULL);
56275 		return h;
56276 	}
56277 
56278 	return NULL;
56279 }
56280 
56281 DUK_INTERNAL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj) {
56282 	duk_hstring *h;
56283 
56284 	h = (duk_hstring *) duk_hobject_get_internal_value_heaphdr(heap, obj);
56285 	if (h != NULL) {
56286 		DUK_ASSERT(DUK_HEAPHDR_IS_STRING((duk_heaphdr *) h));
56287 	}
56288 	return h;
56289 }
56290 
56291 DUK_LOCAL duk_hobject *duk__hobject_get_entry_object_stridx(duk_heap *heap, duk_hobject *obj, duk_small_uint_t stridx) {
56292 	duk_tval *tv;
56293 	duk_hobject *h;
56294 
56295 	tv = duk_hobject_find_entry_tval_ptr_stridx(heap, obj, stridx);
56296 	if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
56297 		h = DUK_TVAL_GET_OBJECT(tv);
56298 		DUK_ASSERT(h != NULL);
56299 		return h;
56300 	}
56301 	return NULL;
56302 }
56303 
56304 DUK_INTERNAL duk_harray *duk_hobject_get_formals(duk_hthread *thr, duk_hobject *obj) {
56305 	duk_harray *h;
56306 
56307 	h = (duk_harray *) duk__hobject_get_entry_object_stridx(thr->heap, obj, DUK_STRIDX_INT_FORMALS);
56308 	if (h != NULL) {
56309 		DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) h));
56310 		DUK_ASSERT(h->length <= DUK_HOBJECT_GET_ASIZE((duk_hobject *) h));
56311 	}
56312 	return h;
56313 }
56314 
56315 DUK_INTERNAL duk_hobject *duk_hobject_get_varmap(duk_hthread *thr, duk_hobject *obj) {
56316 	duk_hobject *h;
56317 
56318 	h = duk__hobject_get_entry_object_stridx(thr->heap, obj, DUK_STRIDX_INT_VARMAP);
56319 	return h;
56320 }
56321 
56322 /*
56323  *  Arguments handling helpers (argument map mainly).
56324  *
56325  *  An arguments object has exotic behavior for some numeric indices.
56326  *  Accesses may translate to identifier operations which may have
56327  *  arbitrary side effects (potentially invalidating any duk_tval
56328  *  pointers).
56329  */
56330 
56331 /* Lookup 'key' from arguments internal 'map', perform a variable lookup
56332  * if mapped, and leave the result on top of stack (and return non-zero).
56333  * Used in E5 Section 10.6 algorithms [[Get]] and [[GetOwnProperty]].
56334  */
56335 DUK_LOCAL
56336 duk_bool_t duk__lookup_arguments_map(duk_hthread *thr,
56337                                      duk_hobject *obj,
56338                                      duk_hstring *key,
56339                                      duk_propdesc *temp_desc,
56340                                      duk_hobject **out_map,
56341                                      duk_hobject **out_varenv) {
56342 	duk_hobject *map;
56343 	duk_hobject *varenv;
56344 	duk_bool_t rc;
56345 
56346 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
56347 
56348 	DUK_DDD(DUK_DDDPRINT("arguments map lookup: thr=%p, obj=%p, key=%p, temp_desc=%p "
56349 	                     "(obj -> %!O, key -> %!O)",
56350 	                     (void *) thr, (void *) obj, (void *) key, (void *) temp_desc,
56351 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
56352 
56353 	if (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
56354 		DUK_DDD(DUK_DDDPRINT("-> no 'map'"));
56355 		return 0;
56356 	}
56357 
56358 	map = duk_require_hobject(thr, -1);
56359 	DUK_ASSERT(map != NULL);
56360 	duk_pop_unsafe(thr);  /* map is reachable through obj */
56361 
56362 	if (!duk_hobject_get_own_propdesc(thr, map, key, temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
56363 		DUK_DDD(DUK_DDDPRINT("-> 'map' exists, but key not in map"));
56364 		return 0;
56365 	}
56366 
56367 	/* [... varname] */
56368 	DUK_DDD(DUK_DDDPRINT("-> 'map' exists, and contains key, key is mapped to argument/variable binding %!T",
56369 	                     (duk_tval *) duk_get_tval(thr, -1)));
56370 	DUK_ASSERT(duk_is_string(thr, -1));  /* guaranteed when building arguments */
56371 
56372 	/* get varenv for varname (callee's declarative lexical environment) */
56373 	rc = duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_VARENV(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE);
56374 	DUK_UNREF(rc);
56375 	DUK_ASSERT(rc != 0);  /* arguments MUST have an initialized lexical environment reference */
56376 	varenv = duk_require_hobject(thr, -1);
56377 	DUK_ASSERT(varenv != NULL);
56378 	duk_pop_unsafe(thr);  /* varenv remains reachable through 'obj' */
56379 
56380 	DUK_DDD(DUK_DDDPRINT("arguments varenv is: %!dO", (duk_heaphdr *) varenv));
56381 
56382 	/* success: leave varname in stack */
56383 	*out_map = map;
56384 	*out_varenv = varenv;
56385 	return 1;  /* [... varname] */
56386 }
56387 
56388 /* Lookup 'key' from arguments internal 'map', and leave replacement value
56389  * on stack top if mapped (and return non-zero).
56390  * Used in E5 Section 10.6 algorithm for [[GetOwnProperty]] (used by [[Get]]).
56391  */
56392 DUK_LOCAL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
56393 	duk_hobject *map;
56394 	duk_hobject *varenv;
56395 	duk_hstring *varname;
56396 
56397 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
56398 
56399 	if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
56400 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic get behavior"));
56401 		return 0;
56402 	}
56403 
56404 	/* [... varname] */
56405 
56406 	varname = duk_require_hstring(thr, -1);
56407 	DUK_ASSERT(varname != NULL);
56408 	duk_pop_unsafe(thr);  /* varname is still reachable */
56409 
56410 	DUK_DDD(DUK_DDDPRINT("arguments object automatic getvar for a bound variable; "
56411 	                     "key=%!O, varname=%!O",
56412 	                     (duk_heaphdr *) key,
56413 	                     (duk_heaphdr *) varname));
56414 
56415 	(void) duk_js_getvar_envrec(thr, varenv, varname, 1 /*throw*/);
56416 
56417 	/* [... value this_binding] */
56418 
56419 	duk_pop_unsafe(thr);
56420 
56421 	/* leave result on stack top */
56422 	return 1;
56423 }
56424 
56425 /* Lookup 'key' from arguments internal 'map', perform a variable write if mapped.
56426  * Used in E5 Section 10.6 algorithm for [[DefineOwnProperty]] (used by [[Put]]).
56427  * Assumes stack top contains 'put' value (which is NOT popped).
56428  */
56429 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) {
56430 	duk_hobject *map;
56431 	duk_hobject *varenv;
56432 	duk_hstring *varname;
56433 
56434 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
56435 
56436 	if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
56437 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic put behavior"));
56438 		return;
56439 	}
56440 
56441 	/* [... put_value varname] */
56442 
56443 	varname = duk_require_hstring(thr, -1);
56444 	DUK_ASSERT(varname != NULL);
56445 	duk_pop_unsafe(thr);  /* varname is still reachable */
56446 
56447 	DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
56448 	                     "key=%!O, varname=%!O, value=%!T",
56449 	                     (duk_heaphdr *) key,
56450 	                     (duk_heaphdr *) varname,
56451 	                     (duk_tval *) duk_require_tval(thr, -1)));
56452 
56453 	/* [... put_value] */
56454 
56455 	/*
56456 	 *  Note: although arguments object variable mappings are only established
56457 	 *  for non-strict functions (and a call to a non-strict function created
56458 	 *  the arguments object in question), an inner strict function may be doing
56459 	 *  the actual property write.  Hence the throw_flag applied here comes from
56460 	 *  the property write call.
56461 	 */
56462 
56463 	duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(thr, -1), throw_flag);
56464 
56465 	/* [... put_value] */
56466 }
56467 
56468 /* Lookup 'key' from arguments internal 'map', delete mapping if found.
56469  * Used in E5 Section 10.6 algorithm for [[Delete]].  Note that the
56470  * variable/argument itself (where the map points) is not deleted.
56471  */
56472 DUK_LOCAL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
56473 	duk_hobject *map;
56474 
56475 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
56476 
56477 	if (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
56478 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic delete behavior"));
56479 		return;
56480 	}
56481 
56482 	map = duk_require_hobject(thr, -1);
56483 	DUK_ASSERT(map != NULL);
56484 	duk_pop_unsafe(thr);  /* map is reachable through obj */
56485 
56486 	DUK_DDD(DUK_DDDPRINT("-> have 'map', delete key %!O from map (if exists)); ignore result",
56487 	                     (duk_heaphdr *) key));
56488 
56489 	/* Note: no recursion issue, we can trust 'map' to behave */
56490 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(map));
56491 	DUK_DDD(DUK_DDDPRINT("map before deletion: %!O", (duk_heaphdr *) map));
56492 	(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
56493 	DUK_DDD(DUK_DDDPRINT("map after deletion: %!O", (duk_heaphdr *) map));
56494 }
56495 
56496 /*
56497  *  ECMAScript compliant [[GetOwnProperty]](P), for internal use only.
56498  *
56499  *  If property is found:
56500  *    - Fills descriptor fields to 'out_desc'
56501  *    - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
56502  *      property onto the stack ('undefined' for accessor properties).
56503  *    - Returns non-zero
56504  *
56505  *  If property is not found:
56506  *    - 'out_desc' is left in untouched state (possibly garbage)
56507  *    - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
56508  *      set)
56509  *    - Returns zero
56510  *
56511  *  Notes:
56512  *
56513  *    - Getting a property descriptor may cause an allocation (and hence
56514  *      GC) to take place, hence reachability and refcount of all related
56515  *      values matter.  Reallocation of value stack, properties, etc may
56516  *      invalidate many duk_tval pointers (concretely, those which reside
56517  *      in memory areas subject to reallocation).  However, heap object
56518  *      pointers are never affected (heap objects have stable pointers).
56519  *
56520  *    - The value of a plain property is always reachable and has a non-zero
56521  *      reference count.
56522  *
56523  *    - The value of a virtual property is not necessarily reachable from
56524  *      elsewhere and may have a refcount of zero.  Hence we push it onto
56525  *      the valstack for the caller, which ensures it remains reachable
56526  *      while it is needed.
56527  *
56528  *    - There are no virtual accessor properties.  Hence, all getters and
56529  *      setters are always related to concretely stored properties, which
56530  *      ensures that the get/set functions in the resulting descriptor are
56531  *      reachable and have non-zero refcounts.  Should there be virtual
56532  *      accessor properties later, this would need to change.
56533  */
56534 
56535 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) {
56536 	duk_tval *tv;
56537 
56538 	DUK_DDD(DUK_DDDPRINT("duk_hobject_get_own_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
56539 	                     "arr_idx=%ld (obj -> %!O, key -> %!O)",
56540 	                     (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
56541 	                     (long) flags, (long) arr_idx,
56542 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
56543 
56544 	DUK_ASSERT(thr != NULL);
56545 	DUK_ASSERT(thr->heap != NULL);
56546 	DUK_ASSERT(obj != NULL);
56547 	DUK_ASSERT(key != NULL);
56548 	DUK_ASSERT(out_desc != NULL);
56549 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
56550 
56551 	DUK_STATS_INC(thr->heap, stats_getownpropdesc_count);
56552 
56553 	/* Each code path returning 1 (= found) must fill in all the output
56554 	 * descriptor fields.  We don't do it beforehand because it'd be
56555 	 * unnecessary work if the property isn't found and would happen
56556 	 * multiple times for an inheritance chain.
56557 	 */
56558 	DUK_ASSERT_SET_GARBAGE(out_desc, sizeof(*out_desc));
56559 #if 0
56560 	out_desc->flags = 0;
56561 	out_desc->get = NULL;
56562 	out_desc->set = NULL;
56563 	out_desc->e_idx = -1;
56564 	out_desc->h_idx = -1;
56565 	out_desc->a_idx = -1;
56566 #endif
56567 
56568 	/*
56569 	 *  Try entries part first because it's the common case.
56570 	 *
56571 	 *  Array part lookups are usually handled by the array fast path, and
56572 	 *  are not usually inherited.  Array and entry parts never contain the
56573 	 *  same keys so the entry part vs. array part order doesn't matter.
56574 	 */
56575 
56576 	if (duk_hobject_find_entry(thr->heap, obj, key, &out_desc->e_idx, &out_desc->h_idx)) {
56577 		duk_int_t e_idx = out_desc->e_idx;
56578 		DUK_ASSERT(out_desc->e_idx >= 0);
56579 		out_desc->a_idx = -1;
56580 		out_desc->flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, e_idx);
56581 		out_desc->get = NULL;
56582 		out_desc->set = NULL;
56583 		if (DUK_UNLIKELY(out_desc->flags & DUK_PROPDESC_FLAG_ACCESSOR)) {
56584 			DUK_DDD(DUK_DDDPRINT("-> found accessor property in entry part"));
56585 			out_desc->get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, e_idx);
56586 			out_desc->set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, e_idx);
56587 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
56588 				/* a dummy undefined value is pushed to make valstack
56589 				 * behavior uniform for caller
56590 				 */
56591 				duk_push_undefined(thr);
56592 			}
56593 		} else {
56594 			DUK_DDD(DUK_DDDPRINT("-> found plain property in entry part"));
56595 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
56596 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
56597 				duk_push_tval(thr, tv);
56598 			}
56599 		}
56600 		goto prop_found;
56601 	}
56602 
56603 	/*
56604 	 *  Try array part.
56605 	 */
56606 
56607 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj) && arr_idx != DUK__NO_ARRAY_INDEX) {
56608 		if (arr_idx < DUK_HOBJECT_GET_ASIZE(obj)) {
56609 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
56610 			if (!DUK_TVAL_IS_UNUSED(tv)) {
56611 				DUK_DDD(DUK_DDDPRINT("-> found in array part"));
56612 				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
56613 					duk_push_tval(thr, tv);
56614 				}
56615 				/* implicit attributes */
56616 				out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
56617 				                  DUK_PROPDESC_FLAG_CONFIGURABLE |
56618 				                  DUK_PROPDESC_FLAG_ENUMERABLE;
56619 				out_desc->get = NULL;
56620 				out_desc->set = NULL;
56621 				out_desc->e_idx = -1;
56622 				out_desc->h_idx = -1;
56623 				out_desc->a_idx = (duk_int_t) arr_idx;  /* XXX: limit 2G due to being signed */
56624 				goto prop_found;
56625 			}
56626 		}
56627 	}
56628 
56629 	DUK_DDD(DUK_DDDPRINT("-> not found as a concrete property"));
56630 
56631 	/*
56632 	 *  Not found as a concrete property, check for virtual properties.
56633 	 */
56634 
56635 	if (!DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(obj)) {
56636 		/* Quick skip. */
56637 		goto prop_not_found;
56638 	}
56639 
56640 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
56641 		duk_harray *a;
56642 
56643 		DUK_DDD(DUK_DDDPRINT("array object exotic property get for key: %!O, arr_idx: %ld",
56644 		                     (duk_heaphdr *) key, (long) arr_idx));
56645 
56646 		a = (duk_harray *) obj;
56647 		DUK_HARRAY_ASSERT_VALID(a);
56648 
56649 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
56650 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
56651 
56652 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
56653 				duk_push_uint(thr, (duk_uint_t) a->length);
56654 			}
56655 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
56656 			if (DUK_HARRAY_LENGTH_WRITABLE(a)) {
56657 				out_desc->flags |= DUK_PROPDESC_FLAG_WRITABLE;
56658 			}
56659 			out_desc->get = NULL;
56660 			out_desc->set = NULL;
56661 			out_desc->e_idx = -1;
56662 			out_desc->h_idx = -1;
56663 			out_desc->a_idx = -1;
56664 
56665 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
56666 			goto prop_found_noexotic;  /* cannot be arguments exotic */
56667 		}
56668 	} else if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj)) {
56669 		DUK_DDD(DUK_DDDPRINT("string object exotic property get for key: %!O, arr_idx: %ld",
56670 		                     (duk_heaphdr *) key, (long) arr_idx));
56671 
56672 		/* XXX: charlen; avoid multiple lookups? */
56673 
56674 		if (arr_idx != DUK__NO_ARRAY_INDEX) {
56675 			duk_hstring *h_val;
56676 
56677 			DUK_DDD(DUK_DDDPRINT("array index exists"));
56678 
56679 			h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
56680 			DUK_ASSERT(h_val);
56681 			if (arr_idx < DUK_HSTRING_GET_CHARLEN(h_val)) {
56682 				DUK_DDD(DUK_DDDPRINT("-> found, array index inside string"));
56683 				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
56684 					duk_push_hstring(thr, h_val);
56685 					duk_substring(thr, -1, arr_idx, arr_idx + 1);  /* [str] -> [substr] */
56686 				}
56687 				out_desc->flags = DUK_PROPDESC_FLAG_ENUMERABLE |  /* E5 Section 15.5.5.2 */
56688 				                  DUK_PROPDESC_FLAG_VIRTUAL;
56689 				out_desc->get = NULL;
56690 				out_desc->set = NULL;
56691 				out_desc->e_idx = -1;
56692 				out_desc->h_idx = -1;
56693 				out_desc->a_idx = -1;
56694 
56695 				DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
56696 				goto prop_found_noexotic;  /* cannot be arguments exotic */
56697 			} else {
56698 				/* index is above internal string length -> property is fully normal */
56699 				DUK_DDD(DUK_DDDPRINT("array index outside string -> normal property"));
56700 			}
56701 		} else if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
56702 			duk_hstring *h_val;
56703 
56704 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
56705 
56706 			h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
56707 			DUK_ASSERT(h_val != NULL);
56708 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
56709 				duk_push_uint(thr, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_val));
56710 			}
56711 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;  /* E5 Section 15.5.5.1 */
56712 			out_desc->get = NULL;
56713 			out_desc->set = NULL;
56714 			out_desc->e_idx = -1;
56715 			out_desc->h_idx = -1;
56716 			out_desc->a_idx = -1;
56717 
56718 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
56719 			goto prop_found_noexotic;  /* cannot be arguments exotic */
56720 		}
56721 	}
56722 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
56723 	else if (DUK_HOBJECT_IS_BUFOBJ(obj)) {
56724 		duk_hbufobj *h_bufobj;
56725 		duk_uint_t byte_off;
56726 		duk_small_uint_t elem_size;
56727 
56728 		h_bufobj = (duk_hbufobj *) obj;
56729 		DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
56730 		DUK_DDD(DUK_DDDPRINT("bufobj property get for key: %!O, arr_idx: %ld",
56731 		                     (duk_heaphdr *) key, (long) arr_idx));
56732 
56733 		if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
56734 			DUK_DDD(DUK_DDDPRINT("array index exists"));
56735 
56736 			/* Careful with wrapping: arr_idx upshift may easily wrap, whereas
56737 			 * length downshift won't.
56738 			 */
56739 			if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) {
56740 				byte_off = arr_idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
56741 				elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
56742 				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
56743 					duk_uint8_t *data;
56744 
56745 					if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
56746 						data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
56747 						duk_hbufobj_push_validated_read(thr, h_bufobj, data, elem_size);
56748 					} else {
56749 						DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (read zero)"));
56750 						duk_push_uint(thr, 0);
56751 					}
56752 				}
56753 				out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
56754 				                  DUK_PROPDESC_FLAG_VIRTUAL;
56755 				if (DUK_HOBJECT_GET_CLASS_NUMBER(obj) != DUK_HOBJECT_CLASS_ARRAYBUFFER) {
56756 					/* ArrayBuffer indices are non-standard and are
56757 					 * non-enumerable to avoid their serialization.
56758 					 */
56759 					out_desc->flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
56760 				}
56761 				out_desc->get = NULL;
56762 				out_desc->set = NULL;
56763 				out_desc->e_idx = -1;
56764 				out_desc->h_idx = -1;
56765 				out_desc->a_idx = -1;
56766 
56767 				DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
56768 				goto prop_found_noexotic;  /* cannot be e.g. arguments exotic, since exotic 'traits' are mutually exclusive */
56769 			} else {
56770 				/* index is above internal buffer length -> property is fully normal */
56771 				DUK_DDD(DUK_DDDPRINT("array index outside buffer -> normal property"));
56772 			}
56773 		} else if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
56774 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
56775 
56776 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
56777 				/* Length in elements: take into account shift, but
56778 				 * intentionally don't check the underlying buffer here.
56779 				 */
56780 				duk_push_uint(thr, h_bufobj->length >> h_bufobj->shift);
56781 			}
56782 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
56783 			out_desc->get = NULL;
56784 			out_desc->set = NULL;
56785 			out_desc->e_idx = -1;
56786 			out_desc->h_idx = -1;
56787 			out_desc->a_idx = -1;
56788 
56789 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
56790 			goto prop_found_noexotic;  /* cannot be arguments exotic */
56791 		}
56792 	}
56793 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
56794 
56795 	/* Array properties have exotic behavior but they are concrete,
56796 	 * so no special handling here.
56797 	 *
56798 	 * Arguments exotic behavior (E5 Section 10.6, [[GetOwnProperty]]
56799 	 * is only relevant as a post-check implemented below; hence no
56800 	 * check here.
56801 	 */
56802 
56803 	/*
56804 	 *  Not found as concrete or virtual.
56805 	 */
56806 
56807  prop_not_found:
56808 	DUK_DDD(DUK_DDDPRINT("-> not found (virtual, entry part, or array part)"));
56809 	DUK_STATS_INC(thr->heap, stats_getownpropdesc_miss);
56810 	return 0;
56811 
56812 	/*
56813 	 *  Found.
56814 	 *
56815 	 *  Arguments object has exotic post-processing, see E5 Section 10.6,
56816 	 *  description of [[GetOwnProperty]] variant for arguments.
56817 	 */
56818 
56819  prop_found:
56820 	DUK_DDD(DUK_DDDPRINT("-> property found, checking for arguments exotic post-behavior"));
56821 
56822 	/* Notes:
56823 	 *  - Only numbered indices are relevant, so arr_idx fast reject is good
56824 	 *    (this is valid unless there are more than 4**32-1 arguments).
56825 	 *  - Since variable lookup has no side effects, this can be skipped if
56826 	 *    DUK_GETDESC_FLAG_PUSH_VALUE is not set.
56827 	 */
56828 
56829 	if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
56830 	                 arr_idx != DUK__NO_ARRAY_INDEX &&
56831 	                 (flags & DUK_GETDESC_FLAG_PUSH_VALUE))) {
56832 		duk_propdesc temp_desc;
56833 
56834 		/* Magically bound variable cannot be an accessor.  However,
56835 		 * there may be an accessor property (or a plain property) in
56836 		 * place with magic behavior removed.  This happens e.g. when
56837 		 * a magic property is redefined with defineProperty().
56838 		 * Cannot assert for "not accessor" here.
56839 		 */
56840 
56841 		/* replaces top of stack with new value if necessary */
56842 		DUK_ASSERT((flags & DUK_GETDESC_FLAG_PUSH_VALUE) != 0);
56843 
56844 		/* This can perform a variable lookup but only into a declarative
56845 		 * environment which has no side effects.
56846 		 */
56847 		if (duk__check_arguments_map_for_get(thr, obj, key, &temp_desc)) {
56848 			DUK_DDD(DUK_DDDPRINT("-> arguments exotic behavior overrides result: %!T -> %!T",
56849 			                     (duk_tval *) duk_get_tval(thr, -2),
56850 			                     (duk_tval *) duk_get_tval(thr, -1)));
56851 			/* [... old_result result] -> [... result] */
56852 			duk_remove_m2(thr);
56853 		}
56854 	}
56855 
56856  prop_found_noexotic:
56857 	DUK_STATS_INC(thr->heap, stats_getownpropdesc_hit);
56858 	return 1;
56859 }
56860 
56861 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) {
56862 	DUK_ASSERT(thr != NULL);
56863 	DUK_ASSERT(obj != NULL);
56864 	DUK_ASSERT(key != NULL);
56865 	DUK_ASSERT(out_desc != NULL);
56866 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
56867 
56868 	return duk__get_own_propdesc_raw(thr, obj, key, DUK_HSTRING_GET_ARRIDX_SLOW(key), out_desc, flags);
56869 }
56870 
56871 /*
56872  *  ECMAScript compliant [[GetProperty]](P), for internal use only.
56873  *
56874  *  If property is found:
56875  *    - Fills descriptor fields to 'out_desc'
56876  *    - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
56877  *      property onto the stack ('undefined' for accessor properties).
56878  *    - Returns non-zero
56879  *
56880  *  If property is not found:
56881  *    - 'out_desc' is left in untouched state (possibly garbage)
56882  *    - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
56883  *      set)
56884  *    - Returns zero
56885  *
56886  *  May cause arbitrary side effects and invalidate (most) duk_tval
56887  *  pointers.
56888  */
56889 
56890 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) {
56891 	duk_hobject *curr;
56892 	duk_uint32_t arr_idx;
56893 	duk_uint_t sanity;
56894 
56895 	DUK_ASSERT(thr != NULL);
56896 	DUK_ASSERT(thr->heap != NULL);
56897 	DUK_ASSERT(obj != NULL);
56898 	DUK_ASSERT(key != NULL);
56899 	DUK_ASSERT(out_desc != NULL);
56900 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
56901 
56902 	DUK_STATS_INC(thr->heap, stats_getpropdesc_count);
56903 
56904 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
56905 
56906 	DUK_DDD(DUK_DDDPRINT("duk__get_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
56907 	                     "arr_idx=%ld (obj -> %!O, key -> %!O)",
56908 	                     (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
56909 	                     (long) flags, (long) arr_idx,
56910 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
56911 
56912 	curr = obj;
56913 	DUK_ASSERT(curr != NULL);
56914 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
56915 	do {
56916 		if (duk__get_own_propdesc_raw(thr, curr, key, arr_idx, out_desc, flags)) {
56917 			/* stack contains value (if requested), 'out_desc' is set */
56918 			DUK_STATS_INC(thr->heap, stats_getpropdesc_hit);
56919 			return 1;
56920 		}
56921 
56922 		/* not found in 'curr', next in prototype chain; impose max depth */
56923 		if (DUK_UNLIKELY(sanity-- == 0)) {
56924 			if (flags & DUK_GETDESC_FLAG_IGNORE_PROTOLOOP) {
56925 				/* treat like property not found */
56926 				break;
56927 			} else {
56928 				DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
56929 				DUK_WO_NORETURN(return 0;);
56930 			}
56931 		}
56932 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
56933 	} while (curr != NULL);
56934 
56935 	/* out_desc is left untouched (possibly garbage), caller must use return
56936 	 * value to determine whether out_desc can be looked up
56937 	 */
56938 
56939 	DUK_STATS_INC(thr->heap, stats_getpropdesc_miss);
56940 	return 0;
56941 }
56942 
56943 /*
56944  *  Shallow fast path checks for accessing array elements with numeric
56945  *  indices.  The goal is to try to avoid coercing an array index to an
56946  *  (interned) string for the most common lookups, in particular, for
56947  *  standard Array objects.
56948  *
56949  *  Interning is avoided but only for a very narrow set of cases:
56950  *    - Object has array part, index is within array allocation, and
56951  *      value is not unused (= key exists)
56952  *    - Object has no interfering exotic behavior (e.g. arguments or
56953  *      string object exotic behaviors interfere, array exotic
56954  *      behavior does not).
56955  *
56956  *  Current shortcoming: if key does not exist (even if it is within
56957  *  the array allocation range) a slow path lookup with interning is
56958  *  always required.  This can probably be fixed so that there is a
56959  *  quick fast path for non-existent elements as well, at least for
56960  *  standard Array objects.
56961  */
56962 
56963 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
56964 DUK_LOCAL duk_tval *duk__getprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {
56965 	duk_tval *tv;
56966 	duk_uint32_t idx;
56967 
56968 	DUK_UNREF(thr);
56969 
56970 	if (!(DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
56971 	     !DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
56972 	     !DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj) &&
56973 	     !DUK_HOBJECT_IS_BUFOBJ(obj) &&
56974 	     !DUK_HOBJECT_IS_PROXY(obj))) {
56975 		/* Must have array part and no conflicting exotic behaviors.
56976 		 * Doesn't need to have array special behavior, e.g. Arguments
56977 		 * object has array part.
56978 		 */
56979 		return NULL;
56980 	}
56981 
56982 	/* Arrays never have other exotic behaviors. */
56983 
56984 	DUK_DDD(DUK_DDDPRINT("fast path attempt (no exotic string/arguments/buffer "
56985 	                     "behavior, object has array part)"));
56986 
56987 #if defined(DUK_USE_FASTINT)
56988 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
56989 		idx = duk__tval_fastint_to_arr_idx(tv_key);
56990 	} else
56991 #endif
56992 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
56993 		idx = duk__tval_number_to_arr_idx(tv_key);
56994 	} else {
56995 		DUK_DDD(DUK_DDDPRINT("key is not a number"));
56996 		return NULL;
56997 	}
56998 
56999 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
57000 	 * is 0xffffffffUL.  We don't need to check for that explicitly
57001 	 * because 0xffffffffUL will never be inside object 'a_size'.
57002 	 */
57003 
57004 	if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
57005 		DUK_DDD(DUK_DDDPRINT("key is not an array index or outside array part"));
57006 		return NULL;
57007 	}
57008 	DUK_ASSERT(idx != 0xffffffffUL);
57009 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
57010 
57011 	/* XXX: for array instances we could take a shortcut here and assume
57012 	 * Array.prototype doesn't contain an array index property.
57013 	 */
57014 
57015 	DUK_DDD(DUK_DDDPRINT("key is a valid array index and inside array part"));
57016 	tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
57017 	if (!DUK_TVAL_IS_UNUSED(tv)) {
57018 		DUK_DDD(DUK_DDDPRINT("-> fast path successful"));
57019 		return tv;
57020 	}
57021 
57022 	DUK_DDD(DUK_DDDPRINT("fast path attempt failed, fall back to slow path"));
57023 	return NULL;
57024 }
57025 
57026 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) {
57027 	duk_tval *tv;
57028 	duk_harray *a;
57029 	duk_uint32_t idx;
57030 	duk_uint32_t old_len, new_len;
57031 
57032 	if (!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj) &&
57033 	      DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
57034 	      DUK_HOBJECT_HAS_EXTENSIBLE(obj))) {
57035 		return 0;
57036 	}
57037 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));  /* caller ensures */
57038 
57039 	a = (duk_harray *) obj;
57040 	DUK_HARRAY_ASSERT_VALID(a);
57041 
57042 #if defined(DUK_USE_FASTINT)
57043 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
57044 		idx = duk__tval_fastint_to_arr_idx(tv_key);
57045 	} else
57046 #endif
57047 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
57048 		idx = duk__tval_number_to_arr_idx(tv_key);
57049 	} else {
57050 		DUK_DDD(DUK_DDDPRINT("key is not a number"));
57051 		return 0;
57052 	}
57053 
57054 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
57055 	 * is 0xffffffffUL.  We don't need to check for that explicitly
57056 	 * because 0xffffffffUL will never be inside object 'a_size'.
57057 	 */
57058 
57059 	if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {  /* for resizing of array part, use slow path */
57060 		return 0;
57061 	}
57062 	DUK_ASSERT(idx != 0xffffffffUL);
57063 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
57064 
57065 	old_len = a->length;
57066 
57067 	if (idx >= old_len) {
57068 		DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
57069 		                     "(arr_idx=%ld, old_len=%ld)",
57070 		                     (long) idx, (long) old_len));
57071 		if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
57072 			/* The correct behavior here is either a silent error
57073 			 * or a TypeError, depending on strictness.  Fall back
57074 			 * to the slow path to handle the situation.
57075 			 */
57076 			return 0;
57077 		}
57078 		new_len = idx + 1;
57079 
57080 		((duk_harray *) obj)->length = new_len;
57081 	}
57082 
57083 	tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
57084 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects */
57085 
57086 	DUK_DDD(DUK_DDDPRINT("array fast path success for index %ld", (long) idx));
57087 	return 1;
57088 }
57089 #endif  /* DUK_USE_ARRAY_PROP_FASTPATH */
57090 
57091 /*
57092  *  Fast path for bufobj getprop/putprop
57093  */
57094 
57095 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
57096 DUK_LOCAL duk_bool_t duk__getprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {
57097 	duk_uint32_t idx;
57098 	duk_hbufobj *h_bufobj;
57099 	duk_uint_t byte_off;
57100 	duk_small_uint_t elem_size;
57101 	duk_uint8_t *data;
57102 
57103 	if (!DUK_HOBJECT_IS_BUFOBJ(obj)) {
57104 		return 0;
57105 	}
57106 	h_bufobj = (duk_hbufobj *) obj;
57107 	if (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
57108 		return 0;
57109 	}
57110 
57111 #if defined(DUK_USE_FASTINT)
57112 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
57113 		idx = duk__tval_fastint_to_arr_idx(tv_key);
57114 	} else
57115 #endif
57116 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
57117 		idx = duk__tval_number_to_arr_idx(tv_key);
57118 	} else {
57119 		return 0;
57120 	}
57121 
57122 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
57123 	 * is 0xffffffffUL.  We don't need to check for that explicitly
57124 	 * because 0xffffffffUL will never be inside bufobj length.
57125 	 */
57126 
57127 	/* Careful with wrapping (left shifting idx would be unsafe). */
57128 	if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
57129 		return 0;
57130 	}
57131 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
57132 
57133 	byte_off = idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
57134 	elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
57135 
57136 	if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
57137 		data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
57138 		duk_hbufobj_push_validated_read(thr, h_bufobj, data, elem_size);
57139 	} else {
57140 		DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (read zero)"));
57141 		duk_push_uint(thr, 0);
57142 	}
57143 
57144 	return 1;
57145 }
57146 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
57147 
57148 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
57149 DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val) {
57150 	duk_uint32_t idx;
57151 	duk_hbufobj *h_bufobj;
57152 	duk_uint_t byte_off;
57153 	duk_small_uint_t elem_size;
57154 	duk_uint8_t *data;
57155 
57156 	if (!(DUK_HOBJECT_IS_BUFOBJ(obj) &&
57157 	      DUK_TVAL_IS_NUMBER(tv_val))) {
57158 		return 0;
57159 	}
57160 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));  /* caller ensures; rom objects are never bufobjs now */
57161 
57162 	h_bufobj = (duk_hbufobj *) obj;
57163 	if (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
57164 		return 0;
57165 	}
57166 
57167 #if defined(DUK_USE_FASTINT)
57168 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
57169 		idx = duk__tval_fastint_to_arr_idx(tv_key);
57170 	} else
57171 #endif
57172 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
57173 		idx = duk__tval_number_to_arr_idx(tv_key);
57174 	} else {
57175 		return 0;
57176 	}
57177 
57178 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
57179 	 * is 0xffffffffUL.  We don't need to check for that explicitly
57180 	 * because 0xffffffffUL will never be inside bufobj length.
57181 	 */
57182 
57183 	/* Careful with wrapping (left shifting idx would be unsafe). */
57184 	if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
57185 		return 0;
57186 	}
57187 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
57188 
57189 	byte_off = idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
57190 	elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
57191 
57192 	/* Value is required to be a number in the fast path so there
57193 	 * are no side effects in write coercion.
57194 	 */
57195 	duk_push_tval(thr, tv_val);
57196 	DUK_ASSERT(duk_is_number(thr, -1));
57197 
57198 	if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
57199 		data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
57200 		duk_hbufobj_validated_write(thr, h_bufobj, data, elem_size);
57201 	} else {
57202 		DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (write skipped)"));
57203 	}
57204 
57205 	duk_pop_unsafe(thr);
57206 	return 1;
57207 }
57208 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
57209 
57210 /*
57211  *  GETPROP: ECMAScript property read.
57212  */
57213 
57214 DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
57215 	duk_tval tv_obj_copy;
57216 	duk_tval tv_key_copy;
57217 	duk_hobject *curr = NULL;
57218 	duk_hstring *key = NULL;
57219 	duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
57220 	duk_propdesc desc;
57221 	duk_uint_t sanity;
57222 
57223 	DUK_DDD(DUK_DDDPRINT("getprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
57224 	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
57225 	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));
57226 
57227 	DUK_ASSERT(thr != NULL);
57228 	DUK_ASSERT(thr->heap != NULL);
57229 	DUK_ASSERT(tv_obj != NULL);
57230 	DUK_ASSERT(tv_key != NULL);
57231 
57232 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
57233 
57234 	DUK_STATS_INC(thr->heap, stats_getprop_all);
57235 
57236 	/*
57237 	 *  Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
57238 	 *  them being invalidated by a valstack resize.
57239 	 *
57240 	 *  XXX: this is now an overkill for many fast paths.  Rework this
57241 	 *  to be faster (although switching to a valstack discipline might
57242 	 *  be a better solution overall).
57243 	 */
57244 
57245 	DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
57246 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
57247 	tv_obj = &tv_obj_copy;
57248 	tv_key = &tv_key_copy;
57249 
57250 	/*
57251 	 *  Coercion and fast path processing
57252 	 */
57253 
57254 	switch (DUK_TVAL_GET_TAG(tv_obj)) {
57255 	case DUK_TAG_UNDEFINED:
57256 	case DUK_TAG_NULL: {
57257 		/* Note: unconditional throw */
57258 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
57259 #if defined(DUK_USE_PARANOID_ERRORS)
57260 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
57261 #else
57262 		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot read property %s of %s",
57263 		               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
57264 #endif
57265 		DUK_WO_NORETURN(return 0;);
57266 		break;
57267 	}
57268 
57269 	case DUK_TAG_BOOLEAN: {
57270 		DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
57271 		curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
57272 		break;
57273 	}
57274 
57275 	case DUK_TAG_STRING: {
57276 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
57277 		duk_int_t pop_count;
57278 
57279 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
57280 			/* Symbols (ES2015 or hidden) don't have virtual properties. */
57281 			DUK_DDD(DUK_DDDPRINT("base object is a symbol, start lookup from symbol prototype"));
57282 			curr = thr->builtins[DUK_BIDX_SYMBOL_PROTOTYPE];
57283 			break;
57284 		}
57285 
57286 #if defined(DUK_USE_FASTINT)
57287 		if (DUK_TVAL_IS_FASTINT(tv_key)) {
57288 			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
57289 			DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
57290 			pop_count = 0;
57291 		} else
57292 #endif
57293 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
57294 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
57295 			DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path number; arr_idx %ld", (long) arr_idx));
57296 			pop_count = 0;
57297 		} else {
57298 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57299 			DUK_ASSERT(key != NULL);
57300 			DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
57301 			                     "coercion key is %!T, arr_idx %ld",
57302 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
57303 			pop_count = 1;
57304 		}
57305 
57306 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
57307 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
57308 			duk_pop_n_unsafe(thr, pop_count);
57309 			duk_push_hstring(thr, h);
57310 			duk_substring(thr, -1, arr_idx, arr_idx + 1);  /* [str] -> [substr] */
57311 
57312 			DUK_STATS_INC(thr->heap, stats_getprop_stringidx);
57313 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is an index inside string length "
57314 			                     "after coercion -> return char)",
57315 			                     (duk_tval *) duk_get_tval(thr, -1)));
57316 			return 1;
57317 		}
57318 
57319 		if (pop_count == 0) {
57320 			/* This is a pretty awkward control flow, but we need to recheck the
57321 			 * key coercion here.
57322 			 */
57323 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57324 			DUK_ASSERT(key != NULL);
57325 			DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
57326 			                     "coercion key is %!T, arr_idx %ld",
57327 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
57328 		}
57329 
57330 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
57331 			duk_pop_unsafe(thr);  /* [key] -> [] */
57332 			duk_push_uint(thr, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h));  /* [] -> [res] */
57333 
57334 			DUK_STATS_INC(thr->heap, stats_getprop_stringlen);
57335 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is 'length' after coercion -> "
57336 			                     "return string length)",
57337 			                     (duk_tval *) duk_get_tval(thr, -1)));
57338 			return 1;
57339 		}
57340 
57341 		DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
57342 		curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
57343 		goto lookup;  /* avoid double coercion */
57344 	}
57345 
57346 	case DUK_TAG_OBJECT: {
57347 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
57348 		duk_tval *tmp;
57349 #endif
57350 
57351 		curr = DUK_TVAL_GET_OBJECT(tv_obj);
57352 		DUK_ASSERT(curr != NULL);
57353 
57354 		/* XXX: array .length fast path (important in e.g. loops)? */
57355 
57356 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
57357 		tmp = duk__getprop_shallow_fastpath_array_tval(thr, curr, tv_key);
57358 		if (tmp) {
57359 			duk_push_tval(thr, tmp);
57360 
57361 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is object, key is a number, array part "
57362 			                     "fast path)",
57363 			                     (duk_tval *) duk_get_tval(thr, -1)));
57364 			DUK_STATS_INC(thr->heap, stats_getprop_arrayidx);
57365 			return 1;
57366 		}
57367 #endif
57368 
57369 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
57370 		if (duk__getprop_fastpath_bufobj_tval(thr, curr, tv_key) != 0) {
57371 			/* Read value pushed on stack. */
57372 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is bufobj, key is a number, bufobj "
57373 			                     "fast path)",
57374 			                     (duk_tval *) duk_get_tval(thr, -1)));
57375 			DUK_STATS_INC(thr->heap, stats_getprop_bufobjidx);
57376 			return 1;
57377 		}
57378 #endif
57379 
57380 #if defined(DUK_USE_ES6_PROXY)
57381 		if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(curr))) {
57382 			duk_hobject *h_target;
57383 
57384 			if (duk__proxy_check_prop(thr, curr, DUK_STRIDX_GET, tv_key, &h_target)) {
57385 				/* -> [ ... trap handler ] */
57386 				DUK_DDD(DUK_DDDPRINT("-> proxy object 'get' for key %!T", (duk_tval *) tv_key));
57387 				DUK_STATS_INC(thr->heap, stats_getprop_proxy);
57388 				duk_push_hobject(thr, h_target);  /* target */
57389 				duk_push_tval(thr, tv_key);       /* P */
57390 				duk_push_tval(thr, tv_obj);       /* Receiver: Proxy object */
57391 				duk_call_method(thr, 3 /*nargs*/);
57392 
57393 				/* Target object must be checked for a conflicting
57394 				 * non-configurable property.
57395 				 */
57396 				arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57397 				DUK_ASSERT(key != NULL);
57398 
57399 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
57400 					duk_tval *tv_hook = duk_require_tval(thr, -3);  /* value from hook */
57401 					duk_tval *tv_targ = duk_require_tval(thr, -1);  /* value from target */
57402 					duk_bool_t datadesc_reject;
57403 					duk_bool_t accdesc_reject;
57404 
57405 					DUK_DDD(DUK_DDDPRINT("proxy 'get': target has matching property %!O, check for "
57406 					                     "conflicting property; tv_hook=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
57407 					                     "desc.get=%p, desc.set=%p",
57408 					                     (duk_heaphdr *) key, (duk_tval *) tv_hook, (duk_tval *) tv_targ,
57409 					                     (unsigned long) desc.flags,
57410 					                     (void *) desc.get, (void *) desc.set));
57411 
57412 					datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
57413 					                  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
57414 					                  !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&
57415 					                  !duk_js_samevalue(tv_hook, tv_targ);
57416 					accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
57417 					                 !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
57418 					                 (desc.get == NULL) &&
57419 					                 !DUK_TVAL_IS_UNDEFINED(tv_hook);
57420 					if (datadesc_reject || accdesc_reject) {
57421 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
57422 						DUK_WO_NORETURN(return 0;);
57423 					}
57424 
57425 					duk_pop_2_unsafe(thr);
57426 				} else {
57427 					duk_pop_unsafe(thr);
57428 				}
57429 				return 1;  /* return value */
57430 			}
57431 
57432 			curr = h_target;  /* resume lookup from target */
57433 			DUK_TVAL_SET_OBJECT(tv_obj, curr);
57434 		}
57435 #endif  /* DUK_USE_ES6_PROXY */
57436 
57437 		if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(curr)) {
57438 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57439 			DUK_ASSERT(key != NULL);
57440 
57441 			DUK_STATS_INC(thr->heap, stats_getprop_arguments);
57442 			if (duk__check_arguments_map_for_get(thr, curr, key, &desc)) {
57443 				DUK_DDD(DUK_DDDPRINT("-> %!T (base is object with arguments exotic behavior, "
57444 				                     "key matches magically bound property -> skip standard "
57445 				                     "Get with replacement value)",
57446 				                     (duk_tval *) duk_get_tval(thr, -1)));
57447 
57448 				/* no need for 'caller' post-check, because 'key' must be an array index */
57449 
57450 				duk_remove_m2(thr);  /* [key result] -> [result] */
57451 				return 1;
57452 			}
57453 
57454 			goto lookup;  /* avoid double coercion */
57455 		}
57456 		break;
57457 	}
57458 
57459 	/* Buffer has virtual properties similar to string, but indexed values
57460 	 * are numbers, not 1-byte buffers/strings which would perform badly.
57461 	 */
57462 	case DUK_TAG_BUFFER: {
57463 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
57464 		duk_int_t pop_count;
57465 
57466 		/*
57467 		 *  Because buffer values are often looped over, a number fast path
57468 		 *  is important.
57469 		 */
57470 
57471 #if defined(DUK_USE_FASTINT)
57472 		if (DUK_TVAL_IS_FASTINT(tv_key)) {
57473 			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
57474 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
57475 			pop_count = 0;
57476 		}
57477 		else
57478 #endif
57479 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
57480 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
57481 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
57482 			pop_count = 0;
57483 		} else {
57484 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57485 			DUK_ASSERT(key != NULL);
57486 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
57487 			                     "coercion key is %!T, arr_idx %ld",
57488 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
57489 			pop_count = 1;
57490 		}
57491 
57492 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
57493 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
57494 			duk_pop_n_unsafe(thr, pop_count);
57495 			duk_push_uint(thr, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h))[arr_idx]);
57496 			DUK_STATS_INC(thr->heap, stats_getprop_bufferidx);
57497 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is an index inside buffer length "
57498 			                     "after coercion -> return byte as number)",
57499 			                     (duk_tval *) duk_get_tval(thr, -1)));
57500 			return 1;
57501 		}
57502 
57503 		if (pop_count == 0) {
57504 			/* This is a pretty awkward control flow, but we need to recheck the
57505 			 * key coercion here.
57506 			 */
57507 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57508 			DUK_ASSERT(key != NULL);
57509 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
57510 			                     "coercion key is %!T, arr_idx %ld",
57511 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
57512 		}
57513 
57514 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
57515 			duk_pop_unsafe(thr);  /* [key] -> [] */
57516 			duk_push_uint(thr, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h));  /* [] -> [res] */
57517 			DUK_STATS_INC(thr->heap, stats_getprop_bufferlen);
57518 
57519 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'length' "
57520 			                     "after coercion -> return buffer length)",
57521 			                     (duk_tval *) duk_get_tval(thr, -1)));
57522 			return 1;
57523 		}
57524 
57525 		DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from Uint8Array prototype"));
57526 		curr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
57527 		goto lookup;  /* avoid double coercion */
57528 	}
57529 
57530 	case DUK_TAG_POINTER: {
57531 		DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
57532 		curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
57533 		break;
57534 	}
57535 
57536 	case DUK_TAG_LIGHTFUNC: {
57537 		/* Lightfuncs inherit getter .name and .length from %NativeFunctionPrototype%. */
57538 		DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
57539 		curr = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
57540 		break;
57541 	}
57542 
57543 #if defined(DUK_USE_FASTINT)
57544 	case DUK_TAG_FASTINT:
57545 #endif
57546 	default: {
57547 		/* number */
57548 		DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
57549 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_obj));
57550 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));
57551 		curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
57552 		break;
57553 	}
57554 	}
57555 
57556 	/* key coercion (unless already coerced above) */
57557 	DUK_ASSERT(key == NULL);
57558 	arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57559 	DUK_ASSERT(key != NULL);
57560 	/*
57561 	 *  Property lookup
57562 	 */
57563 
57564  lookup:
57565 	/* [key] (coerced) */
57566 	DUK_ASSERT(curr != NULL);
57567 	DUK_ASSERT(key != NULL);
57568 
57569 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
57570 	do {
57571 		if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
57572 			goto next_in_chain;
57573 		}
57574 
57575 		if (desc.get != NULL) {
57576 			/* accessor with defined getter */
57577 			DUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0);
57578 
57579 			duk_pop_unsafe(thr);              /* [key undefined] -> [key] */
57580 			duk_push_hobject(thr, desc.get);
57581 			duk_push_tval(thr, tv_obj);       /* note: original, uncoerced base */
57582 #if defined(DUK_USE_NONSTD_GETTER_KEY_ARGUMENT)
57583 			duk_dup_m3(thr);
57584 			duk_call_method(thr, 1);          /* [key getter this key] -> [key retval] */
57585 #else
57586 			duk_call_method(thr, 0);          /* [key getter this] -> [key retval] */
57587 #endif
57588 		} else {
57589 			/* [key value] or [key undefined] */
57590 
57591 			/* data property or accessor without getter */
57592 			DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||
57593 			           (desc.get == NULL));
57594 
57595 			/* if accessor without getter, return value is undefined */
57596 			DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||
57597 			           duk_is_undefined(thr, -1));
57598 
57599 			/* Note: for an accessor without getter, falling through to
57600 			 * check for "caller" exotic behavior is unnecessary as
57601 			 * "undefined" will never activate the behavior.  But it does
57602 			 * no harm, so we'll do it anyway.
57603 			 */
57604 		}
57605 
57606 		goto found;  /* [key result] */
57607 
57608 	 next_in_chain:
57609 		/* XXX: option to pretend property doesn't exist if sanity limit is
57610 		 * hit might be useful.
57611 		 */
57612 		if (DUK_UNLIKELY(sanity-- == 0)) {
57613 			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
57614 			DUK_WO_NORETURN(return 0;);
57615 		}
57616 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
57617 	} while (curr != NULL);
57618 
57619 	/*
57620 	 *  Not found
57621 	 */
57622 
57623 	duk_to_undefined(thr, -1);  /* [key] -> [undefined] (default value) */
57624 
57625 	DUK_DDD(DUK_DDDPRINT("-> %!T (not found)", (duk_tval *) duk_get_tval(thr, -1)));
57626 	return 0;
57627 
57628 	/*
57629 	 *  Found; post-processing (Function and arguments objects)
57630 	 */
57631 
57632  found:
57633 	/* [key result] */
57634 
57635 #if !defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
57636 	/* Special behavior for 'caller' property of (non-bound) function objects
57637 	 * and non-strict Arguments objects: if 'caller' -value- (!) is a strict
57638 	 * mode function, throw a TypeError (E5 Sections 15.3.5.4, 10.6).
57639 	 * Quite interestingly, a non-strict function with no formal arguments
57640 	 * will get an arguments object -without- special 'caller' behavior!
57641 	 *
57642 	 * The E5.1 spec is a bit ambiguous if this special behavior applies when
57643 	 * a bound function is the base value (not the 'caller' value): Section
57644 	 * 15.3.4.5 (describing bind()) states that [[Get]] for bound functions
57645 	 * matches that of Section 15.3.5.4 ([[Get]] for Function instances).
57646 	 * However, Section 13.3.5.4 has "NOTE: Function objects created using
57647 	 * Function.prototype.bind use the default [[Get]] internal method."
57648 	 * The current implementation assumes this means that bound functions
57649 	 * should not have the special [[Get]] behavior.
57650 	 *
57651 	 * The E5.1 spec is also a bit unclear if the TypeError throwing is
57652 	 * applied if the 'caller' value is a strict bound function.  The
57653 	 * current implementation will throw even for both strict non-bound
57654 	 * and strict bound functions.
57655 	 *
57656 	 * See test-dev-strict-func-as-caller-prop-value.js for quite extensive
57657 	 * tests.
57658 	 *
57659 	 * This exotic behavior is disabled when the non-standard 'caller' property
57660 	 * is enabled, as it conflicts with the free use of 'caller'.
57661 	 */
57662 	if (key == DUK_HTHREAD_STRING_CALLER(thr) &&
57663 	    DUK_TVAL_IS_OBJECT(tv_obj)) {
57664 		duk_hobject *orig = DUK_TVAL_GET_OBJECT(tv_obj);
57665 		DUK_ASSERT(orig != NULL);
57666 
57667 		if (DUK_HOBJECT_IS_NONBOUND_FUNCTION(orig) ||
57668 		    DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
57669 			duk_hobject *h;
57670 
57671 			/* XXX: The TypeError is currently not applied to bound
57672 			 * functions because the 'strict' flag is not copied by
57673 			 * bind().  This may or may not be correct, the specification
57674 			 * only refers to the value being a "strict mode Function
57675 			 * object" which is ambiguous.
57676 			 */
57677 			DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(orig));
57678 
57679 			h = duk_get_hobject(thr, -1);  /* NULL if not an object */
57680 			if (h &&
57681 			    DUK_HOBJECT_IS_FUNCTION(h) &&
57682 			    DUK_HOBJECT_HAS_STRICT(h)) {
57683 				/* XXX: sufficient to check 'strict', assert for 'is function' */
57684 				DUK_ERROR_TYPE(thr, DUK_STR_STRICT_CALLER_READ);
57685 				DUK_WO_NORETURN(return 0;);
57686 			}
57687 		}
57688 	}
57689 #endif   /* !DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
57690 
57691 	duk_remove_m2(thr);  /* [key result] -> [result] */
57692 
57693 	DUK_DDD(DUK_DDDPRINT("-> %!T (found)", (duk_tval *) duk_get_tval(thr, -1)));
57694 	return 1;
57695 }
57696 
57697 /*
57698  *  HASPROP: ECMAScript property existence check ("in" operator).
57699  *
57700  *  Interestingly, the 'in' operator does not do any coercion of
57701  *  the target object.
57702  */
57703 
57704 DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
57705 	duk_tval tv_key_copy;
57706 	duk_hobject *obj;
57707 	duk_hstring *key;
57708 	duk_uint32_t arr_idx;
57709 	duk_bool_t rc;
57710 	duk_propdesc desc;
57711 
57712 	DUK_DDD(DUK_DDDPRINT("hasprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
57713 	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
57714 	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));
57715 
57716 	DUK_ASSERT(thr != NULL);
57717 	DUK_ASSERT(thr->heap != NULL);
57718 	DUK_ASSERT(tv_obj != NULL);
57719 	DUK_ASSERT(tv_key != NULL);
57720 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
57721 
57722 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
57723 	tv_key = &tv_key_copy;
57724 
57725 	/*
57726 	 *  The 'in' operator requires an object as its right hand side,
57727 	 *  throwing a TypeError unconditionally if this is not the case.
57728 	 *
57729 	 *  However, lightfuncs need to behave like fully fledged objects
57730 	 *  here to be maximally transparent, so we need to handle them
57731 	 *  here.  Same goes for plain buffers which behave like ArrayBuffers.
57732 	 */
57733 
57734 	/* XXX: Refactor key coercion so that it's only called once.  It can't
57735 	 * be trivially lifted here because the object must be type checked
57736 	 * first.
57737 	 */
57738 
57739 	if (DUK_TVAL_IS_OBJECT(tv_obj)) {
57740 		obj = DUK_TVAL_GET_OBJECT(tv_obj);
57741 		DUK_ASSERT(obj != NULL);
57742 
57743 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57744 	} else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
57745 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57746 		if (duk__key_is_plain_buf_ownprop(thr, DUK_TVAL_GET_BUFFER(tv_obj), key, arr_idx)) {
57747 			rc = 1;
57748 			goto pop_and_return;
57749 		}
57750 		obj = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
57751 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
57752 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57753 
57754 		/* If not found, resume existence check from %NativeFunctionPrototype%.
57755 		 * We can just substitute the value in this case; nothing will
57756 		 * need the original base value (as would be the case with e.g.
57757 		 * setters/getters.
57758 		 */
57759 		obj = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
57760 	} else {
57761 		/* Note: unconditional throw */
57762 		DUK_DDD(DUK_DDDPRINT("base object is not an object -> reject"));
57763 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
57764 		DUK_WO_NORETURN(return 0;);
57765 	}
57766 
57767 	/* XXX: fast path for arrays? */
57768 
57769 	DUK_ASSERT(key != NULL);
57770 	DUK_ASSERT(obj != NULL);
57771 	DUK_UNREF(arr_idx);
57772 
57773 #if defined(DUK_USE_ES6_PROXY)
57774 	if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(obj))) {
57775 		duk_hobject *h_target;
57776 		duk_bool_t tmp_bool;
57777 
57778 		/* XXX: the key in 'key in obj' is string coerced before we're called
57779 		 * (which is the required behavior in E5/E5.1/E6) so the key is a string
57780 		 * here already.
57781 		 */
57782 
57783 		if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_HAS, tv_key, &h_target)) {
57784 			/* [ ... key trap handler ] */
57785 			DUK_DDD(DUK_DDDPRINT("-> proxy object 'has' for key %!T", (duk_tval *) tv_key));
57786 			duk_push_hobject(thr, h_target);  /* target */
57787 			duk_push_tval(thr, tv_key);       /* P */
57788 			duk_call_method(thr, 2 /*nargs*/);
57789 			tmp_bool = duk_to_boolean_top_pop(thr);
57790 			if (!tmp_bool) {
57791 				/* Target object must be checked for a conflicting
57792 				 * non-configurable property.
57793 				 */
57794 
57795 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
57796 					DUK_DDD(DUK_DDDPRINT("proxy 'has': target has matching property %!O, check for "
57797 					                     "conflicting property; desc.flags=0x%08lx, "
57798 					                     "desc.get=%p, desc.set=%p",
57799 					                     (duk_heaphdr *) key, (unsigned long) desc.flags,
57800 					                     (void *) desc.get, (void *) desc.set));
57801 					/* XXX: Extensibility check for target uses IsExtensible().  If we
57802 					 * implemented the isExtensible trap and didn't reject proxies as
57803 					 * proxy targets, it should be respected here.
57804 					 */
57805 					if (!((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&  /* property is configurable and */
57806 					      DUK_HOBJECT_HAS_EXTENSIBLE(h_target))) {          /* ... target is extensible */
57807 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
57808 						DUK_WO_NORETURN(return 0;);
57809 					}
57810 				}
57811 			}
57812 
57813 			duk_pop_unsafe(thr);  /* [ key ] -> [] */
57814 			return tmp_bool;
57815 		}
57816 
57817 		obj = h_target;  /* resume check from proxy target */
57818 	}
57819 #endif  /* DUK_USE_ES6_PROXY */
57820 
57821 	/* XXX: inline into a prototype walking loop? */
57822 
57823 	rc = duk__get_propdesc(thr, obj, key, &desc, 0 /*flags*/);  /* don't push value */
57824 	/* fall through */
57825 
57826  pop_and_return:
57827 	duk_pop_unsafe(thr);  /* [ key ] -> [] */
57828 	return rc;
57829 }
57830 
57831 /*
57832  *  HASPROP variant used internally.
57833  *
57834  *  This primitive must never throw an error, callers rely on this.
57835  *  In particular, don't throw an error for prototype loops; instead,
57836  *  pretend like the property doesn't exist if a prototype sanity limit
57837  *  is reached.
57838  *
57839  *  Does not implement proxy behavior: if applied to a proxy object,
57840  *  returns key existence on the proxy object itself.
57841  */
57842 
57843 DUK_INTERNAL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
57844 	duk_propdesc dummy;
57845 
57846 	DUK_ASSERT(thr != NULL);
57847 	DUK_ASSERT(thr->heap != NULL);
57848 	DUK_ASSERT(obj != NULL);
57849 	DUK_ASSERT(key != NULL);
57850 
57851 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
57852 
57853 	return duk__get_propdesc(thr, obj, key, &dummy, DUK_GETDESC_FLAG_IGNORE_PROTOLOOP);  /* don't push value */
57854 }
57855 
57856 /*
57857  *  Helper: handle Array object 'length' write which automatically
57858  *  deletes properties, see E5 Section 15.4.5.1, step 3.  This is
57859  *  quite tricky to get right.
57860  *
57861  *  Used by duk_hobject_putprop().
57862  */
57863 
57864 /* Coerce a new .length candidate to a number and check that it's a valid
57865  * .length.
57866  */
57867 DUK_LOCAL duk_uint32_t duk__to_new_array_length_checked(duk_hthread *thr, duk_tval *tv) {
57868 	duk_uint32_t res;
57869 	duk_double_t d;
57870 
57871 #if !defined(DUK_USE_PREFER_SIZE)
57872 #if defined(DUK_USE_FASTINT)
57873 	/* When fastints are enabled, the most interesting case is assigning
57874 	 * a fastint to .length (e.g. arr.length = 0).
57875 	 */
57876 	if (DUK_TVAL_IS_FASTINT(tv)) {
57877 		/* Very common case. */
57878 		duk_int64_t fi;
57879 		fi = DUK_TVAL_GET_FASTINT(tv);
57880 		if (fi < 0 || fi > DUK_I64_CONSTANT(0xffffffff)) {
57881 			goto fail_range;
57882 		}
57883 		return (duk_uint32_t) fi;
57884 	}
57885 #else  /* DUK_USE_FASTINT */
57886 	/* When fastints are not enabled, the most interesting case is any
57887 	 * number.
57888 	 */
57889 	if (DUK_TVAL_IS_DOUBLE(tv)) {
57890 		d = DUK_TVAL_GET_NUMBER(tv);
57891 	}
57892 #endif  /* DUK_USE_FASTINT */
57893 	else
57894 #endif  /* !DUK_USE_PREFER_SIZE */
57895 	{
57896 		/* In all other cases, and when doing a size optimized build,
57897 		 * fall back to the comprehensive handler.
57898 		 */
57899 		d = duk_js_tonumber(thr, tv);
57900 	}
57901 
57902 	/* Refuse to update an Array's 'length' to a value outside the
57903 	 * 32-bit range.  Negative zero is accepted as zero.
57904 	 */
57905 	res = duk_double_to_uint32_t(d);
57906 	if ((duk_double_t) res != d) {
57907 		goto fail_range;
57908 	}
57909 
57910 	return res;
57911 
57912  fail_range:
57913 	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARRAY_LENGTH);
57914 	DUK_WO_NORETURN(return 0;);
57915 }
57916 
57917 /* Delete elements required by a smaller length, taking into account
57918  * potentially non-configurable elements.  Returns non-zero if all
57919  * elements could be deleted, and zero if all or some elements could
57920  * not be deleted.  Also writes final "target length" to 'out_result_len'.
57921  * This is the length value that should go into the 'length' property
57922  * (must be set by the caller).  Never throws an error.
57923  */
57924 DUK_LOCAL
57925 duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
57926                                                 duk_hobject *obj,
57927                                                 duk_uint32_t old_len,
57928                                                 duk_uint32_t new_len,
57929                                                 duk_bool_t force_flag,
57930                                                 duk_uint32_t *out_result_len) {
57931 	duk_uint32_t target_len;
57932 	duk_uint_fast32_t i;
57933 	duk_uint32_t arr_idx;
57934 	duk_hstring *key;
57935 	duk_tval *tv;
57936 	duk_bool_t rc;
57937 
57938 	DUK_DDD(DUK_DDDPRINT("new array length smaller than old (%ld -> %ld), "
57939 	                     "probably need to remove elements",
57940 	                     (long) old_len, (long) new_len));
57941 
57942 	/*
57943 	 *  New length is smaller than old length, need to delete properties above
57944 	 *  the new length.
57945 	 *
57946 	 *  If array part exists, this is straightforward: array entries cannot
57947 	 *  be non-configurable so this is guaranteed to work.
57948 	 *
57949 	 *  If array part does not exist, array-indexed values are scattered
57950 	 *  in the entry part, and some may not be configurable (preventing length
57951 	 *  from becoming lower than their index + 1).  To handle the algorithm
57952 	 *  in E5 Section 15.4.5.1, step l correctly, we scan the entire property
57953 	 *  set twice.
57954 	 */
57955 
57956 	DUK_ASSERT(thr != NULL);
57957 	DUK_ASSERT(obj != NULL);
57958 	DUK_ASSERT(new_len < old_len);
57959 	DUK_ASSERT(out_result_len != NULL);
57960 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
57961 
57962 	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));
57963 	DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(obj));
57964 
57965 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
57966 		/*
57967 		 *  All defined array-indexed properties are in the array part
57968 		 *  (we assume the array part is comprehensive), and all array
57969 		 *  entries are writable, configurable, and enumerable.  Thus,
57970 		 *  nothing can prevent array entries from being deleted.
57971 		 */
57972 
57973 		DUK_DDD(DUK_DDDPRINT("have array part, easy case"));
57974 
57975 		if (old_len < DUK_HOBJECT_GET_ASIZE(obj)) {
57976 			/* XXX: assertion that entries >= old_len are already unused */
57977 			i = old_len;
57978 		} else {
57979 			i = DUK_HOBJECT_GET_ASIZE(obj);
57980 		}
57981 		DUK_ASSERT(i <= DUK_HOBJECT_GET_ASIZE(obj));
57982 
57983 		while (i > new_len) {
57984 			i--;
57985 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
57986 			DUK_TVAL_SET_UNUSED_UPDREF(thr, tv);  /* side effects */
57987 		}
57988 
57989 		*out_result_len = new_len;
57990 		return 1;
57991 	} else {
57992 		/*
57993 		 *  Entries part is a bit more complex.
57994 		 */
57995 
57996 		/* Stage 1: find highest preventing non-configurable entry (if any).
57997 		 * When forcing, ignore non-configurability.
57998 		 */
57999 
58000 		DUK_DDD(DUK_DDDPRINT("no array part, slow case"));
58001 
58002 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 1: find target_len "
58003 		                     "(highest preventing non-configurable entry (if any))"));
58004 
58005 		target_len = new_len;
58006 		if (force_flag) {
58007 			DUK_DDD(DUK_DDDPRINT("array length write, no array part; force flag -> skip stage 1"));
58008 			goto skip_stage1;
58009 		}
58010 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
58011 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
58012 			if (!key) {
58013 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
58014 				continue;
58015 			}
58016 			if (!DUK_HSTRING_HAS_ARRIDX(key)) {
58017 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
58018 				continue;
58019 			}
58020 
58021 			DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key));  /* XXX: macro checks for array index flag, which is unnecessary here */
58022 			arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
58023 			DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
58024 			DUK_ASSERT(arr_idx < old_len);  /* consistency requires this */
58025 
58026 			if (arr_idx < new_len) {
58027 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below new_len",
58028 				                     (long) i, (long) arr_idx));
58029 				continue;
58030 			}
58031 			if (DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)) {
58032 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is a relevant array index %ld, but configurable",
58033 				                     (long) i, (long) arr_idx));
58034 				continue;
58035 			}
58036 
58037 			/* relevant array index is non-configurable, blocks write */
58038 			if (arr_idx >= target_len) {
58039 				DUK_DDD(DUK_DDDPRINT("entry at index %ld has arr_idx %ld, is not configurable, "
58040 				                     "update target_len %ld -> %ld",
58041 				                     (long) i, (long) arr_idx, (long) target_len,
58042 				                     (long) (arr_idx + 1)));
58043 				target_len = arr_idx + 1;
58044 			}
58045 		}
58046 	 skip_stage1:
58047 
58048 		/* stage 2: delete configurable entries above target length */
58049 
58050 		DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld, target_len=%ld",
58051 		                     (long) old_len, (long) new_len, (long) target_len));
58052 
58053 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 2: remove "
58054 		                     "entries >= target_len"));
58055 
58056 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
58057 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
58058 			if (!key) {
58059 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
58060 				continue;
58061 			}
58062 			if (!DUK_HSTRING_HAS_ARRIDX(key)) {
58063 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
58064 				continue;
58065 			}
58066 
58067 			DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key));  /* XXX: macro checks for array index flag, which is unnecessary here */
58068 			arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
58069 			DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
58070 			DUK_ASSERT(arr_idx < old_len);  /* consistency requires this */
58071 
58072 			if (arr_idx < target_len) {
58073 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below target_len",
58074 				                     (long) i, (long) arr_idx));
58075 				continue;
58076 			}
58077 			DUK_ASSERT(force_flag || DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i));  /* stage 1 guarantees */
58078 
58079 			DUK_DDD(DUK_DDDPRINT("delete entry index %ld: key is array index %ld",
58080 			                     (long) i, (long) arr_idx));
58081 
58082 			/*
58083 			 *  Slow delete, but we don't care as we're already in a very slow path.
58084 			 *  The delete always succeeds: key has no exotic behavior, property
58085 			 *  is configurable, and no resize occurs.
58086 			 */
58087 			rc = duk_hobject_delprop_raw(thr, obj, key, force_flag ? DUK_DELPROP_FLAG_FORCE : 0);
58088 			DUK_UNREF(rc);
58089 			DUK_ASSERT(rc != 0);
58090 		}
58091 
58092 		/* stage 3: update length (done by caller), decide return code */
58093 
58094 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 3: update length (done by caller)"));
58095 
58096 		*out_result_len = target_len;
58097 
58098 		if (target_len == new_len) {
58099 			DUK_DDD(DUK_DDDPRINT("target_len matches new_len, return success"));
58100 			return 1;
58101 		}
58102 		DUK_DDD(DUK_DDDPRINT("target_len does not match new_len (some entry prevented "
58103 		                     "full length adjustment), return error"));
58104 		return 0;
58105 	}
58106 
58107 	DUK_UNREACHABLE();
58108 }
58109 
58110 /* XXX: is valstack top best place for argument? */
58111 DUK_LOCAL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj) {
58112 	duk_harray *a;
58113 	duk_uint32_t old_len;
58114 	duk_uint32_t new_len;
58115 	duk_uint32_t result_len;
58116 	duk_bool_t rc;
58117 
58118 	DUK_DDD(DUK_DDDPRINT("handling a put operation to array 'length' exotic property, "
58119 	                     "new val: %!T",
58120 	                     (duk_tval *) duk_get_tval(thr, -1)));
58121 
58122 	DUK_ASSERT(thr != NULL);
58123 	DUK_ASSERT(obj != NULL);
58124 
58125 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58126 
58127 	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));
58128 	DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(obj));
58129 	a = (duk_harray *) obj;
58130 	DUK_HARRAY_ASSERT_VALID(a);
58131 
58132 	DUK_ASSERT(duk_is_valid_index(thr, -1));
58133 
58134 	/*
58135 	 *  Get old and new length
58136 	 */
58137 
58138 	old_len = a->length;
58139 	new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_NEGIDX(thr, -1));
58140 	DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) old_len, (long) new_len));
58141 
58142 	/*
58143 	 *  Writability check
58144 	 */
58145 
58146 	if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
58147 		DUK_DDD(DUK_DDDPRINT("length is not writable, fail"));
58148 		return 0;
58149 	}
58150 
58151 	/*
58152 	 *  New length not lower than old length => no changes needed
58153 	 *  (not even array allocation).
58154 	 */
58155 
58156 	if (new_len >= old_len) {
58157 		DUK_DDD(DUK_DDDPRINT("new length is same or higher than old length, just update length, no deletions"));
58158 		a->length = new_len;
58159 		return 1;
58160 	}
58161 
58162 	DUK_DDD(DUK_DDDPRINT("new length is lower than old length, probably must delete entries"));
58163 
58164 	/*
58165 	 *  New length lower than old length => delete elements, then
58166 	 *  update length.
58167 	 *
58168 	 *  Note: even though a bunch of elements have been deleted, the 'desc' is
58169 	 *  still valid as properties haven't been resized (and entries compacted).
58170 	 */
58171 
58172 	rc = duk__handle_put_array_length_smaller(thr, obj, old_len, new_len, 0 /*force_flag*/, &result_len);
58173 	DUK_ASSERT(result_len >= new_len && result_len <= old_len);
58174 
58175 	a->length = result_len;
58176 
58177 	/* XXX: shrink array allocation or entries compaction here? */
58178 
58179 	return rc;
58180 }
58181 
58182 /*
58183  *  PUTPROP: ECMAScript property write.
58184  *
58185  *  Unlike ECMAScript primitive which returns nothing, returns 1 to indicate
58186  *  success and 0 to indicate failure (assuming throw is not set).
58187  *
58188  *  This is an extremely tricky function.  Some examples:
58189  *
58190  *    * Currently a decref may trigger a GC, which may compact an object's
58191  *      property allocation.  Consequently, any entry indices (e_idx) will
58192  *      be potentially invalidated by a decref.
58193  *
58194  *    * Exotic behaviors (strings, arrays, arguments object) require,
58195  *      among other things:
58196  *
58197  *      - Preprocessing before and postprocessing after an actual property
58198  *        write.  For example, array index write requires pre-checking the
58199  *        array 'length' property for access control, and may require an
58200  *        array 'length' update after the actual write has succeeded (but
58201  *        not if it fails).
58202  *
58203  *      - Deletion of multiple entries, as a result of array 'length' write.
58204  *
58205  *    * Input values are taken as pointers which may point to the valstack.
58206  *      If valstack is resized because of the put (this may happen at least
58207  *      when the array part is abandoned), the pointers can be invalidated.
58208  *      (We currently make a copy of all of the input values to avoid issues.)
58209  */
58210 
58211 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) {
58212 	duk_tval tv_obj_copy;
58213 	duk_tval tv_key_copy;
58214 	duk_tval tv_val_copy;
58215 	duk_hobject *orig = NULL;  /* NULL if tv_obj is primitive */
58216 	duk_hobject *curr;
58217 	duk_hstring *key = NULL;
58218 	duk_propdesc desc;
58219 	duk_tval *tv;
58220 	duk_uint32_t arr_idx;
58221 	duk_bool_t rc;
58222 	duk_int_t e_idx;
58223 	duk_uint_t sanity;
58224 	duk_uint32_t new_array_length = 0;  /* 0 = no update */
58225 
58226 	DUK_DDD(DUK_DDDPRINT("putprop: thr=%p, obj=%p, key=%p, val=%p, throw=%ld "
58227 	                     "(obj -> %!T, key -> %!T, val -> %!T)",
58228 	                     (void *) thr, (void *) tv_obj, (void *) tv_key, (void *) tv_val,
58229 	                     (long) throw_flag, (duk_tval *) tv_obj, (duk_tval *) tv_key, (duk_tval *) tv_val));
58230 
58231 	DUK_ASSERT(thr != NULL);
58232 	DUK_ASSERT(thr->heap != NULL);
58233 	DUK_ASSERT(tv_obj != NULL);
58234 	DUK_ASSERT(tv_key != NULL);
58235 	DUK_ASSERT(tv_val != NULL);
58236 
58237 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58238 
58239 	DUK_STATS_INC(thr->heap, stats_putprop_all);
58240 
58241 	/*
58242 	 *  Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
58243 	 *  them being invalidated by a valstack resize.
58244 	 *
58245 	 *  XXX: this is an overkill for some paths, so optimize this later
58246 	 *  (or maybe switch to a stack arguments model entirely).
58247 	 */
58248 
58249 	DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
58250 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
58251 	DUK_TVAL_SET_TVAL(&tv_val_copy, tv_val);
58252 	tv_obj = &tv_obj_copy;
58253 	tv_key = &tv_key_copy;
58254 	tv_val = &tv_val_copy;
58255 
58256 	/*
58257 	 *  Coercion and fast path processing.
58258 	 */
58259 
58260 	switch (DUK_TVAL_GET_TAG(tv_obj)) {
58261 	case DUK_TAG_UNDEFINED:
58262 	case DUK_TAG_NULL: {
58263 		/* Note: unconditional throw */
58264 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject (object=%!iT)",
58265 		                     (duk_tval *) tv_obj));
58266 #if defined(DUK_USE_PARANOID_ERRORS)
58267 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
58268 #else
58269 		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
58270 		               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
58271 #endif
58272 		DUK_WO_NORETURN(return 0;);
58273 		break;
58274 	}
58275 
58276 	case DUK_TAG_BOOLEAN: {
58277 		DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
58278 		curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
58279 		break;
58280 	}
58281 
58282 	case DUK_TAG_STRING: {
58283 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
58284 
58285 		/*
58286 		 *  Note: currently no fast path for array index writes.
58287 		 *  They won't be possible anyway as strings are immutable.
58288 		 */
58289 
58290 		DUK_ASSERT(key == NULL);
58291 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
58292 		DUK_ASSERT(key != NULL);
58293 
58294 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
58295 			/* Symbols (ES2015 or hidden) don't have virtual properties. */
58296 			curr = thr->builtins[DUK_BIDX_SYMBOL_PROTOTYPE];
58297 			goto lookup;
58298 		}
58299 
58300 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
58301 			goto fail_not_writable;
58302 		}
58303 
58304 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
58305 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
58306 			goto fail_not_writable;
58307 		}
58308 
58309 		DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
58310 		curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
58311 		goto lookup;  /* avoid double coercion */
58312 	}
58313 
58314 	case DUK_TAG_OBJECT: {
58315 		orig = DUK_TVAL_GET_OBJECT(tv_obj);
58316 		DUK_ASSERT(orig != NULL);
58317 
58318 #if defined(DUK_USE_ROM_OBJECTS)
58319 		/* With this check in place fast paths won't need read-only
58320 		 * object checks.  This is technically incorrect if there are
58321 		 * setters that cause no writes to ROM objects, but current
58322 		 * built-ins don't have such setters.
58323 		 */
58324 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
58325 			DUK_DD(DUK_DDPRINT("attempt to putprop on read-only target object"));
58326 			goto fail_not_writable_no_pop;  /* Must avoid duk_pop() in exit path */
58327 		}
58328 #endif
58329 
58330 		/* The fast path for array property put is not fully compliant:
58331 		 * If one places conflicting number-indexed properties into
58332 		 * Array.prototype (for example, a non-writable Array.prototype[7])
58333 		 * the fast path will incorrectly ignore them.
58334 		 *
58335 		 * This fast path could be made compliant by falling through
58336 		 * to the slow path if the previous value was UNUSED.  This would
58337 		 * also remove the need to check for extensibility.  Right now a
58338 		 * non-extensible array is slower than an extensible one as far
58339 		 * as writes are concerned.
58340 		 *
58341 		 * The fast path behavior is documented in more detail here:
58342 		 * tests/ecmascript/test-misc-array-fast-write.js
58343 		 */
58344 
58345 		/* XXX: array .length? */
58346 
58347 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
58348 		if (duk__putprop_shallow_fastpath_array_tval(thr, orig, tv_key, tv_val) != 0) {
58349 			DUK_DDD(DUK_DDDPRINT("array fast path success"));
58350 			DUK_STATS_INC(thr->heap, stats_putprop_arrayidx);
58351 			return 1;
58352 		}
58353 #endif
58354 
58355 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
58356 		if (duk__putprop_fastpath_bufobj_tval(thr, orig, tv_key, tv_val) != 0) {
58357 			DUK_DDD(DUK_DDDPRINT("base is bufobj, key is a number, bufobj fast path"));
58358 			DUK_STATS_INC(thr->heap, stats_putprop_bufobjidx);
58359 			return 1;
58360 		}
58361 #endif
58362 
58363 #if defined(DUK_USE_ES6_PROXY)
58364 		if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(orig))) {
58365 			duk_hobject *h_target;
58366 			duk_bool_t tmp_bool;
58367 
58368 			if (duk__proxy_check_prop(thr, orig, DUK_STRIDX_SET, tv_key, &h_target)) {
58369 				/* -> [ ... trap handler ] */
58370 				DUK_DDD(DUK_DDDPRINT("-> proxy object 'set' for key %!T", (duk_tval *) tv_key));
58371 				DUK_STATS_INC(thr->heap, stats_putprop_proxy);
58372 				duk_push_hobject(thr, h_target);  /* target */
58373 				duk_push_tval(thr, tv_key);       /* P */
58374 				duk_push_tval(thr, tv_val);       /* V */
58375 				duk_push_tval(thr, tv_obj);       /* Receiver: Proxy object */
58376 				duk_call_method(thr, 4 /*nargs*/);
58377 				tmp_bool = duk_to_boolean_top_pop(thr);
58378 				if (!tmp_bool) {
58379 					goto fail_proxy_rejected;
58380 				}
58381 
58382 				/* Target object must be checked for a conflicting
58383 				 * non-configurable property.
58384 				 */
58385 				arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
58386 				DUK_ASSERT(key != NULL);
58387 
58388 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
58389 					duk_tval *tv_targ = duk_require_tval(thr, -1);
58390 					duk_bool_t datadesc_reject;
58391 					duk_bool_t accdesc_reject;
58392 
58393 					DUK_DDD(DUK_DDDPRINT("proxy 'set': target has matching property %!O, check for "
58394 					                     "conflicting property; tv_val=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
58395 					                     "desc.get=%p, desc.set=%p",
58396 					                     (duk_heaphdr *) key, (duk_tval *) tv_val, (duk_tval *) tv_targ,
58397 					                     (unsigned long) desc.flags,
58398 					                     (void *) desc.get, (void *) desc.set));
58399 
58400 					datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
58401 					                  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
58402 					                  !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&
58403 					                  !duk_js_samevalue(tv_val, tv_targ);
58404 					accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
58405 					                 !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
58406 					                 (desc.set == NULL);
58407 					if (datadesc_reject || accdesc_reject) {
58408 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
58409 						DUK_WO_NORETURN(return 0;);
58410 					}
58411 
58412 					duk_pop_2_unsafe(thr);
58413 				} else {
58414 					duk_pop_unsafe(thr);
58415 				}
58416 				return 1;  /* success */
58417 			}
58418 
58419 			orig = h_target;  /* resume write to target */
58420 			DUK_TVAL_SET_OBJECT(tv_obj, orig);
58421 		}
58422 #endif  /* DUK_USE_ES6_PROXY */
58423 
58424 		curr = orig;
58425 		break;
58426 	}
58427 
58428 	case DUK_TAG_BUFFER: {
58429 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
58430 		duk_int_t pop_count = 0;
58431 
58432 		/*
58433 		 *  Because buffer values may be looped over and read/written
58434 		 *  from, an array index fast path is important.
58435 		 */
58436 
58437 #if defined(DUK_USE_FASTINT)
58438 		if (DUK_TVAL_IS_FASTINT(tv_key)) {
58439 			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
58440 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
58441 			pop_count = 0;
58442 		} else
58443 #endif
58444 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
58445 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
58446 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
58447 			pop_count = 0;
58448 		} else {
58449 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
58450 			DUK_ASSERT(key != NULL);
58451 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
58452 			                     "coercion key is %!T, arr_idx %ld",
58453 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
58454 			pop_count = 1;
58455 		}
58456 
58457 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
58458 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
58459 			duk_uint8_t *data;
58460 			DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
58461 			data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
58462 
58463 			/* XXX: duk_to_int() ensures we'll get 8 lowest bits as
58464 			 * as input is within duk_int_t range (capped outside it).
58465 			 */
58466 #if defined(DUK_USE_FASTINT)
58467 			/* Buffer writes are often integers. */
58468 			if (DUK_TVAL_IS_FASTINT(tv_val)) {
58469 				data[arr_idx] = (duk_uint8_t) DUK_TVAL_GET_FASTINT_U32(tv_val);
58470 			}
58471 			else
58472 #endif
58473 			{
58474 				duk_push_tval(thr, tv_val);
58475 				data[arr_idx] = (duk_uint8_t) duk_to_uint32(thr, -1);
58476 				pop_count++;
58477 			}
58478 
58479 			duk_pop_n_unsafe(thr, pop_count);
58480 			DUK_DDD(DUK_DDDPRINT("result: success (buffer data write)"));
58481 			DUK_STATS_INC(thr->heap, stats_putprop_bufferidx);
58482 			return 1;
58483 		}
58484 
58485 		if (pop_count == 0) {
58486 			/* This is a pretty awkward control flow, but we need to recheck the
58487 			 * key coercion here.
58488 			 */
58489 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
58490 			DUK_ASSERT(key != NULL);
58491 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
58492 			                     "coercion key is %!T, arr_idx %ld",
58493 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
58494 		}
58495 
58496 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
58497 			goto fail_not_writable;
58498 		}
58499 
58500 		DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from Uint8Array prototype"));
58501 		curr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
58502 		goto lookup;  /* avoid double coercion */
58503 	}
58504 
58505 	case DUK_TAG_POINTER: {
58506 		DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
58507 		curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
58508 		break;
58509 	}
58510 
58511 	case DUK_TAG_LIGHTFUNC: {
58512 		/* Lightfuncs have no own properties and are considered non-extensible.
58513 		 * However, the write may be captured by an inherited setter which
58514 		 * means we can't stop the lookup here.
58515 		 */
58516 		DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
58517 		curr = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
58518 		break;
58519 	}
58520 
58521 #if defined(DUK_USE_FASTINT)
58522 	case DUK_TAG_FASTINT:
58523 #endif
58524 	default: {
58525 		/* number */
58526 		DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
58527 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));
58528 		curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
58529 		break;
58530 	}
58531 	}
58532 
58533 	DUK_ASSERT(key == NULL);
58534 	arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
58535 	DUK_ASSERT(key != NULL);
58536 
58537  lookup:
58538 
58539 	/*
58540 	 *  Check whether the property already exists in the prototype chain.
58541 	 *  Note that the actual write goes into the original base object
58542 	 *  (except if an accessor property captures the write).
58543 	 */
58544 
58545 	/* [key] */
58546 
58547 	DUK_ASSERT(curr != NULL);
58548 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
58549 	do {
58550 		if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
58551 			goto next_in_chain;
58552 		}
58553 
58554 		if (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
58555 			/*
58556 			 *  Found existing accessor property (own or inherited).
58557 			 *  Call setter with 'this' set to orig, and value as the only argument.
58558 			 *  Setter calls are OK even for ROM objects.
58559 			 *
58560 			 *  Note: no exotic arguments object behavior, because [[Put]] never
58561 			 *  calls [[DefineOwnProperty]] (E5 Section 8.12.5, step 5.b).
58562 			 */
58563 
58564 			duk_hobject *setter;
58565 
58566 			DUK_DD(DUK_DDPRINT("put to an own or inherited accessor, calling setter"));
58567 
58568 			setter = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, curr, desc.e_idx);
58569 			if (!setter) {
58570 				goto fail_no_setter;
58571 			}
58572 			duk_push_hobject(thr, setter);
58573 			duk_push_tval(thr, tv_obj);  /* note: original, uncoerced base */
58574 			duk_push_tval(thr, tv_val);  /* [key setter this val] */
58575 #if defined(DUK_USE_NONSTD_SETTER_KEY_ARGUMENT)
58576 			duk_dup_m4(thr);
58577 			duk_call_method(thr, 2);     /* [key setter this val key] -> [key retval] */
58578 #else
58579 			duk_call_method(thr, 1);     /* [key setter this val] -> [key retval] */
58580 #endif
58581 			duk_pop_unsafe(thr);         /* ignore retval -> [key] */
58582 			goto success_no_arguments_exotic;
58583 		}
58584 
58585 		if (orig == NULL) {
58586 			/*
58587 			 *  Found existing own or inherited plain property, but original
58588 			 *  base is a primitive value.
58589 			 */
58590 			DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
58591 			goto fail_base_primitive;
58592 		}
58593 
58594 		if (curr != orig) {
58595 			/*
58596 			 *  Found existing inherited plain property.
58597 			 *  Do an access control check, and if OK, write
58598 			 *  new property to 'orig'.
58599 			 */
58600 			if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
58601 				DUK_DD(DUK_DDPRINT("found existing inherited plain property, but original object is not extensible"));
58602 				goto fail_not_extensible;
58603 			}
58604 			if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
58605 				DUK_DD(DUK_DDPRINT("found existing inherited plain property, original object is extensible, but inherited property is not writable"));
58606 				goto fail_not_writable;
58607 			}
58608 			DUK_DD(DUK_DDPRINT("put to new property, object extensible, inherited property found and is writable"));
58609 			goto create_new;
58610 		} else {
58611 			/*
58612 			 *  Found existing own (non-inherited) plain property.
58613 			 *  Do an access control check and update in place.
58614 			 */
58615 
58616 			if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
58617 				DUK_DD(DUK_DDPRINT("found existing own (non-inherited) plain property, but property is not writable"));
58618 				goto fail_not_writable;
58619 			}
58620 			if (desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) {
58621 				DUK_DD(DUK_DDPRINT("found existing own (non-inherited) virtual property, property is writable"));
58622 
58623 				if (DUK_HOBJECT_IS_ARRAY(curr)) {
58624 					/*
58625 					 *  Write to 'length' of an array is a very complex case
58626 					 *  handled in a helper which updates both the array elements
58627 					 *  and writes the new 'length'.  The write may result in an
58628 					 *  unconditional RangeError or a partial write (indicated
58629 					 *  by a return code).
58630 					 *
58631 					 *  Note: the helper has an unnecessary writability check
58632 					 *  for 'length', we already know it is writable.
58633 					 */
58634 					DUK_ASSERT(key == DUK_HTHREAD_STRING_LENGTH(thr));  /* only virtual array property */
58635 
58636 					DUK_DDD(DUK_DDDPRINT("writing existing 'length' property to array exotic, invoke complex helper"));
58637 
58638 					/* XXX: the helper currently assumes stack top contains new
58639 					 * 'length' value and the whole calling convention is not very
58640 					 * compatible with what we need.
58641 					 */
58642 
58643 					duk_push_tval(thr, tv_val);  /* [key val] */
58644 					rc = duk__handle_put_array_length(thr, orig);
58645 					duk_pop_unsafe(thr);  /* [key val] -> [key] */
58646 					if (!rc) {
58647 						goto fail_array_length_partial;
58648 					}
58649 
58650 					/* key is 'length', cannot match argument exotic behavior */
58651 					goto success_no_arguments_exotic;
58652 				}
58653 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
58654 				else if (DUK_HOBJECT_IS_BUFOBJ(curr)) {
58655 					duk_hbufobj *h_bufobj;
58656 					duk_uint_t byte_off;
58657 					duk_small_uint_t elem_size;
58658 
58659 					h_bufobj = (duk_hbufobj *) curr;
58660 					DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
58661 
58662 					DUK_DD(DUK_DDPRINT("writable virtual property is in buffer object"));
58663 
58664 					/* Careful with wrapping: arr_idx upshift may easily wrap, whereas
58665 					 * length downshift won't.
58666 					 */
58667 					if (arr_idx < (h_bufobj->length >> h_bufobj->shift) && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
58668 						duk_uint8_t *data;
58669 						DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
58670 
58671 						DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);  /* index/length check guarantees */
58672 						byte_off = arr_idx << h_bufobj->shift;       /* no wrap assuming h_bufobj->length is valid */
58673 						elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
58674 
58675 						/* Coerce to number before validating pointers etc so that the
58676 						 * number coercions in duk_hbufobj_validated_write() are
58677 						 * guaranteed to be side effect free and not invalidate the
58678 						 * pointer checks we do here.
58679 						 */
58680 						duk_push_tval(thr, tv_val);
58681 						(void) duk_to_number_m1(thr);
58682 
58683 						if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
58684 							data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
58685 							duk_hbufobj_validated_write(thr, h_bufobj, data, elem_size);
58686 						} else {
58687 							DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (write skipped)"));
58688 						}
58689 						duk_pop_unsafe(thr);
58690 						goto success_no_arguments_exotic;
58691 					}
58692 				}
58693 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
58694 
58695 				DUK_D(DUK_DPRINT("should not happen, key %!O", key));
58696 				goto fail_internal;  /* should not happen */
58697 			}
58698 			DUK_DD(DUK_DDPRINT("put to existing own plain property, property is writable"));
58699 			goto update_old;
58700 		}
58701 		DUK_UNREACHABLE();
58702 
58703 	 next_in_chain:
58704 		/* XXX: option to pretend property doesn't exist if sanity limit is
58705 		 * hit might be useful.
58706 		 */
58707 		if (DUK_UNLIKELY(sanity-- == 0)) {
58708 			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
58709 			DUK_WO_NORETURN(return 0;);
58710 		}
58711 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
58712 	} while (curr != NULL);
58713 
58714 	/*
58715 	 *  Property not found in prototype chain.
58716 	 */
58717 
58718 	DUK_DDD(DUK_DDDPRINT("property not found in prototype chain"));
58719 
58720 	if (orig == NULL) {
58721 		DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
58722 		goto fail_base_primitive;
58723 	}
58724 
58725 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
58726 		DUK_DD(DUK_DDPRINT("put to a new property (not found in prototype chain), but original object not extensible"));
58727 		goto fail_not_extensible;
58728 	}
58729 
58730 	goto create_new;
58731 
58732  update_old:
58733 
58734 	/*
58735 	 *  Update an existing property of the base object.
58736 	 */
58737 
58738 	/* [key] */
58739 
58740 	DUK_DDD(DUK_DDDPRINT("update an existing property of the original object"));
58741 
58742 	DUK_ASSERT(orig != NULL);
58743 #if defined(DUK_USE_ROM_OBJECTS)
58744 	/* This should not happen because DUK_TAG_OBJECT case checks
58745 	 * for this already, but check just in case.
58746 	 */
58747 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
58748 		goto fail_not_writable;
58749 	}
58750 #endif
58751 
58752 	/* Although there are writable virtual properties (e.g. plain buffer
58753 	 * and buffer object number indices), they are handled before we come
58754 	 * here.
58755 	 */
58756 	DUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) == 0);
58757 	DUK_ASSERT(desc.a_idx >= 0 || desc.e_idx >= 0);
58758 
58759 	/* Array own property .length is handled above. */
58760 	DUK_ASSERT(!(DUK_HOBJECT_IS_ARRAY(orig) && key == DUK_HTHREAD_STRING_LENGTH(thr)));
58761 
58762 	if (desc.e_idx >= 0) {
58763 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);
58764 		DUK_DDD(DUK_DDDPRINT("previous entry value: %!iT", (duk_tval *) tv));
58765 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects; e_idx may be invalidated */
58766 		/* don't touch property attributes or hash part */
58767 		DUK_DD(DUK_DDPRINT("put to an existing entry at index %ld -> new value %!iT",
58768 		                   (long) desc.e_idx, (duk_tval *) tv));
58769 	} else {
58770 		/* Note: array entries are always writable, so the writability check
58771 		 * above is pointless for them.  The check could be avoided with some
58772 		 * refactoring but is probably not worth it.
58773 		 */
58774 
58775 		DUK_ASSERT(desc.a_idx >= 0);
58776 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, desc.a_idx);
58777 		DUK_DDD(DUK_DDDPRINT("previous array value: %!iT", (duk_tval *) tv));
58778 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects; a_idx may be invalidated */
58779 		DUK_DD(DUK_DDPRINT("put to an existing array entry at index %ld -> new value %!iT",
58780 		                   (long) desc.a_idx, (duk_tval *) tv));
58781 	}
58782 
58783 	/* Regardless of whether property is found in entry or array part,
58784 	 * it may have arguments exotic behavior (array indices may reside
58785 	 * in entry part for abandoned / non-existent array parts).
58786 	 */
58787 	goto success_with_arguments_exotic;
58788 
58789  create_new:
58790 
58791 	/*
58792 	 *  Create a new property in the original object.
58793 	 *
58794 	 *  Exotic properties need to be reconsidered here from a write
58795 	 *  perspective (not just property attributes perspective).
58796 	 *  However, the property does not exist in the object already,
58797 	 *  so this limits the kind of exotic properties that apply.
58798 	 */
58799 
58800 	/* [key] */
58801 
58802 	DUK_DDD(DUK_DDDPRINT("create new property to original object"));
58803 
58804 	DUK_ASSERT(orig != NULL);
58805 
58806 	/* Array own property .length is handled above. */
58807 	DUK_ASSERT(!(DUK_HOBJECT_IS_ARRAY(orig) && key == DUK_HTHREAD_STRING_LENGTH(thr)));
58808 
58809 #if defined(DUK_USE_ROM_OBJECTS)
58810 	/* This should not happen because DUK_TAG_OBJECT case checks
58811 	 * for this already, but check just in case.
58812 	 */
58813 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
58814 		goto fail_not_writable;
58815 	}
58816 #endif
58817 
58818 	/* Not possible because array object 'length' is present
58819 	 * from its creation and cannot be deleted, and is thus
58820 	 * caught as an existing property above.
58821 	 */
58822 	DUK_ASSERT(!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
58823 	             key == DUK_HTHREAD_STRING_LENGTH(thr)));
58824 
58825 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
58826 	    arr_idx != DUK__NO_ARRAY_INDEX) {
58827 		/* automatic length update */
58828 		duk_uint32_t old_len;
58829 		duk_harray *a;
58830 
58831 		a = (duk_harray *) orig;
58832 		DUK_HARRAY_ASSERT_VALID(a);
58833 
58834 		old_len = a->length;
58835 
58836 		if (arr_idx >= old_len) {
58837 			DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
58838 			                     "(arr_idx=%ld, old_len=%ld)",
58839 			                     (long) arr_idx, (long) old_len));
58840 
58841 			if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
58842 				DUK_DD(DUK_DDPRINT("attempt to extend array, but array 'length' is not writable"));
58843 				goto fail_not_writable;
58844 			}
58845 
58846 			/* Note: actual update happens once write has been completed
58847 			 * without error below.  The write should always succeed
58848 			 * from a specification viewpoint, but we may e.g. run out
58849 			 * of memory.  It's safer in this order.
58850 			 */
58851 
58852 			DUK_ASSERT(arr_idx != 0xffffffffUL);
58853 			new_array_length = arr_idx + 1;  /* flag for later write */
58854 		} else {
58855 			DUK_DDD(DUK_DDDPRINT("write new array entry does not require length update "
58856 			                     "(arr_idx=%ld, old_len=%ld)",
58857 			                     (long) arr_idx, (long) old_len));
58858 		}
58859 	}
58860 
58861  /* write_to_array_part: */
58862 
58863 	/*
58864 	 *  Write to array part?
58865 	 *
58866 	 *  Note: array abandonding requires a property resize which uses
58867 	 *  'rechecks' valstack for temporaries and may cause any existing
58868 	 *  valstack pointers to be invalidated.  To protect against this,
58869 	 *  tv_obj, tv_key, and tv_val are copies of the original inputs.
58870 	 */
58871 
58872 	if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(orig)) {
58873 		tv = duk__obtain_arridx_slot(thr, arr_idx, orig);
58874 		if (tv == NULL) {
58875 			DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(orig));
58876 			goto write_to_entry_part;
58877 		}
58878 
58879 		/* prev value must be unused, no decref */
58880 		DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
58881 		DUK_TVAL_SET_TVAL(tv, tv_val);
58882 		DUK_TVAL_INCREF(thr, tv);
58883 		DUK_DD(DUK_DDPRINT("put to new array entry: %ld -> %!T",
58884 		                   (long) arr_idx, (duk_tval *) tv));
58885 
58886 		/* Note: array part values are [[Writable]], [[Enumerable]],
58887 		 * and [[Configurable]] which matches the required attributes
58888 		 * here.
58889 		 */
58890 		goto entry_updated;
58891 	}
58892 
58893  write_to_entry_part:
58894 
58895 	/*
58896 	 *  Write to entry part
58897 	 */
58898 
58899 	/* entry allocation updates hash part and increases the key
58900 	 * refcount; may need a props allocation resize but doesn't
58901 	 * 'recheck' the valstack.
58902 	 */
58903 	e_idx = duk__hobject_alloc_entry_checked(thr, orig, key);
58904 	DUK_ASSERT(e_idx >= 0);
58905 
58906 	tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, e_idx);
58907 	/* prev value can be garbage, no decref */
58908 	DUK_TVAL_SET_TVAL(tv, tv_val);
58909 	DUK_TVAL_INCREF(thr, tv);
58910 	DUK_HOBJECT_E_SET_FLAGS(thr->heap, orig, e_idx, DUK_PROPDESC_FLAGS_WEC);
58911 	goto entry_updated;
58912 
58913  entry_updated:
58914 
58915 	/*
58916 	 *  Possible pending array length update, which must only be done
58917 	 *  if the actual entry write succeeded.
58918 	 */
58919 
58920 	if (new_array_length > 0) {
58921 		/* Note: zero works as a "no update" marker because the new length
58922 		 * can never be zero after a new property is written.
58923 		 */
58924 
58925 		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig));
58926 
58927 		DUK_DDD(DUK_DDDPRINT("write successful, pending array length update to: %ld",
58928 		                     (long) new_array_length));
58929 
58930 		((duk_harray *) orig)->length = new_array_length;
58931 	}
58932 
58933 	/*
58934 	 *  Arguments exotic behavior not possible for new properties: all
58935 	 *  magically bound properties are initially present in the arguments
58936 	 *  object, and if they are deleted, the binding is also removed from
58937 	 *  parameter map.
58938 	 */
58939 
58940 	goto success_no_arguments_exotic;
58941 
58942  success_with_arguments_exotic:
58943 
58944 	/*
58945 	 *  Arguments objects have exotic [[DefineOwnProperty]] which updates
58946 	 *  the internal 'map' of arguments for writes to currently mapped
58947 	 *  arguments.  More conretely, writes to mapped arguments generate
58948 	 *  a write to a bound variable.
58949 	 *
58950 	 *  The [[Put]] algorithm invokes [[DefineOwnProperty]] for existing
58951 	 *  data properties and new properties, but not for existing accessors.
58952 	 *  Hence, in E5 Section 10.6 ([[DefinedOwnProperty]] algorithm), we
58953 	 *  have a Desc with 'Value' (and possibly other properties too), and
58954 	 *  we end up in step 5.b.i.
58955 	 */
58956 
58957 	if (arr_idx != DUK__NO_ARRAY_INDEX &&
58958 	    DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
58959 		/* Note: only numbered indices are relevant, so arr_idx fast reject
58960 		 * is good (this is valid unless there are more than 4**32-1 arguments).
58961 		 */
58962 
58963 		DUK_DDD(DUK_DDDPRINT("putprop successful, arguments exotic behavior needed"));
58964 
58965 		/* Note: we can reuse 'desc' here */
58966 
58967 		/* XXX: top of stack must contain value, which helper doesn't touch,
58968 		 * rework to use tv_val directly?
58969 		 */
58970 
58971 		duk_push_tval(thr, tv_val);
58972 		(void) duk__check_arguments_map_for_put(thr, orig, key, &desc, throw_flag);
58973 		duk_pop_unsafe(thr);
58974 	}
58975 	/* fall thru */
58976 
58977  success_no_arguments_exotic:
58978 	/* shared exit path now */
58979 	DUK_DDD(DUK_DDDPRINT("result: success"));
58980 	duk_pop_unsafe(thr);  /* remove key */
58981 	return 1;
58982 
58983 #if defined(DUK_USE_ES6_PROXY)
58984  fail_proxy_rejected:
58985 	DUK_DDD(DUK_DDDPRINT("result: error, proxy rejects"));
58986 	if (throw_flag) {
58987 		DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
58988 		DUK_WO_NORETURN(return 0;);
58989 	}
58990 	/* Note: no key on stack */
58991 	return 0;
58992 #endif
58993 
58994  fail_base_primitive:
58995 	DUK_DDD(DUK_DDDPRINT("result: error, base primitive"));
58996 	if (throw_flag) {
58997 #if defined(DUK_USE_PARANOID_ERRORS)
58998 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
58999 #else
59000 		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
59001 		               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
59002 #endif
59003 		DUK_WO_NORETURN(return 0;);
59004 	}
59005 	duk_pop_unsafe(thr);  /* remove key */
59006 	return 0;
59007 
59008  fail_not_extensible:
59009 	DUK_DDD(DUK_DDDPRINT("result: error, not extensible"));
59010 	if (throw_flag) {
59011 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);
59012 		DUK_WO_NORETURN(return 0;);
59013 	}
59014 	duk_pop_unsafe(thr);  /* remove key */
59015 	return 0;
59016 
59017  fail_not_writable:
59018 	DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
59019 	if (throw_flag) {
59020 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
59021 		DUK_WO_NORETURN(return 0;);
59022 	}
59023 	duk_pop_unsafe(thr);  /* remove key */
59024 	return 0;
59025 
59026 #if defined(DUK_USE_ROM_OBJECTS)
59027  fail_not_writable_no_pop:
59028 	DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
59029 	if (throw_flag) {
59030 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
59031 		DUK_WO_NORETURN(return 0;);
59032 	}
59033 	return 0;
59034 #endif
59035 
59036  fail_array_length_partial:
59037 	DUK_DD(DUK_DDPRINT("result: error, array length write only partially successful"));
59038 	if (throw_flag) {
59039 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
59040 		DUK_WO_NORETURN(return 0;);
59041 	}
59042 	duk_pop_unsafe(thr);  /* remove key */
59043 	return 0;
59044 
59045  fail_no_setter:
59046 	DUK_DDD(DUK_DDDPRINT("result: error, accessor property without setter"));
59047 	if (throw_flag) {
59048 		DUK_ERROR_TYPE(thr, DUK_STR_SETTER_UNDEFINED);
59049 		DUK_WO_NORETURN(return 0;);
59050 	}
59051 	duk_pop_unsafe(thr);  /* remove key */
59052 	return 0;
59053 
59054  fail_internal:
59055 	DUK_DDD(DUK_DDDPRINT("result: error, internal"));
59056 	if (throw_flag) {
59057 		DUK_ERROR_INTERNAL(thr);
59058 		DUK_WO_NORETURN(return 0;);
59059 	}
59060 	duk_pop_unsafe(thr);  /* remove key */
59061 	return 0;
59062 }
59063 
59064 /*
59065  *  ECMAScript compliant [[Delete]](P, Throw).
59066  */
59067 
59068 DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
59069 	duk_propdesc desc;
59070 	duk_tval *tv;
59071 	duk_uint32_t arr_idx;
59072 	duk_bool_t throw_flag;
59073 	duk_bool_t force_flag;
59074 
59075 	throw_flag = (flags & DUK_DELPROP_FLAG_THROW);
59076 	force_flag = (flags & DUK_DELPROP_FLAG_FORCE);
59077 
59078 	DUK_DDD(DUK_DDDPRINT("delprop_raw: thr=%p, obj=%p, key=%p, throw=%ld, force=%ld (obj -> %!O, key -> %!O)",
59079 	                     (void *) thr, (void *) obj, (void *) key, (long) throw_flag, (long) force_flag,
59080 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
59081 
59082 	DUK_ASSERT(thr != NULL);
59083 	DUK_ASSERT(thr->heap != NULL);
59084 	DUK_ASSERT(obj != NULL);
59085 	DUK_ASSERT(key != NULL);
59086 
59087 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
59088 
59089 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
59090 
59091 	/* 0 = don't push current value */
59092 	if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
59093 		DUK_DDD(DUK_DDDPRINT("property not found, succeed always"));
59094 		goto success;
59095 	}
59096 
59097 #if defined(DUK_USE_ROM_OBJECTS)
59098 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
59099 		DUK_DD(DUK_DDPRINT("attempt to delprop on read-only target object"));
59100 		goto fail_not_configurable;
59101 	}
59102 #endif
59103 
59104 	if ((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) == 0 && !force_flag) {
59105 		goto fail_not_configurable;
59106 	}
59107 	if (desc.a_idx < 0 && desc.e_idx < 0) {
59108 		/* Currently there are no deletable virtual properties, but
59109 		 * with force_flag we might attempt to delete one.
59110 		 */
59111 		DUK_DD(DUK_DDPRINT("delete failed: property found, force flag, but virtual (and implicitly non-configurable)"));
59112 		goto fail_virtual;
59113 	}
59114 
59115 	if (desc.a_idx >= 0) {
59116 		DUK_ASSERT(desc.e_idx < 0);
59117 
59118 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
59119 		DUK_TVAL_SET_UNUSED_UPDREF(thr, tv);  /* side effects */
59120 		goto success;
59121 	} else {
59122 		DUK_ASSERT(desc.a_idx < 0);
59123 
59124 		/* remove hash entry (no decref) */
59125 #if defined(DUK_USE_HOBJECT_HASH_PART)
59126 		if (desc.h_idx >= 0) {
59127 			duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
59128 
59129 			DUK_DDD(DUK_DDDPRINT("removing hash entry at h_idx %ld", (long) desc.h_idx));
59130 			DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) > 0);
59131 			DUK_ASSERT((duk_uint32_t) desc.h_idx < DUK_HOBJECT_GET_HSIZE(obj));
59132 			h_base[desc.h_idx] = DUK__HASH_DELETED;
59133 		} else {
59134 			DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);
59135 		}
59136 #else
59137 		DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);
59138 #endif
59139 
59140 		/* Remove value.  This requires multiple writes so avoid side
59141 		 * effects via no-refzero macros so that e_idx is not
59142 		 * invalidated.
59143 		 */
59144 		DUK_DDD(DUK_DDDPRINT("before removing value, e_idx %ld, key %p, key at slot %p",
59145 		                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
59146 		DUK_DDD(DUK_DDDPRINT("removing value at e_idx %ld", (long) desc.e_idx));
59147 		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx)) {
59148 			duk_hobject *tmp;
59149 
59150 			tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, desc.e_idx);
59151 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, desc.e_idx, NULL);
59152 			DUK_UNREF(tmp);
59153 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
59154 
59155 			tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, desc.e_idx);
59156 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, desc.e_idx, NULL);
59157 			DUK_UNREF(tmp);
59158 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
59159 		} else {
59160 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
59161 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
59162 		}
59163 #if 0
59164 		/* Not strictly necessary because if key == NULL, flag MUST be ignored. */
59165 		DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, 0);
59166 #endif
59167 
59168 		/* Remove key. */
59169 		DUK_DDD(DUK_DDDPRINT("before removing key, e_idx %ld, key %p, key at slot %p",
59170 		                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
59171 		DUK_DDD(DUK_DDDPRINT("removing key at e_idx %ld", (long) desc.e_idx));
59172 		DUK_ASSERT(key == DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx));
59173 		DUK_HOBJECT_E_SET_KEY(thr->heap, obj, desc.e_idx, NULL);
59174 		DUK_HSTRING_DECREF_NORZ(thr, key);
59175 
59176 		/* Trigger refzero side effects only when we're done as a
59177 		 * finalizer might operate on the object and affect the
59178 		 * e_idx we're supposed to use.
59179 		 */
59180 		DUK_REFZERO_CHECK_SLOW(thr);
59181 		goto success;
59182 	}
59183 
59184 	DUK_UNREACHABLE();
59185 
59186  success:
59187 	/*
59188 	 *  Argument exotic [[Delete]] behavior (E5 Section 10.6) is
59189 	 *  a post-check, keeping arguments internal 'map' in sync with
59190 	 *  any successful deletes (note that property does not need to
59191 	 *  exist for delete to 'succeed').
59192 	 *
59193 	 *  Delete key from 'map'.  Since 'map' only contains array index
59194 	 *  keys, we can use arr_idx for a fast skip.
59195 	 */
59196 
59197 	DUK_DDD(DUK_DDDPRINT("delete successful, check for arguments exotic behavior"));
59198 
59199 	if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
59200 		/* Note: only numbered indices are relevant, so arr_idx fast reject
59201 		 * is good (this is valid unless there are more than 4**32-1 arguments).
59202 		 */
59203 
59204 		DUK_DDD(DUK_DDDPRINT("delete successful, arguments exotic behavior needed"));
59205 
59206 		/* Note: we can reuse 'desc' here */
59207 		(void) duk__check_arguments_map_for_delete(thr, obj, key, &desc);
59208 	}
59209 
59210 	DUK_DDD(DUK_DDDPRINT("delete successful"));
59211 	return 1;
59212 
59213  fail_virtual:  /* just use the same "not configurable" error message */
59214  fail_not_configurable:
59215 	DUK_DDD(DUK_DDDPRINT("delete failed: property found, not configurable"));
59216 
59217 	if (throw_flag) {
59218 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
59219 		DUK_WO_NORETURN(return 0;);
59220 	}
59221 	return 0;
59222 }
59223 
59224 /*
59225  *  DELPROP: ECMAScript property deletion.
59226  */
59227 
59228 DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag) {
59229 	duk_hstring *key = NULL;
59230 #if defined(DUK_USE_ES6_PROXY)
59231 	duk_propdesc desc;
59232 #endif
59233 	duk_int_t entry_top;
59234 	duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
59235 	duk_bool_t rc;
59236 
59237 	DUK_DDD(DUK_DDDPRINT("delprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
59238 	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
59239 	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));
59240 
59241 	DUK_ASSERT(thr != NULL);
59242 	DUK_ASSERT(thr->heap != NULL);
59243 	DUK_ASSERT(tv_obj != NULL);
59244 	DUK_ASSERT(tv_key != NULL);
59245 
59246 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
59247 
59248 	/* Storing the entry top is cheaper here to ensure stack is correct at exit,
59249 	 * as there are several paths out.
59250 	 */
59251 	entry_top = duk_get_top(thr);
59252 
59253 	if (DUK_TVAL_IS_UNDEFINED(tv_obj) ||
59254 	    DUK_TVAL_IS_NULL(tv_obj)) {
59255 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
59256 		goto fail_invalid_base_uncond;
59257 	}
59258 
59259 	duk_push_tval(thr, tv_obj);
59260 	duk_push_tval(thr, tv_key);
59261 
59262 	tv_obj = DUK_GET_TVAL_NEGIDX(thr, -2);
59263 	if (DUK_TVAL_IS_OBJECT(tv_obj)) {
59264 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_obj);
59265 		DUK_ASSERT(obj != NULL);
59266 
59267 #if defined(DUK_USE_ES6_PROXY)
59268 		if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(obj))) {
59269 			duk_hobject *h_target;
59270 			duk_bool_t tmp_bool;
59271 
59272 			/* Note: proxy handling must happen before key is string coerced. */
59273 
59274 			if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_DELETE_PROPERTY, tv_key, &h_target)) {
59275 				/* -> [ ... obj key trap handler ] */
59276 				DUK_DDD(DUK_DDDPRINT("-> proxy object 'deleteProperty' for key %!T", (duk_tval *) tv_key));
59277 				duk_push_hobject(thr, h_target);  /* target */
59278 				duk_dup_m4(thr);  /* P */
59279 				duk_call_method(thr, 2 /*nargs*/);
59280 				tmp_bool = duk_to_boolean_top_pop(thr);
59281 				if (!tmp_bool) {
59282 					goto fail_proxy_rejected;  /* retval indicates delete failed */
59283 				}
59284 
59285 				/* Target object must be checked for a conflicting
59286 				 * non-configurable property.
59287 				 */
59288 				tv_key = DUK_GET_TVAL_NEGIDX(thr, -1);
59289 				arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59290 				DUK_ASSERT(key != NULL);
59291 
59292 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
59293 					duk_small_int_t desc_reject;
59294 
59295 					DUK_DDD(DUK_DDDPRINT("proxy 'deleteProperty': target has matching property %!O, check for "
59296 					                     "conflicting property; desc.flags=0x%08lx, "
59297 					                     "desc.get=%p, desc.set=%p",
59298 					                     (duk_heaphdr *) key, (unsigned long) desc.flags,
59299 					                     (void *) desc.get, (void *) desc.set));
59300 
59301 					desc_reject = !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE);
59302 					if (desc_reject) {
59303 						/* unconditional */
59304 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
59305 						DUK_WO_NORETURN(return 0;);
59306 					}
59307 				}
59308 				rc = 1;  /* success */
59309 				goto done_rc;
59310 			}
59311 
59312 			obj = h_target;  /* resume delete to target */
59313 		}
59314 #endif  /* DUK_USE_ES6_PROXY */
59315 
59316 		arr_idx = duk__to_property_key(thr, -1, &key);
59317 		DUK_ASSERT(key != NULL);
59318 
59319 		rc = duk_hobject_delprop_raw(thr, obj, key, throw_flag ? DUK_DELPROP_FLAG_THROW : 0);
59320 		goto done_rc;
59321 	} else if (DUK_TVAL_IS_STRING(tv_obj)) {
59322 		/* String has .length and array index virtual properties
59323 		 * which can't be deleted.  No need for a symbol check;
59324 		 * no offending virtual symbols exist.
59325 		 */
59326 		/* XXX: unnecessary string coercion for array indices,
59327 		 * intentional to keep small.
59328 		 */
59329 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
59330 		DUK_ASSERT(h != NULL);
59331 
59332 		arr_idx = duk__to_property_key(thr, -1, &key);
59333 		DUK_ASSERT(key != NULL);
59334 
59335 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
59336 			goto fail_not_configurable;
59337 		}
59338 
59339 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
59340 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
59341 			goto fail_not_configurable;
59342 		}
59343 	} else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
59344 		/* XXX: unnecessary string coercion for array indices,
59345 		 * intentional to keep small; some overlap with string
59346 		 * handling.
59347 		 */
59348 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
59349 		DUK_ASSERT(h != NULL);
59350 
59351 		arr_idx = duk__to_property_key(thr, -1, &key);
59352 		DUK_ASSERT(key != NULL);
59353 
59354 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
59355 			goto fail_not_configurable;
59356 		}
59357 
59358 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
59359 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
59360 			goto fail_not_configurable;
59361 		}
59362 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
59363 		/* Lightfunc has no virtual properties since Duktape 2.2
59364 		 * so success.  Still must coerce key for side effects.
59365 		 */
59366 
59367 		arr_idx = duk__to_property_key(thr, -1, &key);
59368 		DUK_ASSERT(key != NULL);
59369 		DUK_UNREF(key);
59370 	}
59371 
59372 	/* non-object base, no offending virtual property */
59373 	rc = 1;
59374 	goto done_rc;
59375 
59376  done_rc:
59377 	duk_set_top_unsafe(thr, entry_top);
59378 	return rc;
59379 
59380  fail_invalid_base_uncond:
59381 	/* Note: unconditional throw */
59382 	DUK_ASSERT(duk_get_top(thr) == entry_top);
59383 #if defined(DUK_USE_PARANOID_ERRORS)
59384 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
59385 #else
59386 	DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot delete property %s of %s",
59387 	               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
59388 #endif
59389 	DUK_WO_NORETURN(return 0;);
59390 
59391 #if defined(DUK_USE_ES6_PROXY)
59392  fail_proxy_rejected:
59393 	if (throw_flag) {
59394 		DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
59395 		DUK_WO_NORETURN(return 0;);
59396 	}
59397 	duk_set_top_unsafe(thr, entry_top);
59398 	return 0;
59399 #endif
59400 
59401  fail_not_configurable:
59402 	if (throw_flag) {
59403 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
59404 		DUK_WO_NORETURN(return 0;);
59405 	}
59406 	duk_set_top_unsafe(thr, entry_top);
59407 	return 0;
59408 }
59409 
59410 /*
59411  *  Internal helper to define a property with specific flags, ignoring
59412  *  normal semantics such as extensibility, write protection etc.
59413  *  Overwrites any existing value and attributes unless caller requests
59414  *  that value only be updated if it doesn't already exists.
59415  *
59416  *  Does not support:
59417  *    - virtual properties (error if write attempted)
59418  *    - getter/setter properties (error if write attempted)
59419  *    - non-default (!= WEC) attributes for array entries (error if attempted)
59420  *    - array abandoning: if array part exists, it is always extended
59421  *    - array 'length' updating
59422  *
59423  *  Stack: [... in_val] -> []
59424  *
59425  *  Used for e.g. built-in initialization and environment record
59426  *  operations.
59427  */
59428 
59429 DUK_INTERNAL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
59430 	duk_propdesc desc;
59431 	duk_uint32_t arr_idx;
59432 	duk_int_t e_idx;
59433 	duk_tval *tv1 = NULL;
59434 	duk_tval *tv2 = NULL;
59435 	duk_small_uint_t propflags = flags & DUK_PROPDESC_FLAGS_MASK;  /* mask out flags not actually stored */
59436 
59437 	DUK_DDD(DUK_DDDPRINT("define new property (internal): thr=%p, obj=%!O, key=%!O, flags=0x%02lx, val=%!T",
59438 	                     (void *) thr, (duk_heaphdr *) obj, (duk_heaphdr *) key,
59439 	                     (unsigned long) flags, (duk_tval *) duk_get_tval(thr, -1)));
59440 
59441 	DUK_ASSERT(thr != NULL);
59442 	DUK_ASSERT(thr->heap != NULL);
59443 	DUK_ASSERT(obj != NULL);
59444 	DUK_ASSERT(key != NULL);
59445 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
59446 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
59447 	DUK_ASSERT(duk_is_valid_index(thr, -1));  /* contains value */
59448 
59449 	arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
59450 
59451 	if (duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
59452 		if (desc.e_idx >= 0) {
59453 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
59454 				DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> skip as requested"));
59455 				goto pop_exit;
59456 			}
59457 			DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> update value and attributes"));
59458 			if (DUK_UNLIKELY(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx))) {
59459 				DUK_D(DUK_DPRINT("existing property is an accessor, not supported"));
59460 				goto error_internal;
59461 			}
59462 
59463 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, propflags);
59464 			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
59465 		} else if (desc.a_idx >= 0) {
59466 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
59467 				DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> skip as requested"));
59468 				goto pop_exit;
59469 			}
59470 			DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> update value (assert attributes)"));
59471 			if (propflags != DUK_PROPDESC_FLAGS_WEC) {
59472 				DUK_D(DUK_DPRINT("existing property in array part, but propflags not WEC (0x%02lx)",
59473 				                 (unsigned long) propflags));
59474 				goto error_internal;
59475 			}
59476 
59477 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
59478 		} else {
59479 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
59480 				DUK_DDD(DUK_DDDPRINT("property already exists but is virtual -> skip as requested"));
59481 				goto pop_exit;
59482 			}
59483 			if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
59484 				duk_uint32_t new_len;
59485 #if defined(DUK_USE_DEBUG)
59486 				duk_uint32_t prev_len;
59487 				prev_len = ((duk_harray *) obj)->length;
59488 #endif
59489 				new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_NEGIDX(thr, -1));
59490 				((duk_harray *) obj)->length = new_len;
59491 				DUK_DD(DUK_DDPRINT("internal define property for array .length: %ld -> %ld",
59492 				                   (long) prev_len, (long) ((duk_harray *) obj)->length));
59493 				goto pop_exit;
59494 			}
59495 			DUK_DD(DUK_DDPRINT("property already exists but is virtual -> failure"));
59496 			goto error_virtual;
59497 		}
59498 
59499 		goto write_value;
59500 	}
59501 
59502 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
59503 		if (arr_idx != DUK__NO_ARRAY_INDEX) {
59504 			DUK_DDD(DUK_DDDPRINT("property does not exist, object has array part -> possibly extend array part and write value (assert attributes)"));
59505 			DUK_ASSERT(propflags == DUK_PROPDESC_FLAGS_WEC);
59506 
59507 			tv1 = duk__obtain_arridx_slot(thr, arr_idx, obj);
59508 			if (tv1 == NULL) {
59509 				DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
59510 				goto write_to_entry_part;
59511 			}
59512 
59513 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
59514 			goto write_value;
59515 		}
59516 	}
59517 
59518  write_to_entry_part:
59519 	DUK_DDD(DUK_DDDPRINT("property does not exist, object belongs in entry part -> allocate new entry and write value and attributes"));
59520 	e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);  /* increases key refcount */
59521 	DUK_ASSERT(e_idx >= 0);
59522 	DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, propflags);
59523 	tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
59524 	/* new entry: previous value is garbage; set to undefined to share write_value */
59525 	DUK_TVAL_SET_UNDEFINED(tv1);
59526 	goto write_value;
59527 
59528  write_value:
59529 	/* tv1 points to value storage */
59530 
59531 	tv2 = duk_require_tval(thr, -1);  /* late lookup, avoid side effects */
59532 	DUK_DDD(DUK_DDDPRINT("writing/updating value: %!T -> %!T",
59533 	                     (duk_tval *) tv1, (duk_tval *) tv2));
59534 
59535 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
59536 	goto pop_exit;
59537 
59538  pop_exit:
59539 	duk_pop_unsafe(thr);  /* remove in_val */
59540 	return;
59541 
59542  error_virtual:  /* share error message */
59543  error_internal:
59544 	DUK_ERROR_INTERNAL(thr);
59545 	DUK_WO_NORETURN(return;);
59546 }
59547 
59548 /*
59549  *  Fast path for defining array indexed values without interning the key.
59550  *  This is used by e.g. code for Array prototype and traceback creation so
59551  *  must avoid interning.
59552  */
59553 
59554 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) {
59555 	duk_hstring *key;
59556 	duk_tval *tv1, *tv2;
59557 
59558 	DUK_DDD(DUK_DDDPRINT("define new property (internal) arr_idx fast path: thr=%p, obj=%!O, "
59559 	                     "arr_idx=%ld, flags=0x%02lx, val=%!T",
59560 	                     (void *) thr, obj, (long) arr_idx, (unsigned long) flags,
59561 	                     (duk_tval *) duk_get_tval(thr, -1)));
59562 
59563 	DUK_ASSERT(thr != NULL);
59564 	DUK_ASSERT(thr->heap != NULL);
59565 	DUK_ASSERT(obj != NULL);
59566 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
59567 
59568 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
59569 	    arr_idx != DUK__NO_ARRAY_INDEX &&
59570 	    flags == DUK_PROPDESC_FLAGS_WEC) {
59571 		DUK_ASSERT((flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) == 0);  /* covered by comparison */
59572 
59573 		DUK_DDD(DUK_DDDPRINT("define property to array part (property may or may not exist yet)"));
59574 
59575 		tv1 = duk__obtain_arridx_slot(thr, arr_idx, obj);
59576 		if (tv1 == NULL) {
59577 			DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
59578 			goto write_slow;
59579 		}
59580 		tv2 = duk_require_tval(thr, -1);
59581 
59582 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
59583 
59584 		duk_pop_unsafe(thr);  /* [ ...val ] -> [ ... ] */
59585 		return;
59586 	}
59587 
59588  write_slow:
59589 	DUK_DDD(DUK_DDDPRINT("define property fast path didn't work, use slow path"));
59590 
59591 	key = duk_push_uint_to_hstring(thr, (duk_uint_t) arr_idx);
59592 	DUK_ASSERT(key != NULL);
59593 	duk_insert(thr, -2);  /* [ ... val key ] -> [ ... key val ] */
59594 
59595 	duk_hobject_define_property_internal(thr, obj, key, flags);
59596 
59597 	duk_pop_unsafe(thr);  /* [ ... key ] -> [ ... ] */
59598 }
59599 
59600 /*
59601  *  Internal helpers for managing object 'length'
59602  */
59603 
59604 DUK_INTERNAL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj) {
59605 	duk_double_t val;
59606 
59607 	DUK_CTX_ASSERT_VALID(thr);
59608 	DUK_ASSERT(obj != NULL);
59609 
59610 	/* Fast path for Arrays. */
59611 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
59612 		return ((duk_harray *) obj)->length;
59613 	}
59614 
59615 	/* Slow path, .length can be e.g. accessor, obj can be a Proxy, etc. */
59616 	duk_push_hobject(thr, obj);
59617 	duk_push_hstring_stridx(thr, DUK_STRIDX_LENGTH);
59618 	(void) duk_hobject_getprop(thr,
59619 	                           DUK_GET_TVAL_NEGIDX(thr, -2),
59620 	                           DUK_GET_TVAL_NEGIDX(thr, -1));
59621 	val = duk_to_number_m1(thr);
59622 	duk_pop_3_unsafe(thr);
59623 
59624 	/* This isn't part of ECMAScript semantics; return a value within
59625 	 * duk_size_t range, or 0 otherwise.
59626 	 */
59627 	if (val >= 0.0 && val <= (duk_double_t) DUK_SIZE_MAX) {
59628 		return (duk_size_t) val;
59629 	}
59630 	return 0;
59631 }
59632 
59633 /*
59634  *  Fast finalizer check for an object.  Walks the prototype chain, checking
59635  *  for finalizer presence using DUK_HOBJECT_FLAG_HAVE_FINALIZER which is kept
59636  *  in sync with the actual property when setting/removing the finalizer.
59637  */
59638 
59639 #if defined(DUK_USE_HEAPPTR16)
59640 DUK_INTERNAL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_heap *heap, duk_hobject *obj) {
59641 #else
59642 DUK_INTERNAL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_hobject *obj) {
59643 #endif
59644 	duk_uint_t sanity;
59645 
59646 	DUK_ASSERT(obj != NULL);
59647 
59648 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
59649 	do {
59650 		if (DUK_UNLIKELY(DUK_HOBJECT_HAS_HAVE_FINALIZER(obj))) {
59651 			return 1;
59652 		}
59653 		if (DUK_UNLIKELY(sanity-- == 0)) {
59654 			DUK_D(DUK_DPRINT("prototype loop when checking for finalizer existence; returning false"));
59655 			return 0;
59656 		}
59657 #if defined(DUK_USE_HEAPPTR16)
59658 		DUK_ASSERT(heap != NULL);
59659 		obj = DUK_HOBJECT_GET_PROTOTYPE(heap, obj);
59660 #else
59661 		obj = DUK_HOBJECT_GET_PROTOTYPE(NULL, obj);  /* 'heap' arg ignored */
59662 #endif
59663 	} while (obj != NULL);
59664 
59665 	return 0;
59666 }
59667 
59668 /*
59669  *  Object.getOwnPropertyDescriptor()  (E5 Sections 15.2.3.3, 8.10.4)
59670  *
59671  *  [ ... key ] -> [ ... desc/undefined ]
59672  */
59673 
59674 DUK_INTERNAL void duk_hobject_object_get_own_property_descriptor(duk_hthread *thr, duk_idx_t obj_idx) {
59675 	duk_hobject *obj;
59676 	duk_hstring *key;
59677 	duk_propdesc pd;
59678 
59679 	DUK_ASSERT(thr != NULL);
59680 	DUK_ASSERT(thr->heap != NULL);
59681 
59682 	obj = duk_require_hobject_promote_mask(thr, obj_idx, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
59683 	key = duk_to_property_key_hstring(thr, -1);
59684 	DUK_ASSERT(key != NULL);
59685 
59686 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
59687 
59688 	if (!duk_hobject_get_own_propdesc(thr, obj, key, &pd, DUK_GETDESC_FLAG_PUSH_VALUE)) {
59689 		duk_push_undefined(thr);
59690 		duk_remove_m2(thr);
59691 		return;
59692 	}
59693 
59694 	duk_push_object(thr);
59695 
59696 	/* [ ... key value desc ] */
59697 
59698 	if (DUK_PROPDESC_IS_ACCESSOR(&pd)) {
59699 		/* If a setter/getter is missing (undefined), the descriptor must
59700 		 * still have the property present with the value 'undefined'.
59701 		 */
59702 		if (pd.get) {
59703 			duk_push_hobject(thr, pd.get);
59704 		} else {
59705 			duk_push_undefined(thr);
59706 		}
59707 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_GET);
59708 		if (pd.set) {
59709 			duk_push_hobject(thr, pd.set);
59710 		} else {
59711 			duk_push_undefined(thr);
59712 		}
59713 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_SET);
59714 	} else {
59715 		duk_dup_m2(thr);
59716 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_VALUE);
59717 		duk_push_boolean(thr, DUK_PROPDESC_IS_WRITABLE(&pd));
59718 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_WRITABLE);
59719 	}
59720 	duk_push_boolean(thr, DUK_PROPDESC_IS_ENUMERABLE(&pd));
59721 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_ENUMERABLE);
59722 	duk_push_boolean(thr, DUK_PROPDESC_IS_CONFIGURABLE(&pd));
59723 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_CONFIGURABLE);
59724 
59725 	/* [ ... key value desc ] */
59726 
59727 	duk_replace(thr, -3);
59728 	duk_pop_unsafe(thr);  /* -> [ ... desc ] */
59729 }
59730 
59731 /*
59732  *  NormalizePropertyDescriptor() related helper.
59733  *
59734  *  Internal helper which validates and normalizes a property descriptor
59735  *  represented as an ECMAScript object (e.g. argument to defineProperty()).
59736  *  The output of this conversion is a set of defprop_flags and possibly
59737  *  some values pushed on the value stack to (1) ensure borrowed pointers
59738  *  remain valid, and (2) avoid unnecessary pops for footprint reasons.
59739  *  Caller must manage stack top carefully because the number of values
59740  *  pushed depends on the input property descriptor.
59741  *
59742  *  The original descriptor object must not be altered in the process.
59743  */
59744 
59745 /* XXX: very basic optimization -> duk_get_prop_stridx_top */
59746 
59747 DUK_INTERNAL
59748 void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
59749                                              duk_idx_t idx_in,
59750                                              duk_uint_t *out_defprop_flags,
59751                                              duk_idx_t *out_idx_value,
59752                                              duk_hobject **out_getter,
59753                                              duk_hobject **out_setter) {
59754 	duk_idx_t idx_value = -1;
59755 	duk_hobject *getter = NULL;
59756 	duk_hobject *setter = NULL;
59757 	duk_bool_t is_data_desc = 0;
59758 	duk_bool_t is_acc_desc = 0;
59759 	duk_uint_t defprop_flags = 0;
59760 
59761 	DUK_ASSERT(out_defprop_flags != NULL);
59762 	DUK_ASSERT(out_idx_value != NULL);
59763 	DUK_ASSERT(out_getter != NULL);
59764 	DUK_ASSERT(out_setter != NULL);
59765 	DUK_ASSERT(idx_in <= 0x7fffL);  /* short variants would be OK, but not used to avoid shifts */
59766 
59767 	/* Must be an object, otherwise TypeError (E5.1 Section 8.10.5, step 1). */
59768 	idx_in = duk_require_normalize_index(thr, idx_in);
59769 	(void) duk_require_hobject(thr, idx_in);
59770 
59771 	/* The coercion order must match the ToPropertyDescriptor() algorithm
59772 	 * so that side effects in coercion happen in the correct order.
59773 	 * (This order also happens to be compatible with duk_def_prop(),
59774 	 * although it doesn't matter in practice.)
59775 	 */
59776 
59777 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_VALUE)) {
59778 		is_data_desc = 1;
59779 		defprop_flags |= DUK_DEFPROP_HAVE_VALUE;
59780 		idx_value = duk_get_top_index(thr);
59781 	}
59782 
59783 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_WRITABLE)) {
59784 		is_data_desc = 1;
59785 		if (duk_to_boolean_top_pop(thr)) {
59786 			defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE;
59787 		} else {
59788 			defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE;
59789 		}
59790 	}
59791 
59792 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_GET)) {
59793 		duk_tval *tv = duk_require_tval(thr, -1);
59794 		duk_hobject *h_get;
59795 
59796 		if (DUK_TVAL_IS_UNDEFINED(tv)) {
59797 			/* undefined is accepted */
59798 			DUK_ASSERT(getter == NULL);
59799 		} else {
59800 			/* NOTE: lightfuncs are coerced to full functions because
59801 			 * lightfuncs don't fit into a property value slot.  This
59802 			 * has some side effects, see test-dev-lightfunc-accessor.js.
59803 			 */
59804 			h_get = duk_get_hobject_promote_lfunc(thr, -1);
59805 			if (h_get == NULL || !DUK_HOBJECT_IS_CALLABLE(h_get)) {
59806 				goto type_error;
59807 			}
59808 			getter = h_get;
59809 		}
59810 		is_acc_desc = 1;
59811 		defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
59812 	}
59813 
59814 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_SET)) {
59815 		duk_tval *tv = duk_require_tval(thr, -1);
59816 		duk_hobject *h_set;
59817 
59818 		if (DUK_TVAL_IS_UNDEFINED(tv)) {
59819 			/* undefined is accepted */
59820 			DUK_ASSERT(setter == NULL);
59821 		}  else {
59822 			/* NOTE: lightfuncs are coerced to full functions because
59823 			 * lightfuncs don't fit into a property value slot.  This
59824 			 * has some side effects, see test-dev-lightfunc-accessor.js.
59825 			 */
59826 			h_set = duk_get_hobject_promote_lfunc(thr, -1);
59827 			if (h_set == NULL || !DUK_HOBJECT_IS_CALLABLE(h_set)) {
59828 				goto type_error;
59829 			}
59830 			setter = h_set;
59831 		}
59832 		is_acc_desc = 1;
59833 		defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
59834 	}
59835 
59836 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_ENUMERABLE)) {
59837 		if (duk_to_boolean_top_pop(thr)) {
59838 			defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE;
59839 		} else {
59840 			defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE;
59841 		}
59842 	}
59843 
59844 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_CONFIGURABLE)) {
59845 		if (duk_to_boolean_top_pop(thr)) {
59846 			defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE;
59847 		} else {
59848 			defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE;
59849 		}
59850 	}
59851 
59852 	if (is_data_desc && is_acc_desc) {
59853 		goto type_error;
59854 	}
59855 
59856 	*out_defprop_flags = defprop_flags;
59857 	*out_idx_value = idx_value;
59858 	*out_getter = getter;
59859 	*out_setter = setter;
59860 
59861 	/* [ ... [multiple values] ] */
59862 	return;
59863 
59864  type_error:
59865 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
59866 	DUK_WO_NORETURN(return;);
59867 }
59868 
59869 /*
59870  *  Object.defineProperty() related helper (E5 Section 15.2.3.6).
59871  *  Also handles ES2015 Reflect.defineProperty().
59872  *
59873  *  Inlines all [[DefineOwnProperty]] exotic behaviors.
59874  *
59875  *  Note: ECMAScript compliant [[DefineOwnProperty]](P, Desc, Throw) is not
59876  *  implemented directly, but Object.defineProperty() serves its purpose.
59877  *  We don't need the [[DefineOwnProperty]] internally and we don't have a
59878  *  property descriptor with 'missing values' so it's easier to avoid it
59879  *  entirely.
59880  *
59881  *  Note: this is only called for actual objects, not primitive values.
59882  *  This must support virtual properties for full objects (e.g. Strings)
59883  *  but not for plain values (e.g. strings).  Lightfuncs, even though
59884  *  primitive in a sense, are treated like objects and accepted as target
59885  *  values.
59886  */
59887 
59888 /* XXX: this is a major target for size optimization */
59889 DUK_INTERNAL
59890 duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
59891                                               duk_uint_t defprop_flags,
59892                                               duk_hobject *obj,
59893                                               duk_hstring *key,
59894                                               duk_idx_t idx_value,
59895                                               duk_hobject *get,
59896                                               duk_hobject *set,
59897                                               duk_bool_t throw_flag) {
59898 	duk_uint32_t arr_idx;
59899 	duk_tval tv;
59900 	duk_bool_t has_enumerable;
59901 	duk_bool_t has_configurable;
59902 	duk_bool_t has_writable;
59903 	duk_bool_t has_value;
59904 	duk_bool_t has_get;
59905 	duk_bool_t has_set;
59906 	duk_bool_t is_enumerable;
59907 	duk_bool_t is_configurable;
59908 	duk_bool_t is_writable;
59909 	duk_bool_t force_flag;
59910 	duk_small_uint_t new_flags;
59911 	duk_propdesc curr;
59912 	duk_uint32_t arridx_new_array_length;  /* != 0 => post-update for array 'length' (used when key is an array index) */
59913 	duk_uint32_t arrlen_old_len;
59914 	duk_uint32_t arrlen_new_len;
59915 	duk_bool_t pending_write_protect;
59916 
59917 	DUK_ASSERT(thr != NULL);
59918 	DUK_ASSERT(thr->heap != NULL);
59919 	DUK_ASSERT(obj != NULL);
59920 	DUK_ASSERT(key != NULL);
59921 	/* idx_value may be < 0 (no value), set and get may be NULL */
59922 
59923 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
59924 
59925 	/* All the flags fit in 16 bits, so will fit into duk_bool_t. */
59926 
59927 	has_writable = (defprop_flags & DUK_DEFPROP_HAVE_WRITABLE);
59928 	has_enumerable = (defprop_flags & DUK_DEFPROP_HAVE_ENUMERABLE);
59929 	has_configurable = (defprop_flags & DUK_DEFPROP_HAVE_CONFIGURABLE);
59930 	has_value = (defprop_flags & DUK_DEFPROP_HAVE_VALUE);
59931 	has_get = (defprop_flags & DUK_DEFPROP_HAVE_GETTER);
59932 	has_set = (defprop_flags & DUK_DEFPROP_HAVE_SETTER);
59933 	is_writable = (defprop_flags & DUK_DEFPROP_WRITABLE);
59934 	is_enumerable = (defprop_flags & DUK_DEFPROP_ENUMERABLE);
59935 	is_configurable = (defprop_flags & DUK_DEFPROP_CONFIGURABLE);
59936 	force_flag = (defprop_flags & DUK_DEFPROP_FORCE);
59937 
59938 	arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
59939 
59940 	arridx_new_array_length = 0;
59941 	pending_write_protect = 0;
59942 	arrlen_old_len = 0;
59943 	arrlen_new_len = 0;
59944 
59945 	DUK_DDD(DUK_DDDPRINT("has_enumerable=%ld is_enumerable=%ld "
59946 	                     "has_configurable=%ld is_configurable=%ld "
59947 	                     "has_writable=%ld is_writable=%ld "
59948 	                     "has_value=%ld value=%!T "
59949 	                     "has_get=%ld get=%p=%!O "
59950 	                     "has_set=%ld set=%p=%!O "
59951 	                     "arr_idx=%ld throw_flag=!%ld",
59952 	                     (long) has_enumerable, (long) is_enumerable,
59953 	                     (long) has_configurable, (long) is_configurable,
59954 	                     (long) has_writable, (long) is_writable,
59955 	                     (long) has_value, (duk_tval *) (idx_value >= 0 ? duk_get_tval(thr, idx_value) : NULL),
59956 	                     (long) has_get, (void *) get, (duk_heaphdr *) get,
59957 	                     (long) has_set, (void *) set, (duk_heaphdr *) set,
59958 	                     (long) arr_idx, (long) throw_flag));
59959 
59960 	/*
59961 	 *  Array exotic behaviors can be implemented at this point.  The local variables
59962 	 *  are essentially a 'value copy' of the input descriptor (Desc), which is modified
59963 	 *  by the Array [[DefineOwnProperty]] (E5 Section 15.4.5.1).
59964 	 */
59965 
59966 	if (!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
59967 		goto skip_array_exotic;
59968 	}
59969 
59970 	if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
59971 		duk_harray *a;
59972 
59973 		/* E5 Section 15.4.5.1, step 3, steps a - i are implemented here, j - n at the end */
59974 		if (!has_value) {
59975 			DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', but no value in descriptor -> normal behavior"));
59976 			goto skip_array_exotic;
59977 		}
59978 
59979 		DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', value present in descriptor -> exotic behavior"));
59980 
59981 		/*
59982 		 *  Get old and new length
59983 		 */
59984 
59985 		a = (duk_harray *) obj;
59986 		DUK_HARRAY_ASSERT_VALID(a);
59987 		arrlen_old_len = a->length;
59988 
59989 		DUK_ASSERT(idx_value >= 0);
59990 		arrlen_new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_POSIDX(thr, idx_value));
59991 		duk_push_u32(thr, arrlen_new_len);
59992 		duk_replace(thr, idx_value);  /* step 3.e: replace 'Desc.[[Value]]' */
59993 
59994 		DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) arrlen_old_len, (long) arrlen_new_len));
59995 
59996 		if (arrlen_new_len >= arrlen_old_len) {
59997 			/* standard behavior, step 3.f.i */
59998 			DUK_DDD(DUK_DDDPRINT("new length is same or higher as previous => standard behavior"));
59999 			goto skip_array_exotic;
60000 		}
60001 		DUK_DDD(DUK_DDDPRINT("new length is smaller than previous => exotic post behavior"));
60002 
60003 		/* XXX: consolidated algorithm step 15.f -> redundant? */
60004 		if (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {
60005 			/* Array .length is always non-configurable; if it's also
60006 			 * non-writable, don't allow it to be written.
60007 			 */
60008 			goto fail_not_configurable;
60009 		}
60010 
60011 		/* steps 3.h and 3.i */
60012 		if (has_writable && !is_writable) {
60013 			DUK_DDD(DUK_DDDPRINT("desc writable is false, force it back to true, and flag pending write protect"));
60014 			is_writable = 1;
60015 			pending_write_protect = 1;
60016 		}
60017 
60018 		/* remaining actual steps are carried out if standard DefineOwnProperty succeeds */
60019 	} else if (arr_idx != DUK__NO_ARRAY_INDEX) {
60020 		/* XXX: any chance of unifying this with the 'length' key handling? */
60021 
60022 		/* E5 Section 15.4.5.1, step 4 */
60023 		duk_uint32_t old_len;
60024 		duk_harray *a;
60025 
60026 		a = (duk_harray *) obj;
60027 		DUK_HARRAY_ASSERT_VALID(a);
60028 
60029 		old_len = a->length;
60030 
60031 		if (arr_idx >= old_len) {
60032 			DUK_DDD(DUK_DDDPRINT("defineProperty requires array length update "
60033 			                     "(arr_idx=%ld, old_len=%ld)",
60034 			                     (long) arr_idx, (long) old_len));
60035 
60036 			if (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {
60037 				/* Array .length is always non-configurable, so
60038 				 * if it's also non-writable, don't allow a value
60039 				 * write.  With force flag allow writing.
60040 				 */
60041 				goto fail_not_configurable;
60042 			}
60043 
60044 			/* actual update happens once write has been completed without
60045 			 * error below.
60046 			 */
60047 			DUK_ASSERT(arr_idx != 0xffffffffUL);
60048 			arridx_new_array_length = arr_idx + 1;
60049 		} else {
60050 			DUK_DDD(DUK_DDDPRINT("defineProperty does not require length update "
60051 			                     "(arr_idx=%ld, old_len=%ld) -> standard behavior",
60052 			                     (long) arr_idx, (long) old_len));
60053 		}
60054 	}
60055  skip_array_exotic:
60056 
60057 	/* XXX: There is currently no support for writing buffer object
60058 	 * indexed elements here.  Attempt to do so will succeed and
60059 	 * write a concrete property into the buffer object.  This should
60060 	 * be fixed at some point but because buffers are a custom feature
60061 	 * anyway, this is relatively unimportant.
60062 	 */
60063 
60064 	/*
60065 	 *  Actual Object.defineProperty() default algorithm.
60066 	 */
60067 
60068 	/*
60069 	 *  First check whether property exists; if not, simple case.  This covers
60070 	 *  steps 1-4.
60071 	 */
60072 
60073 	if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE)) {
60074 		DUK_DDD(DUK_DDDPRINT("property does not exist"));
60075 
60076 		if (!DUK_HOBJECT_HAS_EXTENSIBLE(obj) && !force_flag) {
60077 			goto fail_not_extensible;
60078 		}
60079 
60080 #if defined(DUK_USE_ROM_OBJECTS)
60081 		/* ROM objects are never extensible but force flag may
60082 		 * allow us to come here anyway.
60083 		 */
60084 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj) || !DUK_HOBJECT_HAS_EXTENSIBLE(obj));
60085 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
60086 			DUK_D(DUK_DPRINT("attempt to define property on a read-only target object"));
60087 			goto fail_not_configurable;
60088 		}
60089 #endif
60090 
60091 		/* XXX: share final setting code for value and flags?  difficult because
60092 		 * refcount code is different.  Share entry allocation?  But can't allocate
60093 		 * until array index checked.
60094 		 */
60095 
60096 		/* steps 4.a and 4.b are tricky */
60097 		if (has_set || has_get) {
60098 			duk_int_t e_idx;
60099 
60100 			DUK_DDD(DUK_DDDPRINT("create new accessor property"));
60101 
60102 			DUK_ASSERT(has_set || set == NULL);
60103 			DUK_ASSERT(has_get || get == NULL);
60104 			DUK_ASSERT(!has_value);
60105 			DUK_ASSERT(!has_writable);
60106 
60107 			new_flags = DUK_PROPDESC_FLAG_ACCESSOR;  /* defaults, E5 Section 8.6.1, Table 7 */
60108 			if (has_enumerable && is_enumerable) {
60109 				new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
60110 			}
60111 			if (has_configurable && is_configurable) {
60112 				new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
60113 			}
60114 
60115 			if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
60116 				DUK_DDD(DUK_DDDPRINT("accessor cannot go to array part, abandon array"));
60117 				duk__abandon_array_part(thr, obj);
60118 			}
60119 
60120 			/* write to entry part */
60121 			e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);
60122 			DUK_ASSERT(e_idx >= 0);
60123 
60124 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, e_idx, get);
60125 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, e_idx, set);
60126 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
60127 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);
60128 
60129 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
60130 			goto success_exotics;
60131 		} else {
60132 			duk_int_t e_idx;
60133 			duk_tval *tv2;
60134 
60135 			DUK_DDD(DUK_DDDPRINT("create new data property"));
60136 
60137 			DUK_ASSERT(!has_set);
60138 			DUK_ASSERT(!has_get);
60139 
60140 			new_flags = 0;  /* defaults, E5 Section 8.6.1, Table 7 */
60141 			if (has_writable && is_writable) {
60142 				new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
60143 			}
60144 			if (has_enumerable && is_enumerable) {
60145 				new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
60146 			}
60147 			if (has_configurable && is_configurable) {
60148 				new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
60149 			}
60150 			if (has_value) {
60151 				duk_tval *tv_tmp = duk_require_tval(thr, idx_value);
60152 				DUK_TVAL_SET_TVAL(&tv, tv_tmp);
60153 			} else {
60154 				DUK_TVAL_SET_UNDEFINED(&tv);  /* default value */
60155 			}
60156 
60157 			if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
60158 				if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
60159 					DUK_DDD(DUK_DDDPRINT("new data property attributes match array defaults, attempt to write to array part"));
60160 					tv2 = duk__obtain_arridx_slot(thr, arr_idx, obj);
60161 					if (tv2 == NULL) {
60162 						DUK_DDD(DUK_DDDPRINT("failed writing to array part, abandoned array"));
60163 					} else {
60164 						DUK_DDD(DUK_DDDPRINT("success in writing to array part"));
60165 						DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(obj));
60166 						DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv2));
60167 						DUK_TVAL_SET_TVAL(tv2, &tv);
60168 						DUK_TVAL_INCREF(thr, tv2);
60169 						goto success_exotics;
60170 					}
60171 				} else {
60172 					DUK_DDD(DUK_DDDPRINT("new data property cannot go to array part, abandon array"));
60173 					duk__abandon_array_part(thr, obj);
60174 				}
60175 				/* fall through */
60176 			}
60177 
60178 			/* write to entry part */
60179 			e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);
60180 			DUK_ASSERT(e_idx >= 0);
60181 			tv2 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
60182 			DUK_TVAL_SET_TVAL(tv2, &tv);
60183 			DUK_TVAL_INCREF(thr, tv2);
60184 
60185 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
60186 			goto success_exotics;
60187 		}
60188 		DUK_UNREACHABLE();
60189 	}
60190 
60191 	/* we currently assume virtual properties are not configurable (as none of them are) */
60192 	DUK_ASSERT((curr.e_idx >= 0 || curr.a_idx >= 0) || !(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE));
60193 
60194 	/* [obj key desc value get set curr_value] */
60195 
60196 	/*
60197 	 *  Property already exists.  Steps 5-6 detect whether any changes need
60198 	 *  to be made.
60199 	 */
60200 
60201 	if (has_enumerable) {
60202 		if (is_enumerable) {
60203 			if (!(curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE)) {
60204 				goto need_check;
60205 			}
60206 		} else {
60207 			if (curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE) {
60208 				goto need_check;
60209 			}
60210 		}
60211 	}
60212 	if (has_configurable) {
60213 		if (is_configurable) {
60214 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
60215 				goto need_check;
60216 			}
60217 		} else {
60218 			if (curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
60219 				goto need_check;
60220 			}
60221 		}
60222 	}
60223 	if (has_value) {
60224 		duk_tval *tmp1;
60225 		duk_tval *tmp2;
60226 
60227 		/* attempt to change from accessor to data property */
60228 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
60229 			goto need_check;
60230 		}
60231 
60232 		tmp1 = duk_require_tval(thr, -1);         /* curr value */
60233 		tmp2 = duk_require_tval(thr, idx_value);  /* new value */
60234 		if (!duk_js_samevalue(tmp1, tmp2)) {
60235 			goto need_check;
60236 		}
60237 	}
60238 	if (has_writable) {
60239 		/* attempt to change from accessor to data property */
60240 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
60241 			goto need_check;
60242 		}
60243 
60244 		if (is_writable) {
60245 			if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
60246 				goto need_check;
60247 			}
60248 		} else {
60249 			if (curr.flags & DUK_PROPDESC_FLAG_WRITABLE) {
60250 				goto need_check;
60251 			}
60252 		}
60253 	}
60254 	if (has_set) {
60255 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
60256 			if (set != curr.set) {
60257 				goto need_check;
60258 			}
60259 		} else {
60260 			goto need_check;
60261 		}
60262 	}
60263 	if (has_get) {
60264 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
60265 			if (get != curr.get) {
60266 				goto need_check;
60267 			}
60268 		} else {
60269 			goto need_check;
60270 		}
60271 	}
60272 
60273 	/* property exists, either 'desc' is empty, or all values
60274 	 * match (SameValue)
60275 	 */
60276 	goto success_no_exotics;
60277 
60278  need_check:
60279 
60280 	/*
60281 	 *  Some change(s) need to be made.  Steps 7-11.
60282 	 */
60283 
60284 	/* shared checks for all descriptor types */
60285 	if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
60286 		if (has_configurable && is_configurable) {
60287 			goto fail_not_configurable;
60288 		}
60289 		if (has_enumerable) {
60290 			if (curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE) {
60291 				if (!is_enumerable) {
60292 					goto fail_not_configurable;
60293 				}
60294 			} else {
60295 				if (is_enumerable) {
60296 					goto fail_not_configurable;
60297 				}
60298 			}
60299 		}
60300 	}
60301 
60302 	/* Virtual properties don't have backing so they can't mostly be
60303 	 * edited.  Some virtual properties are, however, writable: for
60304 	 * example, virtual index properties of buffer objects and Array
60305 	 * instance .length.  These are not configurable so the checks
60306 	 * above mostly cover attempts to change them, except when the
60307 	 * duk_def_prop() call is used with DUK_DEFPROP_FORCE; even in
60308 	 * that case we can't forcibly change the property attributes
60309 	 * because they don't have concrete backing.
60310 	 */
60311 
60312 	/* XXX: for ROM objects too it'd be best if value modify was
60313 	 * allowed if the value matches SameValue.
60314 	 */
60315 	/* Reject attempt to change a read-only object. */
60316 #if defined(DUK_USE_ROM_OBJECTS)
60317 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
60318 		DUK_DD(DUK_DDPRINT("attempt to define property on read-only target object"));
60319 		goto fail_not_configurable;
60320 	}
60321 #endif
60322 
60323 	/* descriptor type specific checks */
60324 	if (has_set || has_get) {
60325 		/* IsAccessorDescriptor(desc) == true */
60326 		DUK_ASSERT(!has_writable);
60327 		DUK_ASSERT(!has_value);
60328 
60329 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
60330 			/* curr and desc are accessors */
60331 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
60332 				if (has_set && set != curr.set) {
60333 					goto fail_not_configurable;
60334 				}
60335 				if (has_get && get != curr.get) {
60336 					goto fail_not_configurable;
60337 				}
60338 			}
60339 		} else {
60340 			duk_bool_t rc;
60341 			duk_tval *tv1;
60342 
60343 			/* curr is data, desc is accessor */
60344 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
60345 				goto fail_not_configurable;
60346 			}
60347 
60348 			DUK_DDD(DUK_DDDPRINT("convert property to accessor property"));
60349 			if (curr.a_idx >= 0) {
60350 				DUK_DDD(DUK_DDDPRINT("property to convert is stored in an array entry, abandon array and re-lookup"));
60351 				duk__abandon_array_part(thr, obj);
60352 				duk_pop_unsafe(thr);  /* remove old value */
60353 				rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
60354 				DUK_UNREF(rc);
60355 				DUK_ASSERT(rc != 0);
60356 				DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
60357 			}
60358 			if (curr.e_idx < 0) {
60359 				DUK_ASSERT(curr.a_idx < 0 && curr.e_idx < 0);
60360 				goto fail_virtual;  /* safeguard for virtual property */
60361 			}
60362 
60363 			DUK_ASSERT(curr.e_idx >= 0);
60364 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
60365 
60366 			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
60367 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv1);  /* XXX: just decref */
60368 
60369 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
60370 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
60371 			DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
60372 			DUK_HOBJECT_E_SLOT_SET_ACCESSOR(thr->heap, obj, curr.e_idx);
60373 
60374 			DUK_DDD(DUK_DDDPRINT("flags after data->accessor conversion: 0x%02lx",
60375 			                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
60376 			/* Update curr.flags; faster than a re-lookup. */
60377 			curr.flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
60378 			curr.flags |= DUK_PROPDESC_FLAG_ACCESSOR;
60379 		}
60380 	} else if (has_value || has_writable) {
60381 		/* IsDataDescriptor(desc) == true */
60382 		DUK_ASSERT(!has_set);
60383 		DUK_ASSERT(!has_get);
60384 
60385 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
60386 			duk_hobject *tmp;
60387 
60388 			/* curr is accessor, desc is data */
60389 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
60390 				goto fail_not_configurable;
60391 			}
60392 
60393 			/* curr is accessor -> cannot be in array part. */
60394 			DUK_ASSERT(curr.a_idx < 0);
60395 			if (curr.e_idx < 0) {
60396 				goto fail_virtual;  /* safeguard; no virtual accessors now */
60397 			}
60398 
60399 			DUK_DDD(DUK_DDDPRINT("convert property to data property"));
60400 
60401 			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
60402 			tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
60403 			DUK_UNREF(tmp);
60404 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
60405 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
60406 			tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
60407 			DUK_UNREF(tmp);
60408 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
60409 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
60410 
60411 			DUK_TVAL_SET_UNDEFINED(DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx));
60412 			DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
60413 			DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(thr->heap, obj, curr.e_idx);
60414 
60415 			DUK_DDD(DUK_DDDPRINT("flags after accessor->data conversion: 0x%02lx",
60416 			                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
60417 
60418 			/* Update curr.flags; faster than a re-lookup. */
60419 			curr.flags &= ~(DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ACCESSOR);
60420 		} else {
60421 			/* curr and desc are data */
60422 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
60423 				if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_writable && is_writable) {
60424 					goto fail_not_configurable;
60425 				}
60426 				/* Note: changing from writable to non-writable is OK */
60427 				if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_value) {
60428 					duk_tval *tmp1 = duk_require_tval(thr, -1);         /* curr value */
60429 					duk_tval *tmp2 = duk_require_tval(thr, idx_value);  /* new value */
60430 					if (!duk_js_samevalue(tmp1, tmp2)) {
60431 						goto fail_not_configurable;
60432 					}
60433 				}
60434 			}
60435 		}
60436 	} else {
60437 		/* IsGenericDescriptor(desc) == true; this means in practice that 'desc'
60438 		 * only has [[Enumerable]] or [[Configurable]] flag updates, which are
60439 		 * allowed at this point.
60440 		 */
60441 
60442 		DUK_ASSERT(!has_value && !has_writable && !has_get && !has_set);
60443 	}
60444 
60445 	/*
60446 	 *  Start doing property attributes updates.  Steps 12-13.
60447 	 *
60448 	 *  Start by computing new attribute flags without writing yet.
60449 	 *  Property type conversion is done above if necessary.
60450 	 */
60451 
60452 	new_flags = curr.flags;
60453 
60454 	if (has_enumerable) {
60455 		if (is_enumerable) {
60456 			new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
60457 		} else {
60458 			new_flags &= ~DUK_PROPDESC_FLAG_ENUMERABLE;
60459 		}
60460 	}
60461 	if (has_configurable) {
60462 		if (is_configurable) {
60463 			new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
60464 		} else {
60465 			new_flags &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
60466 		}
60467 	}
60468 	if (has_writable) {
60469 		if (is_writable) {
60470 			new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
60471 		} else {
60472 			new_flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
60473 		}
60474 	}
60475 
60476 	/* XXX: write protect after flag? -> any chance of handling it here? */
60477 
60478 	DUK_DDD(DUK_DDDPRINT("new flags that we want to write: 0x%02lx",
60479 	                     (unsigned long) new_flags));
60480 
60481 	/*
60482 	 *  Check whether we need to abandon an array part (if it exists)
60483 	 */
60484 
60485 	if (curr.a_idx >= 0) {
60486 		duk_bool_t rc;
60487 
60488 		DUK_ASSERT(curr.e_idx < 0);
60489 
60490 		if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
60491 			duk_tval *tv1, *tv2;
60492 
60493 			DUK_DDD(DUK_DDDPRINT("array index, new property attributes match array defaults, update in-place"));
60494 
60495 			DUK_ASSERT(curr.flags == DUK_PROPDESC_FLAGS_WEC);  /* must have been, since in array part */
60496 			DUK_ASSERT(!has_set);
60497 			DUK_ASSERT(!has_get);
60498 			DUK_ASSERT(idx_value >= 0);  /* must be: if attributes match and we get here the value must differ (otherwise no change) */
60499 
60500 			tv2 = duk_require_tval(thr, idx_value);
60501 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, curr.a_idx);
60502 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects; may invalidate a_idx */
60503 			goto success_exotics;
60504 		}
60505 
60506 		DUK_DDD(DUK_DDDPRINT("array index, new property attributes do not match array defaults, abandon array and re-lookup"));
60507 		duk__abandon_array_part(thr, obj);
60508 		duk_pop_unsafe(thr);  /* remove old value */
60509 		rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
60510 		DUK_UNREF(rc);
60511 		DUK_ASSERT(rc != 0);
60512 		DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
60513 	}
60514 
60515 	DUK_DDD(DUK_DDDPRINT("updating existing property in entry part"));
60516 
60517 	/* Array case is handled comprehensively above: either in entry
60518 	 * part or a virtual property.
60519 	 */
60520 	DUK_ASSERT(curr.a_idx < 0);
60521 
60522 	DUK_DDD(DUK_DDDPRINT("update existing property attributes"));
60523 	if (curr.e_idx >= 0) {
60524 		DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, curr.e_idx, new_flags);
60525 	} else {
60526 		/* For Array .length the only allowed transition is for .length
60527 		 * to become non-writable.
60528 		 */
60529 		if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
60530 			duk_harray *a;
60531 			a = (duk_harray *) obj;
60532 			DUK_DD(DUK_DDPRINT("Object.defineProperty() attribute update for duk_harray .length -> %02lx", (unsigned long) new_flags));
60533 			DUK_HARRAY_ASSERT_VALID(a);
60534 			if ((new_flags & DUK_PROPDESC_FLAGS_EC) != (curr.flags & DUK_PROPDESC_FLAGS_EC)) {
60535 				DUK_D(DUK_DPRINT("Object.defineProperty() attempt to change virtual array .length enumerable or configurable attribute, fail"));
60536 				goto fail_virtual;
60537 			}
60538 			if (new_flags & DUK_PROPDESC_FLAG_WRITABLE) {
60539 				DUK_HARRAY_SET_LENGTH_WRITABLE(a);
60540 			} else {
60541 				DUK_HARRAY_SET_LENGTH_NONWRITABLE(a);
60542 			}
60543 		}
60544 	}
60545 
60546 	if (has_set) {
60547 		duk_hobject *tmp;
60548 
60549 		/* Virtual properties are non-configurable but with a 'force'
60550 		 * flag we might come here so check explicitly for virtual.
60551 		 */
60552 		if (curr.e_idx < 0) {
60553 			goto fail_virtual;
60554 		}
60555 
60556 		DUK_DDD(DUK_DDDPRINT("update existing property setter"));
60557 		DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
60558 
60559 		tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
60560 		DUK_UNREF(tmp);
60561 		DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, set);
60562 		DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);
60563 		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects; may invalidate e_idx */
60564 	}
60565 	if (has_get) {
60566 		duk_hobject *tmp;
60567 
60568 		if (curr.e_idx < 0) {
60569 			goto fail_virtual;
60570 		}
60571 
60572 		DUK_DDD(DUK_DDDPRINT("update existing property getter"));
60573 		DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
60574 
60575 		tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
60576 		DUK_UNREF(tmp);
60577 		DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, get);
60578 		DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
60579 		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects; may invalidate e_idx */
60580 	}
60581 	if (has_value) {
60582 		duk_tval *tv1, *tv2;
60583 
60584 		DUK_DDD(DUK_DDDPRINT("update existing property value"));
60585 
60586 		if (curr.e_idx >= 0) {
60587 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
60588 			tv2 = duk_require_tval(thr, idx_value);
60589 			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
60590 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects; may invalidate e_idx */
60591 		} else {
60592 			DUK_ASSERT(curr.a_idx < 0);  /* array part case handled comprehensively previously */
60593 
60594 			DUK_DD(DUK_DDPRINT("Object.defineProperty(), value update for virtual property"));
60595 			/* XXX: Uint8Array and other typed array virtual writes not currently
60596 			 * handled.
60597 			 */
60598 			if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
60599 				duk_harray *a;
60600 				a = (duk_harray *) obj;
60601 				DUK_DD(DUK_DDPRINT("Object.defineProperty() value update for duk_harray .length -> %ld", (long) arrlen_new_len));
60602 				DUK_HARRAY_ASSERT_VALID(a);
60603 				a->length = arrlen_new_len;
60604 			} else {
60605 				goto fail_virtual;  /* should not happen */
60606 			}
60607 		}
60608 	}
60609 
60610 	/*
60611 	 *  Standard algorithm succeeded without errors, check for exotic post-behaviors.
60612 	 *
60613 	 *  Arguments exotic behavior in E5 Section 10.6 occurs after the standard
60614 	 *  [[DefineOwnProperty]] has completed successfully.
60615 	 *
60616 	 *  Array exotic behavior in E5 Section 15.4.5.1 is implemented partly
60617 	 *  prior to the default [[DefineOwnProperty]], but:
60618 	 *    - for an array index key (e.g. "10") the final 'length' update occurs here
60619 	 *    - for 'length' key the element deletion and 'length' update occurs here
60620 	 */
60621 
60622  success_exotics:
60623 
60624 	/* curr.a_idx or curr.e_idx may have been invalidated by side effects
60625 	 * above.
60626 	 */
60627 
60628 	/* [obj key desc value get set curr_value] */
60629 
60630 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
60631 		duk_harray *a;
60632 
60633 		a = (duk_harray *) obj;
60634 		DUK_HARRAY_ASSERT_VALID(a);
60635 
60636 		if (arridx_new_array_length > 0) {
60637 			/*
60638 			 *  Note: zero works as a "no update" marker because the new length
60639 			 *  can never be zero after a new property is written.
60640 			 */
60641 
60642 			/* E5 Section 15.4.5.1, steps 4.e.i - 4.e.ii */
60643 
60644 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, pending array length update to: %ld",
60645 			                     (long) arridx_new_array_length));
60646 
60647 			a->length = arridx_new_array_length;
60648 		}
60649 
60650 		if (key == DUK_HTHREAD_STRING_LENGTH(thr) && arrlen_new_len < arrlen_old_len) {
60651 			/*
60652 			 *  E5 Section 15.4.5.1, steps 3.k - 3.n.  The order at the end combines
60653 			 *  the error case 3.l.iii and the success case 3.m-3.n.
60654 			 */
60655 
60656 			/* XXX: investigate whether write protect can be handled above, if we
60657 			 * just update length here while ignoring its protected status
60658 			 */
60659 
60660 			duk_uint32_t result_len;
60661 			duk_bool_t rc;
60662 
60663 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key is 'length', exotic array behavior, "
60664 			                     "doing array element deletion and length update"));
60665 
60666 			rc = duk__handle_put_array_length_smaller(thr, obj, arrlen_old_len, arrlen_new_len, force_flag, &result_len);
60667 
60668 			/* update length (curr points to length, and we assume it's still valid) */
60669 			DUK_ASSERT(result_len >= arrlen_new_len && result_len <= arrlen_old_len);
60670 
60671 			a->length = result_len;
60672 
60673 			if (pending_write_protect) {
60674 				DUK_DDD(DUK_DDDPRINT("setting array length non-writable (pending writability update)"));
60675 				DUK_HARRAY_SET_LENGTH_NONWRITABLE(a);
60676 			}
60677 
60678 			/* XXX: shrink array allocation or entries compaction here? */
60679 			if (!rc) {
60680 				DUK_DD(DUK_DDPRINT("array length write only partially successful"));
60681 				goto fail_not_configurable;
60682 			}
60683 		}
60684 	} else if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
60685 		duk_hobject *map;
60686 		duk_hobject *varenv;
60687 
60688 		DUK_ASSERT(arridx_new_array_length == 0);
60689 		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));  /* traits are separate; in particular, arguments not an array */
60690 
60691 		map = NULL;
60692 		varenv = NULL;
60693 		if (!duk__lookup_arguments_map(thr, obj, key, &curr, &map, &varenv)) {
60694 			goto success_no_exotics;
60695 		}
60696 		DUK_ASSERT(map != NULL);
60697 		DUK_ASSERT(varenv != NULL);
60698 
60699 		/* [obj key desc value get set curr_value varname] */
60700 
60701 		if (has_set || has_get) {
60702 			/* = IsAccessorDescriptor(Desc) */
60703 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map' "
60704 			                     "changed to an accessor, delete arguments binding"));
60705 
60706 			(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
60707 		} else {
60708 			/* Note: this order matters (final value before deleting map entry must be done) */
60709 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
60710 			                     "check for value update / binding deletion"));
60711 
60712 			if (has_value) {
60713 				duk_hstring *varname;
60714 
60715 				DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
60716 				                     "update bound value (variable/argument)"));
60717 
60718 				varname = duk_require_hstring(thr, -1);
60719 				DUK_ASSERT(varname != NULL);
60720 
60721 				DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
60722 				                     "key=%!O, varname=%!O, value=%!T",
60723 				                     (duk_heaphdr *) key,
60724 				                     (duk_heaphdr *) varname,
60725 				                     (duk_tval *) duk_require_tval(thr, idx_value)));
60726 
60727 				/* strict flag for putvar comes from our caller (currently: fixed) */
60728 				duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(thr, idx_value), 1 /*throw_flag*/);
60729 			}
60730 			if (has_writable && !is_writable) {
60731 				DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
60732 				                     "changed to non-writable, delete arguments binding"));
60733 
60734 				(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
60735 			}
60736 		}
60737 
60738 		/* 'varname' is in stack in this else branch, leaving an unbalanced stack below,
60739 		 * but this doesn't matter now.
60740 		 */
60741 	}
60742 
60743  success_no_exotics:
60744 	/* Some code paths use NORZ macros for simplicity, ensure refzero
60745 	 * handling is completed.
60746 	 */
60747 	DUK_REFZERO_CHECK_SLOW(thr);
60748 	return 1;
60749 
60750  fail_not_extensible:
60751 	if (throw_flag) {
60752 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);
60753 		DUK_WO_NORETURN(return 0;);
60754 	}
60755 	return 0;
60756 
60757  fail_virtual:  /* just use the same "not configurable" error message" */
60758  fail_not_configurable:
60759 	if (throw_flag) {
60760 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
60761 		DUK_WO_NORETURN(return 0;);
60762 	}
60763 	return 0;
60764 }
60765 
60766 /*
60767  *  Object.prototype.hasOwnProperty() and Object.prototype.propertyIsEnumerable().
60768  */
60769 
60770 DUK_INTERNAL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_small_uint_t required_desc_flags) {
60771 	duk_hstring *h_v;
60772 	duk_hobject *h_obj;
60773 	duk_propdesc desc;
60774 	duk_bool_t ret;
60775 
60776 	/* coercion order matters */
60777 	h_v = duk_to_hstring_acceptsymbol(thr, 0);
60778 	DUK_ASSERT(h_v != NULL);
60779 
60780 	h_obj = duk_push_this_coercible_to_object(thr);
60781 	DUK_ASSERT(h_obj != NULL);
60782 
60783 	ret = duk_hobject_get_own_propdesc(thr, h_obj, h_v, &desc, 0 /*flags*/);  /* don't push value */
60784 
60785 	duk_push_boolean(thr, ret && ((desc.flags & required_desc_flags) == required_desc_flags));
60786 	return 1;
60787 }
60788 
60789 /*
60790  *  Object.seal() and Object.freeze()  (E5 Sections 15.2.3.8 and 15.2.3.9)
60791  *
60792  *  Since the algorithms are similar, a helper provides both functions.
60793  *  Freezing is essentially sealing + making plain properties non-writable.
60794  *
60795  *  Note: virtual (non-concrete) properties which are non-configurable but
60796  *  writable would pose some problems, but such properties do not currently
60797  *  exist (all virtual properties are non-configurable and non-writable).
60798  *  If they did exist, the non-configurability does NOT prevent them from
60799  *  becoming non-writable.  However, this change should be recorded somehow
60800  *  so that it would turn up (e.g. when getting the property descriptor),
60801  *  requiring some additional flags in the object.
60802  */
60803 
60804 DUK_INTERNAL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze) {
60805 	duk_uint_fast32_t i;
60806 
60807 	DUK_ASSERT(thr != NULL);
60808 	DUK_ASSERT(thr->heap != NULL);
60809 	DUK_ASSERT(obj != NULL);
60810 
60811 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
60812 
60813 #if defined(DUK_USE_ROM_OBJECTS)
60814 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
60815 		DUK_DD(DUK_DDPRINT("attempt to seal/freeze a readonly object, reject"));
60816 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
60817 		DUK_WO_NORETURN(return;);
60818 	}
60819 #endif
60820 
60821 	/*
60822 	 *  Abandon array part because all properties must become non-configurable.
60823 	 *  Note that this is now done regardless of whether this is always the case
60824 	 *  (skips check, but performance problem if caller would do this many times
60825 	 *  for the same object; not likely).
60826 	 */
60827 
60828 	duk__abandon_array_part(thr, obj);
60829 	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) == 0);
60830 
60831 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
60832 		duk_uint8_t *fp;
60833 
60834 		/* since duk__abandon_array_part() causes a resize, there should be no gaps in keys */
60835 		DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != NULL);
60836 
60837 		/* avoid multiple computations of flags address; bypasses macros */
60838 		fp = DUK_HOBJECT_E_GET_FLAGS_PTR(thr->heap, obj, i);
60839 		if (is_freeze && !((*fp) & DUK_PROPDESC_FLAG_ACCESSOR)) {
60840 			*fp &= ~(DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE);
60841 		} else {
60842 			*fp &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
60843 		}
60844 	}
60845 
60846 	DUK_HOBJECT_CLEAR_EXTENSIBLE(obj);
60847 
60848 	/* no need to compact since we already did that in duk__abandon_array_part()
60849 	 * (regardless of whether an array part existed or not.
60850 	 */
60851 
60852 	return;
60853 }
60854 
60855 /*
60856  *  Object.isSealed() and Object.isFrozen()  (E5 Sections 15.2.3.11, 15.2.3.13)
60857  *
60858  *  Since the algorithms are similar, a helper provides both functions.
60859  *  Freezing is essentially sealing + making plain properties non-writable.
60860  *
60861  *  Note: all virtual (non-concrete) properties are currently non-configurable
60862  *  and non-writable (and there are no accessor virtual properties), so they don't
60863  *  need to be considered here now.
60864  */
60865 
60866 DUK_INTERNAL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen) {
60867 	duk_uint_fast32_t i;
60868 
60869 	DUK_ASSERT(obj != NULL);
60870 	DUK_UNREF(thr);
60871 
60872 	/* Note: no allocation pressure, no need to check refcounts etc */
60873 
60874 	/* must not be extensible */
60875 	if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
60876 		return 0;
60877 	}
60878 
60879 	/* all virtual properties are non-configurable and non-writable */
60880 
60881 	/* entry part must not contain any configurable properties, or
60882 	 * writable properties (if is_frozen).
60883 	 */
60884 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
60885 		duk_small_uint_t flags;
60886 
60887 		if (!DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i)) {
60888 			continue;
60889 		}
60890 
60891 		/* avoid multiple computations of flags address; bypasses macros */
60892 		flags = (duk_small_uint_t) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
60893 
60894 		if (flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
60895 			return 0;
60896 		}
60897 		if (is_frozen &&
60898 		    !(flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
60899 		    (flags & DUK_PROPDESC_FLAG_WRITABLE)) {
60900 			return 0;
60901 		}
60902 	}
60903 
60904 	/* array part must not contain any non-unused properties, as they would
60905 	 * be configurable and writable.
60906 	 */
60907 	for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
60908 		duk_tval *tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
60909 		if (!DUK_TVAL_IS_UNUSED(tv)) {
60910 			return 0;
60911 		}
60912 	}
60913 
60914 	return 1;
60915 }
60916 
60917 /*
60918  *  Object.preventExtensions() and Object.isExtensible()  (E5 Sections 15.2.3.10, 15.2.3.13)
60919  *
60920  *  Not needed, implemented by macros DUK_HOBJECT_{HAS,CLEAR,SET}_EXTENSIBLE
60921  *  and the Object built-in bindings.
60922  */
60923 
60924 /* automatic undefs */
60925 #undef DUK__HASH_DELETED
60926 #undef DUK__HASH_UNUSED
60927 #undef DUK__NO_ARRAY_INDEX
60928 #undef DUK__VALSTACK_PROXY_LOOKUP
60929 #undef DUK__VALSTACK_SPACE
60930 /*
60931  *  duk_hstring assertion helpers.
60932  */
60933 
60934 /* #include duk_internal.h -> already included */
60935 
60936 #if defined(DUK_USE_ASSERTIONS)
60937 
60938 DUK_INTERNAL void duk_hstring_assert_valid(duk_hstring *h) {
60939 	DUK_ASSERT(h != NULL);
60940 }
60941 
60942 #endif  /* DUK_USE_ASSERTIONS */
60943 /*
60944  *  Misc support functions
60945  */
60946 
60947 /* #include duk_internal.h -> already included */
60948 
60949 /*
60950  *  duk_hstring charCodeAt, with and without surrogate awareness
60951  */
60952 
60953 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) {
60954 	duk_uint32_t boff;
60955 	const duk_uint8_t *p, *p_start, *p_end;
60956 	duk_ucodepoint_t cp1;
60957 	duk_ucodepoint_t cp2;
60958 
60959 	/* Caller must check character offset to be inside the string. */
60960 	DUK_ASSERT(thr != NULL);
60961 	DUK_ASSERT(h != NULL);
60962 	DUK_ASSERT_DISABLE(pos >= 0);  /* unsigned */
60963 	DUK_ASSERT(pos < (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h));
60964 
60965 	boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint32_t) pos);
60966 	DUK_DDD(DUK_DDDPRINT("charCodeAt: pos=%ld -> boff=%ld, str=%!O",
60967 	                     (long) pos, (long) boff, (duk_heaphdr *) h));
60968 	DUK_ASSERT_DISABLE(boff >= 0);
60969 	DUK_ASSERT(boff < DUK_HSTRING_GET_BYTELEN(h));
60970 
60971 	p_start = DUK_HSTRING_GET_DATA(h);
60972 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
60973 	p = p_start + boff;
60974 	DUK_DDD(DUK_DDDPRINT("p_start=%p, p_end=%p, p=%p",
60975 	                     (const void *) p_start, (const void *) p_end,
60976 	                     (const void *) p));
60977 
60978 	/* For invalid UTF-8 (never happens for standard ECMAScript strings)
60979 	 * return U+FFFD replacement character.
60980 	 */
60981 	if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp1)) {
60982 		if (surrogate_aware && cp1 >= 0xd800UL && cp1 <= 0xdbffUL) {
60983 			/* The decode helper is memory safe even if 'cp1' was
60984 			 * decoded at the end of the string and 'p' is no longer
60985 			 * within string memory range.
60986 			 */
60987 			cp2 = 0;  /* If call fails, this is left untouched and won't match cp2 check. */
60988 			(void) duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp2);
60989 			if (cp2 >= 0xdc00UL && cp2 <= 0xdfffUL) {
60990 				cp1 = (duk_ucodepoint_t) (((cp1 - 0xd800UL) << 10) + (cp2 - 0xdc00UL) + 0x10000UL);
60991 			}
60992 		}
60993 	} else {
60994 		cp1 = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
60995 	}
60996 
60997 	return cp1;
60998 }
60999 
61000 /*
61001  *  duk_hstring charlen, when lazy charlen disabled
61002  */
61003 
61004 #if !defined(DUK_USE_HSTRING_LAZY_CLEN)
61005 #if !defined(DUK_USE_HSTRING_CLEN)
61006 #error non-lazy duk_hstring charlen but DUK_USE_HSTRING_CLEN not set
61007 #endif
61008 DUK_INTERNAL void duk_hstring_init_charlen(duk_hstring *h) {
61009 	duk_uint32_t clen;
61010 
61011 	DUK_ASSERT(h != NULL);
61012 	DUK_ASSERT(!DUK_HSTRING_HAS_ASCII(h));
61013 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
61014 
61015 	clen = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
61016 #if defined(DUK_USE_STRLEN16)
61017 	DUK_ASSERT(clen <= 0xffffUL);  /* Bytelength checked during interning. */
61018 	h->clen16 = (duk_uint16_t) clen;
61019 #else
61020 	h->clen = (duk_uint32_t) clen;
61021 #endif
61022 	if (DUK_LIKELY(clen == DUK_HSTRING_GET_BYTELEN(h))) {
61023 		DUK_HSTRING_SET_ASCII(h);
61024 	}
61025 }
61026 
61027 DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
61028 #if defined(DUK_USE_STRLEN16)
61029 	return h->clen16;
61030 #else
61031 	return h->clen;
61032 #endif
61033 }
61034 #endif  /* !DUK_USE_HSTRING_LAZY_CLEN */
61035 
61036 /*
61037  *  duk_hstring charlen, when lazy charlen enabled
61038  */
61039 
61040 #if defined(DUK_USE_HSTRING_LAZY_CLEN)
61041 #if defined(DUK_USE_HSTRING_CLEN)
61042 DUK_LOCAL DUK_COLD duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h) {
61043 	duk_size_t res;
61044 
61045 	DUK_ASSERT(h->clen == 0);  /* Checked by caller. */
61046 
61047 #if defined(DUK_USE_ROM_STRINGS)
61048 	/* ROM strings have precomputed clen, but if the computed clen is zero
61049 	 * we can still come here and can't write anything.
61050 	 */
61051 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) {
61052 		return 0;
61053 	}
61054 #endif
61055 
61056 	res = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
61057 #if defined(DUK_USE_STRLEN16)
61058 	DUK_ASSERT(res <= 0xffffUL);  /* Bytelength checked during interning. */
61059 	h->clen16 = (duk_uint16_t) res;
61060 #else
61061 	h->clen = (duk_uint32_t) res;
61062 #endif
61063 	if (DUK_LIKELY(res == DUK_HSTRING_GET_BYTELEN(h))) {
61064 		DUK_HSTRING_SET_ASCII(h);
61065 	}
61066 	return res;
61067 }
61068 #else  /* DUK_USE_HSTRING_CLEN */
61069 DUK_LOCAL duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h) {
61070 	if (DUK_LIKELY(DUK_HSTRING_HAS_ASCII(h))) {
61071 		/* Most practical strings will go here. */
61072 		return DUK_HSTRING_GET_BYTELEN(h);
61073 	} else {
61074 		/* ASCII flag is lazy, so set it here. */
61075 		duk_size_t res;
61076 
61077 		/* XXX: here we could use the strcache to speed up the
61078 		 * computation (matters for 'i < str.length' loops).
61079 		 */
61080 
61081 		res = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
61082 
61083 #if defined(DUK_USE_ROM_STRINGS)
61084 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) {
61085 			/* For ROM strings, can't write anything; ASCII flag
61086 			 * is preset so we don't need to update it.
61087 			 */
61088 			return res;
61089 		}
61090 #endif
61091 		if (DUK_LIKELY(res == DUK_HSTRING_GET_BYTELEN(h))) {
61092 			DUK_HSTRING_SET_ASCII(h);
61093 		}
61094 		return res;
61095 	}
61096 }
61097 #endif  /* DUK_USE_HSTRING_CLEN */
61098 
61099 #if defined(DUK_USE_HSTRING_CLEN)
61100 DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
61101 #if defined(DUK_USE_STRLEN16)
61102 	if (DUK_LIKELY(h->clen16 != 0)) {
61103 		return h->clen16;
61104 	}
61105 #else
61106 	if (DUK_LIKELY(h->clen != 0)) {
61107 		return h->clen;
61108 	}
61109 #endif
61110 	return duk__hstring_get_charlen_slowpath(h);
61111 }
61112 #else  /* DUK_USE_HSTRING_CLEN */
61113 DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
61114 	/* Always use slow path. */
61115 	return duk__hstring_get_charlen_slowpath(h);
61116 }
61117 #endif  /* DUK_USE_HSTRING_CLEN */
61118 #endif  /* DUK_USE_HSTRING_LAZY_CLEN */
61119 
61120 /*
61121  *  Compare duk_hstring to an ASCII cstring.
61122  */
61123 
61124 DUK_INTERNAL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const char *cstr) {
61125 	duk_size_t len;
61126 
61127 	DUK_ASSERT(h != NULL);
61128 	DUK_ASSERT(cstr != NULL);
61129 
61130 	len = DUK_STRLEN(cstr);
61131 	if (len != DUK_HSTRING_GET_BYTELEN(h)) {
61132 		return 0;
61133 	}
61134 	if (duk_memcmp((const void *) cstr, (const void *) DUK_HSTRING_GET_DATA(h), len) == 0) {
61135 		return 1;
61136 	}
61137 	return 0;
61138 }
61139 /*
61140  *  duk_hthread allocation and freeing.
61141  */
61142 
61143 /* #include duk_internal.h -> already included */
61144 
61145 /*
61146  *  Allocate initial stacks for a thread.  Note that 'thr' must be reachable
61147  *  as a garbage collection may be triggered by the allocation attempts.
61148  *  Returns zero (without leaking memory) if init fails.
61149  */
61150 
61151 DUK_INTERNAL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr) {
61152 	duk_size_t alloc_size;
61153 	duk_size_t i;
61154 
61155 	DUK_ASSERT(heap != NULL);
61156 	DUK_ASSERT(thr != NULL);
61157 	DUK_ASSERT(thr->valstack == NULL);
61158 	DUK_ASSERT(thr->valstack_end == NULL);
61159 	DUK_ASSERT(thr->valstack_alloc_end == NULL);
61160 	DUK_ASSERT(thr->valstack_bottom == NULL);
61161 	DUK_ASSERT(thr->valstack_top == NULL);
61162 	DUK_ASSERT(thr->callstack_curr == NULL);
61163 
61164 	/* valstack */
61165 	DUK_ASSERT(DUK_VALSTACK_API_ENTRY_MINIMUM <= DUK_VALSTACK_INITIAL_SIZE);
61166 	alloc_size = sizeof(duk_tval) * DUK_VALSTACK_INITIAL_SIZE;
61167 	thr->valstack = (duk_tval *) DUK_ALLOC(heap, alloc_size);
61168 	if (!thr->valstack) {
61169 		goto fail;
61170 	}
61171 	duk_memzero(thr->valstack, alloc_size);
61172 	thr->valstack_end = thr->valstack + DUK_VALSTACK_API_ENTRY_MINIMUM;
61173 	thr->valstack_alloc_end = thr->valstack + DUK_VALSTACK_INITIAL_SIZE;
61174 	thr->valstack_bottom = thr->valstack;
61175 	thr->valstack_top = thr->valstack;
61176 
61177 	for (i = 0; i < DUK_VALSTACK_INITIAL_SIZE; i++) {
61178 		DUK_TVAL_SET_UNDEFINED(&thr->valstack[i]);
61179 	}
61180 
61181 	return 1;
61182 
61183  fail:
61184 	DUK_FREE(heap, thr->valstack);
61185 	DUK_ASSERT(thr->callstack_curr == NULL);
61186 
61187 	thr->valstack = NULL;
61188 	return 0;
61189 }
61190 
61191 /* For indirect allocs. */
61192 
61193 DUK_INTERNAL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud) {
61194 	duk_hthread *thr = (duk_hthread *) ud;
61195 	DUK_UNREF(heap);
61196 	return (void *) thr->valstack;
61197 }
61198 /*
61199  *  Initialize built-in objects.  Current thread must have a valstack
61200  *  and initialization errors may longjmp, so a setjmp() catch point
61201  *  must exist.
61202  */
61203 
61204 /* #include duk_internal.h -> already included */
61205 
61206 /*
61207  *  Encoding constants, must match genbuiltins.py
61208  */
61209 
61210 #define DUK__PROP_FLAGS_BITS             3
61211 #define DUK__LENGTH_PROP_BITS            3
61212 #define DUK__NARGS_BITS                  3
61213 #define DUK__PROP_TYPE_BITS              3
61214 
61215 #define DUK__NARGS_VARARGS_MARKER        0x07
61216 
61217 #define DUK__PROP_TYPE_DOUBLE            0
61218 #define DUK__PROP_TYPE_STRING            1
61219 #define DUK__PROP_TYPE_STRIDX            2
61220 #define DUK__PROP_TYPE_BUILTIN           3
61221 #define DUK__PROP_TYPE_UNDEFINED         4
61222 #define DUK__PROP_TYPE_BOOLEAN_TRUE      5
61223 #define DUK__PROP_TYPE_BOOLEAN_FALSE     6
61224 #define DUK__PROP_TYPE_ACCESSOR          7
61225 
61226 /*
61227  *  Create built-in objects by parsing an init bitstream generated
61228  *  by genbuiltins.py.
61229  */
61230 
61231 #if defined(DUK_USE_ROM_OBJECTS)
61232 #if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
61233 DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
61234 	duk_hobject *h_global;
61235 #if defined(DUK_USE_ROM_GLOBAL_CLONE)
61236 	duk_hobject *h_oldglobal;
61237 	duk_uint8_t *props;
61238 	duk_size_t alloc_size;
61239 #endif
61240 	duk_hobject *h_objenv;
61241 
61242 	/* XXX: refactor into internal helper, duk_clone_hobject() */
61243 
61244 #if defined(DUK_USE_ROM_GLOBAL_INHERIT)
61245 	/* Inherit from ROM-based global object: less RAM usage, less transparent. */
61246 	h_global = duk_push_object_helper(thr,
61247 	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
61248 	                                  DUK_HOBJECT_FLAG_FASTREFS |
61249 	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
61250 	                                  DUK_BIDX_GLOBAL);
61251 	DUK_ASSERT(h_global != NULL);
61252 #elif defined(DUK_USE_ROM_GLOBAL_CLONE)
61253 	/* Clone the properties of the ROM-based global object to create a
61254 	 * fully RAM-based global object.  Uses more memory than the inherit
61255 	 * model but more compliant.
61256 	 */
61257 	h_global = duk_push_object_helper(thr,
61258 	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
61259 	                                  DUK_HOBJECT_FLAG_FASTREFS |
61260 	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
61261 	                                  DUK_BIDX_OBJECT_PROTOTYPE);
61262 	DUK_ASSERT(h_global != NULL);
61263 	h_oldglobal = thr->builtins[DUK_BIDX_GLOBAL];
61264 	DUK_ASSERT(h_oldglobal != NULL);
61265 
61266 	/* Copy the property table verbatim; this handles attributes etc.
61267 	 * For ROM objects it's not necessary (or possible) to update
61268 	 * refcounts so leave them as is.
61269 	 */
61270 	alloc_size = DUK_HOBJECT_P_ALLOC_SIZE(h_oldglobal);
61271 	DUK_ASSERT(alloc_size > 0);
61272 	props = DUK_ALLOC_CHECKED(thr, alloc_size);
61273 	DUK_ASSERT(props != NULL);
61274 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal) != NULL);
61275 	duk_memcpy((void *) props, (const void *) DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal), alloc_size);
61276 
61277 	/* XXX: keep property attributes or tweak them here?
61278 	 * Properties will now be non-configurable even when they're
61279 	 * normally configurable for the global object.
61280 	 */
61281 
61282 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h_global) == NULL);
61283 	DUK_HOBJECT_SET_PROPS(thr->heap, h_global, props);
61284 	DUK_HOBJECT_SET_ESIZE(h_global, DUK_HOBJECT_GET_ESIZE(h_oldglobal));
61285 	DUK_HOBJECT_SET_ENEXT(h_global, DUK_HOBJECT_GET_ENEXT(h_oldglobal));
61286 	DUK_HOBJECT_SET_ASIZE(h_global, DUK_HOBJECT_GET_ASIZE(h_oldglobal));
61287 	DUK_HOBJECT_SET_HSIZE(h_global, DUK_HOBJECT_GET_HSIZE(h_oldglobal));
61288 #else
61289 #error internal error in config defines
61290 #endif
61291 
61292 	duk_hobject_compact_props(thr, h_global);
61293 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
61294 	DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL]));  /* no need to decref: ROM object */
61295 	thr->builtins[DUK_BIDX_GLOBAL] = h_global;
61296 	DUK_HOBJECT_INCREF(thr, h_global);
61297 	DUK_D(DUK_DPRINT("duplicated global object: %!O", h_global));
61298 
61299 	/* Create a fresh object environment for the global scope.  This is
61300 	 * needed so that the global scope points to the newly created RAM-based
61301 	 * global object.
61302 	 */
61303 	h_objenv = (duk_hobject *) duk_hobjenv_alloc(thr,
61304 	                                             DUK_HOBJECT_FLAG_EXTENSIBLE |
61305 	                                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
61306 	DUK_ASSERT(h_objenv != NULL);
61307 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_objenv) == NULL);
61308 	duk_push_hobject(thr, h_objenv);
61309 
61310 	DUK_ASSERT(h_global != NULL);
61311 	((duk_hobjenv *) h_objenv)->target = h_global;
61312 	DUK_HOBJECT_INCREF(thr, h_global);
61313 	DUK_ASSERT(((duk_hobjenv *) h_objenv)->has_this == 0);
61314 
61315 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL);
61316 	DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL_ENV]));  /* no need to decref: ROM object */
61317 	thr->builtins[DUK_BIDX_GLOBAL_ENV] = h_objenv;
61318 	DUK_HOBJECT_INCREF(thr, h_objenv);
61319 	DUK_D(DUK_DPRINT("duplicated global env: %!O", h_objenv));
61320 
61321 	DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) h_objenv);
61322 
61323 	duk_pop_2(thr);  /* Pop global object and global env. */
61324 }
61325 #endif  /* DUK_USE_ROM_GLOBAL_CLONE || DUK_USE_ROM_GLOBAL_INHERIT */
61326 
61327 DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
61328 	/* Setup builtins from ROM objects.  All heaps/threads will share
61329 	 * the same readonly objects.
61330 	 */
61331 	duk_small_uint_t i;
61332 
61333 	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
61334 		duk_hobject *h;
61335 		h = (duk_hobject *) DUK_LOSE_CONST(duk_rom_builtins_bidx[i]);
61336 		DUK_ASSERT(h != NULL);
61337 		thr->builtins[i] = h;
61338 	}
61339 
61340 #if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
61341 	/* By default the global object is read-only which is often much
61342 	 * more of an issue than having read-only built-in objects (like
61343 	 * RegExp, Date, etc).  Use a RAM-based copy of the global object
61344 	 * and the global environment object for convenience.
61345 	 */
61346 	duk__duplicate_ram_global_object(thr);
61347 #endif
61348 }
61349 #else  /* DUK_USE_ROM_OBJECTS */
61350 DUK_LOCAL void duk__push_stridx(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
61351 	duk_small_uint_t n;
61352 
61353 	n = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61354 	DUK_ASSERT_DISABLE(n >= 0);  /* unsigned */
61355 	DUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);
61356 	duk_push_hstring_stridx(thr, n);
61357 }
61358 DUK_LOCAL void duk__push_string(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
61359 	/* XXX: built-ins data could provide a maximum length that is
61360 	 * actually needed; bitpacked max length is now 256 bytes.
61361 	 */
61362 	duk_uint8_t tmp[DUK_BD_BITPACKED_STRING_MAXLEN];
61363 	duk_small_uint_t len;
61364 
61365 	len = duk_bd_decode_bitpacked_string(bd, tmp);
61366 	duk_push_lstring(thr, (const char *) tmp, (duk_size_t) len);
61367 }
61368 DUK_LOCAL void duk__push_stridx_or_string(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
61369 	duk_small_uint_t n;
61370 
61371 	n = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61372 	if (n == 0) {
61373 		duk__push_string(thr, bd);
61374 	} else {
61375 		n--;
61376 		DUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);
61377 		duk_push_hstring_stridx(thr, n);
61378 	}
61379 }
61380 DUK_LOCAL void duk__push_double(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
61381 	duk_double_union du;
61382 	duk_small_uint_t i;
61383 
61384 	for (i = 0; i < 8; i++) {
61385 		/* Encoding endianness must match target memory layout,
61386 		 * build scripts and genbuiltins.py must ensure this.
61387 		 */
61388 		du.uc[i] = (duk_uint8_t) duk_bd_decode(bd, 8);
61389 	}
61390 
61391 	duk_push_number(thr, du.d);  /* push operation normalizes NaNs */
61392 }
61393 
61394 DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
61395 	duk_bitdecoder_ctx bd_ctx;
61396 	duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
61397 	duk_hobject *h;
61398 	duk_small_uint_t i, j;
61399 
61400 	DUK_D(DUK_DPRINT("INITBUILTINS BEGIN: DUK_NUM_BUILTINS=%d, DUK_NUM_BUILTINS_ALL=%d", (int) DUK_NUM_BUILTINS, (int) DUK_NUM_ALL_BUILTINS));
61401 
61402 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
61403 	bd->data = (const duk_uint8_t *) duk_builtins_data;
61404 	bd->length = (duk_size_t) DUK_BUILTINS_DATA_LENGTH;
61405 
61406 	/*
61407 	 *  First create all built-in bare objects on the empty valstack.
61408 	 *
61409 	 *  Built-ins in the index range [0,DUK_NUM_BUILTINS-1] have value
61410 	 *  stack indices matching their eventual thr->builtins[] index.
61411 	 *
61412 	 *  Built-ins in the index range [DUK_NUM_BUILTINS,DUK_NUM_ALL_BUILTINS]
61413 	 *  will exist on the value stack during init but won't be placed
61414 	 *  into thr->builtins[].  These are objects referenced in some way
61415 	 *  from thr->builtins[] roots but which don't need to be indexed by
61416 	 *  Duktape through thr->builtins[] (e.g. user custom objects).
61417 	 *
61418 	 *  Internal prototypes will be incorrect (NULL) at this stage.
61419 	 */
61420 
61421 	duk_require_stack(thr, DUK_NUM_ALL_BUILTINS);
61422 
61423 	DUK_DD(DUK_DDPRINT("create empty built-ins"));
61424 	DUK_ASSERT_TOP(thr, 0);
61425 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
61426 		duk_small_uint_t class_num;
61427 		duk_small_int_t len = -1;  /* must be signed */
61428 
61429 		class_num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61430 		len = (duk_small_int_t) duk_bd_decode_flagged_signed(bd, DUK__LENGTH_PROP_BITS, (duk_int32_t) -1 /*def_value*/);
61431 
61432 		if (class_num == DUK_HOBJECT_CLASS_FUNCTION) {
61433 			duk_small_uint_t natidx;
61434 			duk_small_int_t c_nargs;  /* must hold DUK_VARARGS */
61435 			duk_c_function c_func;
61436 			duk_int16_t magic;
61437 
61438 			DUK_DDD(DUK_DDDPRINT("len=%ld", (long) len));
61439 			DUK_ASSERT(len >= 0);
61440 
61441 			natidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61442 			DUK_ASSERT(natidx != 0);
61443 			c_func = duk_bi_native_functions[natidx];
61444 			DUK_ASSERT(c_func != NULL);
61445 
61446 			c_nargs = (duk_small_int_t) duk_bd_decode_flagged_signed(bd, DUK__NARGS_BITS, len /*def_value*/);
61447 			if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
61448 				c_nargs = DUK_VARARGS;
61449 			}
61450 
61451 			/* XXX: set magic directly here? (it could share the c_nargs arg) */
61452 			(void) duk_push_c_function_builtin(thr, c_func, c_nargs);
61453 			h = duk_known_hobject(thr, -1);
61454 
61455 			/* Currently all built-in native functions are strict.
61456 			 * duk_push_c_function() now sets strict flag, so
61457 			 * assert for it.
61458 			 */
61459 			DUK_ASSERT(DUK_HOBJECT_HAS_STRICT(h));
61460 
61461 			/* XXX: function properties */
61462 
61463 			duk__push_stridx_or_string(thr, bd);
61464 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
61465 			duk_xdef_prop_stridx_short(thr,
61466 			                           -2,
61467 			                           DUK_STRIDX_NAME,
61468 			                           DUK_PROPDESC_FLAGS_C);
61469 #else
61470 			duk_pop(thr);  /* Not very ideal but good enough for now. */
61471 #endif
61472 
61473 			/* Almost all global level Function objects are constructable
61474 			 * but not all: Function.prototype is a non-constructable,
61475 			 * callable Function.
61476 			 */
61477 			if (duk_bd_decode_flag(bd)) {
61478 				DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE(h));
61479 			} else {
61480 				DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h);
61481 			}
61482 
61483 			/* Cast converts magic to 16-bit signed value */
61484 			magic = (duk_int16_t) duk_bd_decode_varuint(bd);
61485 			((duk_hnatfunc *) h)->magic = magic;
61486 		} else if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
61487 			duk_push_array(thr);
61488 		} else if (class_num == DUK_HOBJECT_CLASS_OBJENV) {
61489 			duk_hobjenv *env;
61490 			duk_hobject *global;
61491 
61492 			DUK_ASSERT(i == DUK_BIDX_GLOBAL_ENV);
61493 			DUK_ASSERT(DUK_BIDX_GLOBAL_ENV > DUK_BIDX_GLOBAL);
61494 
61495 			env = duk_hobjenv_alloc(thr,
61496 	                                        DUK_HOBJECT_FLAG_EXTENSIBLE |
61497 	                                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
61498 			DUK_ASSERT(env->target == NULL);
61499 			duk_push_hobject(thr, (duk_hobject *) env);
61500 
61501 			global = duk_known_hobject(thr, DUK_BIDX_GLOBAL);
61502 			DUK_ASSERT(global != NULL);
61503 			env->target = global;
61504 			DUK_HOBJECT_INCREF(thr, global);
61505 			DUK_ASSERT(env->has_this == 0);
61506 
61507 			DUK_HOBJENV_ASSERT_VALID(env);
61508 		} else {
61509 			DUK_ASSERT(class_num != DUK_HOBJECT_CLASS_DECENV);
61510 
61511 			(void) duk_push_object_helper(thr,
61512 			                              DUK_HOBJECT_FLAG_FASTREFS |
61513 			                              DUK_HOBJECT_FLAG_EXTENSIBLE,
61514 			                              -1);  /* no prototype or class yet */
61515 
61516 		}
61517 
61518 		h = duk_known_hobject(thr, -1);
61519 		DUK_HOBJECT_SET_CLASS_NUMBER(h, class_num);
61520 
61521 		if (i < DUK_NUM_BUILTINS) {
61522 			thr->builtins[i] = h;
61523 			DUK_HOBJECT_INCREF(thr, &h->hdr);
61524 		}
61525 
61526 		if (len >= 0) {
61527 			/* In ES2015+ built-in function object .length property
61528 			 * has property attributes C (configurable only):
61529 			 * http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-standard-built-in-objects
61530 			 *
61531 			 * Array.prototype remains an Array instance in ES2015+
61532 			 * and its length has attributes W (writable only).
61533 			 * Because .length is now virtual for duk_harray, it is
61534 			 * not encoded explicitly in init data.
61535 			 */
61536 
61537 			DUK_ASSERT(class_num != DUK_HOBJECT_CLASS_ARRAY);  /* .length is virtual */
61538 			duk_push_int(thr, len);
61539 			duk_xdef_prop_stridx_short(thr,
61540 			                           -2,
61541 			                           DUK_STRIDX_LENGTH,
61542 			                           DUK_PROPDESC_FLAGS_C);
61543 		}
61544 
61545 		/* enable exotic behaviors last */
61546 
61547 		if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
61548 			DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h));  /* set by duk_push_array() */
61549 		}
61550 		if (class_num == DUK_HOBJECT_CLASS_STRING) {
61551 			DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h);
61552 		}
61553 
61554 		/* some assertions */
61555 
61556 		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h));
61557 		/* DUK_HOBJECT_FLAG_CONSTRUCTABLE varies */
61558 		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(h));
61559 		DUK_ASSERT(!DUK_HOBJECT_HAS_COMPFUNC(h));
61560 		/* DUK_HOBJECT_FLAG_NATFUNC varies */
61561 		DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(h));
61562 		DUK_ASSERT(!DUK_HOBJECT_IS_PROXY(h));
61563 		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(h) || class_num == DUK_HOBJECT_CLASS_ARRAY);
61564 		/* DUK_HOBJECT_FLAG_STRICT varies */
61565 		DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(h) ||  /* all native functions have NEWENV */
61566 		           DUK_HOBJECT_HAS_NEWENV(h));
61567 		DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(h));
61568 		DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(h));
61569 		/* DUK_HOBJECT_FLAG_EXOTIC_ARRAY varies */
61570 		/* DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ varies */
61571 		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h));
61572 
61573 		DUK_DDD(DUK_DDDPRINT("created built-in %ld, class=%ld, length=%ld", (long) i, (long) class_num, (long) len));
61574 	}
61575 
61576 	/*
61577 	 *  Then decode the builtins init data (see genbuiltins.py) to
61578 	 *  init objects.  Internal prototypes are set at this stage,
61579 	 *  with thr->builtins[] populated.
61580 	 */
61581 
61582 	DUK_DD(DUK_DDPRINT("initialize built-in object properties"));
61583 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
61584 		duk_small_uint_t t;
61585 		duk_small_uint_t num;
61586 
61587 		DUK_DDD(DUK_DDDPRINT("initializing built-in object at index %ld", (long) i));
61588 		h = duk_known_hobject(thr, (duk_idx_t) i);
61589 
61590 		t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61591 		if (t > 0) {
61592 			t--;
61593 			DUK_DDD(DUK_DDDPRINT("set internal prototype: built-in %ld", (long) t));
61594 			DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, duk_known_hobject(thr, (duk_idx_t) t));
61595 		} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
61596 			/* Standard native built-ins cannot inherit from
61597 			 * %NativeFunctionPrototype%, they are required to
61598 			 * inherit from Function.prototype directly.
61599 			 */
61600 			DUK_ASSERT(thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE] != NULL);
61601 			DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
61602 		}
61603 
61604 		t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61605 		if (t > 0) {
61606 			/* 'prototype' property for all built-in objects (which have it) has attributes:
61607 			 *  [[Writable]] = false,
61608 			 *  [[Enumerable]] = false,
61609 			 *  [[Configurable]] = false
61610 			 */
61611 			t--;
61612 			DUK_DDD(DUK_DDDPRINT("set external prototype: built-in %ld", (long) t));
61613 			duk_dup(thr, (duk_idx_t) t);
61614 			duk_xdef_prop_stridx(thr, (duk_idx_t) i, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_NONE);
61615 		}
61616 
61617 		t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61618 		if (t > 0) {
61619 			/* 'constructor' property for all built-in objects (which have it) has attributes:
61620 			 *  [[Writable]] = true,
61621 			 *  [[Enumerable]] = false,
61622 			 *  [[Configurable]] = true
61623 			 */
61624 			t--;
61625 			DUK_DDD(DUK_DDDPRINT("set external constructor: built-in %ld", (long) t));
61626 			duk_dup(thr, (duk_idx_t) t);
61627 			duk_xdef_prop_stridx(thr, (duk_idx_t) i, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);
61628 		}
61629 
61630 		/* normal valued properties */
61631 		num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61632 		DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld normal valued properties", (long) i, (long) num));
61633 		for (j = 0; j < num; j++) {
61634 			duk_small_uint_t defprop_flags;
61635 
61636 			duk__push_stridx_or_string(thr, bd);
61637 
61638 			/*
61639 			 *  Property attribute defaults are defined in E5 Section 15 (first
61640 			 *  few pages); there is a default for all properties and a special
61641 			 *  default for 'length' properties.  Variation from the defaults is
61642 			 *  signaled using a single flag bit in the bitstream.
61643 			 */
61644 
61645 			defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd,
61646 			                                                         DUK__PROP_FLAGS_BITS,
61647 			                                                         (duk_uint32_t) DUK_PROPDESC_FLAGS_WC);
61648 			defprop_flags |= DUK_DEFPROP_FORCE |
61649 			                 DUK_DEFPROP_HAVE_VALUE |
61650 			                 DUK_DEFPROP_HAVE_WRITABLE |
61651 			                 DUK_DEFPROP_HAVE_ENUMERABLE |
61652 			                 DUK_DEFPROP_HAVE_CONFIGURABLE;  /* Defaults for data properties. */
61653 
61654 			/* The writable, enumerable, configurable flags in prop_flags
61655 			 * match both duk_def_prop() and internal property flags.
61656 			 */
61657 			DUK_ASSERT(DUK_PROPDESC_FLAG_WRITABLE == DUK_DEFPROP_WRITABLE);
61658 			DUK_ASSERT(DUK_PROPDESC_FLAG_ENUMERABLE == DUK_DEFPROP_ENUMERABLE);
61659 			DUK_ASSERT(DUK_PROPDESC_FLAG_CONFIGURABLE == DUK_DEFPROP_CONFIGURABLE);
61660 
61661 			t = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_TYPE_BITS);
61662 
61663 			DUK_DDD(DUK_DDDPRINT("built-in %ld, normal-valued property %ld, key %!T, flags 0x%02lx, type %ld",
61664 			                     (long) i, (long) j, duk_get_tval(thr, -1), (unsigned long) defprop_flags, (long) t));
61665 
61666 			switch (t) {
61667 			case DUK__PROP_TYPE_DOUBLE: {
61668 				duk__push_double(thr, bd);
61669 				break;
61670 			}
61671 			case DUK__PROP_TYPE_STRING: {
61672 				duk__push_string(thr, bd);
61673 				break;
61674 			}
61675 			case DUK__PROP_TYPE_STRIDX: {
61676 				duk__push_stridx(thr, bd);
61677 				break;
61678 			}
61679 			case DUK__PROP_TYPE_BUILTIN: {
61680 				duk_small_uint_t bidx;
61681 
61682 				bidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61683 				duk_dup(thr, (duk_idx_t) bidx);
61684 				break;
61685 			}
61686 			case DUK__PROP_TYPE_UNDEFINED: {
61687 				duk_push_undefined(thr);
61688 				break;
61689 			}
61690 			case DUK__PROP_TYPE_BOOLEAN_TRUE: {
61691 				duk_push_true(thr);
61692 				break;
61693 			}
61694 			case DUK__PROP_TYPE_BOOLEAN_FALSE: {
61695 				duk_push_false(thr);
61696 				break;
61697 			}
61698 			case DUK__PROP_TYPE_ACCESSOR: {
61699 				duk_small_uint_t natidx_getter = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61700 				duk_small_uint_t natidx_setter = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61701 				duk_small_uint_t accessor_magic = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61702 				duk_c_function c_func_getter;
61703 				duk_c_function c_func_setter;
61704 
61705 				DUK_DDD(DUK_DDDPRINT("built-in accessor property: objidx=%ld, key=%!T, getteridx=%ld, setteridx=%ld, flags=0x%04lx",
61706 				                     (long) i, duk_get_tval(thr, -1), (long) natidx_getter, (long) natidx_setter, (unsigned long) defprop_flags));
61707 
61708 				c_func_getter = duk_bi_native_functions[natidx_getter];
61709 				if (c_func_getter != NULL) {
61710 					duk_push_c_function_builtin_noconstruct(thr, c_func_getter, 0);  /* always 0 args */
61711 					duk_set_magic(thr, -1, (duk_int_t) accessor_magic);
61712 					defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
61713 				}
61714 				c_func_setter = duk_bi_native_functions[natidx_setter];
61715 				if (c_func_setter != NULL) {
61716 					duk_push_c_function_builtin_noconstruct(thr, c_func_setter, 1);  /* always 1 arg */
61717 					duk_set_magic(thr, -1, (duk_int_t) accessor_magic);
61718 					defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
61719 				}
61720 
61721 				/* Writable flag doesn't make sense for an accessor. */
61722 				DUK_ASSERT((defprop_flags & DUK_PROPDESC_FLAG_WRITABLE) == 0);  /* genbuiltins.py ensures */
61723 
61724 				defprop_flags &= ~(DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
61725 				defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE;
61726 				break;
61727 			}
61728 			default: {
61729 				/* exhaustive */
61730 				DUK_UNREACHABLE();
61731 			}
61732 			}
61733 
61734 			duk_def_prop(thr, (duk_idx_t) i, defprop_flags);
61735 			DUK_ASSERT_TOP(thr, DUK_NUM_ALL_BUILTINS);
61736 		}
61737 
61738 		/* native function properties */
61739 		num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61740 		DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld function valued properties", (long) i, (long) num));
61741 		for (j = 0; j < num; j++) {
61742 			duk_hstring *h_key;
61743 			duk_small_uint_t natidx;
61744 			duk_int_t c_nargs;  /* must hold DUK_VARARGS */
61745 			duk_small_uint_t c_length;
61746 			duk_int16_t magic;
61747 			duk_c_function c_func;
61748 			duk_hnatfunc *h_func;
61749 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
61750 			duk_small_int_t lightfunc_eligible;
61751 #endif
61752 			duk_small_uint_t defprop_flags;
61753 
61754 			duk__push_stridx_or_string(thr, bd);
61755 			h_key = duk_known_hstring(thr, -1);
61756 			DUK_UNREF(h_key);
61757 			natidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61758 
61759 			c_length = (duk_small_uint_t) duk_bd_decode(bd, DUK__LENGTH_PROP_BITS);
61760 			c_nargs = (duk_int_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, (duk_uint32_t) c_length /*def_value*/);
61761 			if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
61762 				c_nargs = DUK_VARARGS;
61763 			}
61764 
61765 			c_func = duk_bi_native_functions[natidx];
61766 
61767 			DUK_DDD(DUK_DDDPRINT("built-in %ld, function-valued property %ld, key %!O, natidx %ld, length %ld, nargs %ld",
61768 			                     (long) i, (long) j, (duk_heaphdr *) h_key, (long) natidx, (long) c_length,
61769 			                     (c_nargs == DUK_VARARGS ? (long) -1 : (long) c_nargs)));
61770 
61771 			/* Cast converts magic to 16-bit signed value */
61772 			magic = (duk_int16_t) duk_bd_decode_varuint(bd);
61773 
61774 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
61775 			lightfunc_eligible =
61776 				((c_nargs >= DUK_LFUNC_NARGS_MIN && c_nargs <= DUK_LFUNC_NARGS_MAX) || (c_nargs == DUK_VARARGS)) &&
61777 				(c_length <= DUK_LFUNC_LENGTH_MAX) &&
61778 				(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX);
61779 
61780 			/* These functions have trouble working as lightfuncs.
61781 			 * Some of them have specific asserts and some may have
61782 		         * additional properties (e.g. 'require.id' may be written).
61783 			 */
61784 			if (c_func == duk_bi_global_object_eval) {
61785 				lightfunc_eligible = 0;
61786 			}
61787 #if defined(DUK_USE_COROUTINE_SUPPORT)
61788 			if (c_func == duk_bi_thread_yield ||
61789 			    c_func == duk_bi_thread_resume) {
61790 				lightfunc_eligible = 0;
61791 			}
61792 #endif
61793 			if (c_func == duk_bi_function_prototype_call ||
61794 			    c_func == duk_bi_function_prototype_apply ||
61795 			    c_func == duk_bi_reflect_apply ||
61796 			    c_func == duk_bi_reflect_construct) {
61797 				lightfunc_eligible = 0;
61798 			}
61799 
61800 			if (lightfunc_eligible) {
61801 				duk_tval tv_lfunc;
61802 				duk_small_uint_t lf_nargs = (duk_small_uint_t) (c_nargs == DUK_VARARGS ? DUK_LFUNC_NARGS_VARARGS : c_nargs);
61803 				duk_small_uint_t lf_flags = DUK_LFUNC_FLAGS_PACK(magic, c_length, lf_nargs);
61804 				DUK_TVAL_SET_LIGHTFUNC(&tv_lfunc, c_func, lf_flags);
61805 				duk_push_tval(thr, &tv_lfunc);
61806 				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)));
61807 				goto lightfunc_skip;
61808 			}
61809 
61810 			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));
61811 #endif  /* DUK_USE_LIGHTFUNC_BUILTINS */
61812 
61813 			/* [ (builtin objects) name ] */
61814 
61815 			duk_push_c_function_builtin_noconstruct(thr, c_func, c_nargs);
61816 			h_func = duk_known_hnatfunc(thr, -1);
61817 			DUK_UNREF(h_func);
61818 
61819 			/* XXX: add into init data? */
61820 
61821 			/* Special call handling, not described in init data. */
61822 			if (c_func == duk_bi_global_object_eval ||
61823 			    c_func == duk_bi_function_prototype_call ||
61824 			    c_func == duk_bi_function_prototype_apply ||
61825 			    c_func == duk_bi_reflect_apply ||
61826 			    c_func == duk_bi_reflect_construct) {
61827 				DUK_HOBJECT_SET_SPECIAL_CALL((duk_hobject *) h_func);
61828 			}
61829 
61830 			/* Currently all built-in native functions are strict.
61831 			 * This doesn't matter for many functions, but e.g.
61832 			 * String.prototype.charAt (and other string functions)
61833 			 * rely on being strict so that their 'this' binding is
61834 			 * not automatically coerced.
61835 			 */
61836 			DUK_HOBJECT_SET_STRICT((duk_hobject *) h_func);
61837 
61838 			/* No built-in functions are constructable except the top
61839 			 * level ones (Number, etc).
61840 			 */
61841 			DUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_func));
61842 
61843 			/* XXX: any way to avoid decoding magic bit; there are quite
61844 			 * many function properties and relatively few with magic values.
61845 			 */
61846 			h_func->magic = magic;
61847 
61848 			/* [ (builtin objects) name func ] */
61849 
61850 			duk_push_uint(thr, c_length);
61851 			duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
61852 
61853 			duk_dup_m2(thr);
61854 			duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
61855 
61856 			/* XXX: other properties of function instances; 'arguments', 'caller'. */
61857 
61858 			DUK_DD(DUK_DDPRINT("built-in object %ld, function property %ld -> %!T",
61859 			                   (long) i, (long) j, (duk_tval *) duk_get_tval(thr, -1)));
61860 
61861 			/* [ (builtin objects) name func ] */
61862 
61863 			/*
61864 			 *  The default property attributes are correct for all
61865 			 *  function valued properties of built-in objects now.
61866 			 */
61867 
61868 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
61869 		 lightfunc_skip:
61870 #endif
61871 
61872 			defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd,
61873 			                                                         DUK__PROP_FLAGS_BITS,
61874 			                                                         (duk_uint32_t) DUK_PROPDESC_FLAGS_WC);
61875 			defprop_flags |= DUK_DEFPROP_FORCE |
61876 			                 DUK_DEFPROP_HAVE_VALUE |
61877 			                 DUK_DEFPROP_HAVE_WRITABLE |
61878 			                 DUK_DEFPROP_HAVE_ENUMERABLE |
61879 			                 DUK_DEFPROP_HAVE_CONFIGURABLE;
61880 			DUK_ASSERT(DUK_PROPDESC_FLAG_WRITABLE == DUK_DEFPROP_WRITABLE);
61881 			DUK_ASSERT(DUK_PROPDESC_FLAG_ENUMERABLE == DUK_DEFPROP_ENUMERABLE);
61882 			DUK_ASSERT(DUK_PROPDESC_FLAG_CONFIGURABLE == DUK_DEFPROP_CONFIGURABLE);
61883 
61884 			duk_def_prop(thr, (duk_idx_t) i, defprop_flags);
61885 
61886 			/* [ (builtin objects) ] */
61887 		}
61888 	}
61889 
61890 	/*
61891 	 *  Special post-tweaks, for cases not covered by the init data format.
61892 	 *
61893 	 *  - Set Date.prototype.toGMTString to Date.prototype.toUTCString.
61894 	 *    toGMTString is required to have the same Function object as
61895 	 *    toUTCString in E5 Section B.2.6.  Note that while Smjs respects
61896 	 *    this, V8 does not (the Function objects are distinct).
61897 	 *
61898 	 *  - Make DoubleError non-extensible.
61899 	 *
61900 	 *  - Add info about most important effective compile options to Duktape.
61901 	 *
61902 	 *  - Possibly remove some properties (values or methods) which are not
61903 	 *    desirable with current feature options but are not currently
61904 	 *    conditional in init data.
61905 	 */
61906 
61907 #if defined(DUK_USE_DATE_BUILTIN)
61908 	duk_get_prop_stridx_short(thr, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_UTC_STRING);
61909 	duk_xdef_prop_stridx_short(thr, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_GMT_STRING, DUK_PROPDESC_FLAGS_WC);
61910 #endif
61911 
61912 	h = duk_known_hobject(thr, DUK_BIDX_DOUBLE_ERROR);
61913 	DUK_HOBJECT_CLEAR_EXTENSIBLE(h);
61914 
61915 #if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY)
61916 	DUK_DD(DUK_DDPRINT("delete Object.prototype.__proto__ built-in which is not enabled in features"));
61917 	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_PROTOTYPE], DUK_HTHREAD_STRING___PROTO__(thr), DUK_DELPROP_FLAG_THROW);
61918 #endif
61919 
61920 #if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF)
61921 	DUK_DD(DUK_DDPRINT("delete Object.setPrototypeOf built-in which is not enabled in features"));
61922 	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_CONSTRUCTOR], DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr), DUK_DELPROP_FLAG_THROW);
61923 #endif
61924 
61925 	/* XXX: relocate */
61926 	duk_push_string(thr,
61927 			/* Endianness indicator */
61928 #if defined(DUK_USE_INTEGER_LE)
61929 	                "l"
61930 #elif defined(DUK_USE_INTEGER_BE)
61931 	                "b"
61932 #elif defined(DUK_USE_INTEGER_ME)  /* integer mixed endian not really used now */
61933 	                "m"
61934 #else
61935 	                "?"
61936 #endif
61937 #if defined(DUK_USE_DOUBLE_LE)
61938 	                "l"
61939 #elif defined(DUK_USE_DOUBLE_BE)
61940 	                "b"
61941 #elif defined(DUK_USE_DOUBLE_ME)
61942 	                "m"
61943 #else
61944 	                "?"
61945 #endif
61946 	                " "
61947 			/* Packed or unpacked tval */
61948 #if defined(DUK_USE_PACKED_TVAL)
61949 	                "p"
61950 #else
61951 	                "u"
61952 #endif
61953 #if defined(DUK_USE_FASTINT)
61954 			"f"
61955 #endif
61956 			" "
61957 			/* Low memory/performance options */
61958 #if defined(DUK_USE_STRTAB_PTRCOMP)
61959 			"s"
61960 #endif
61961 #if !defined(DUK_USE_HEAPPTR16) && !defined(DUK_DATAPTR16) && !defined(DUK_FUNCPTR16)
61962 			"n"
61963 #endif
61964 #if defined(DUK_USE_HEAPPTR16)
61965 			"h"
61966 #endif
61967 #if defined(DUK_USE_DATAPTR16)
61968 			"d"
61969 #endif
61970 #if defined(DUK_USE_FUNCPTR16)
61971 			"f"
61972 #endif
61973 #if defined(DUK_USE_REFCOUNT16)
61974 			"R"
61975 #endif
61976 #if defined(DUK_USE_STRHASH16)
61977 			"H"
61978 #endif
61979 #if defined(DUK_USE_STRLEN16)
61980 			"S"
61981 #endif
61982 #if defined(DUK_USE_BUFLEN16)
61983 			"B"
61984 #endif
61985 #if defined(DUK_USE_OBJSIZES16)
61986 			"O"
61987 #endif
61988 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
61989 			"L"
61990 #endif
61991 #if defined(DUK_USE_ROM_STRINGS) || defined(DUK_USE_ROM_OBJECTS)
61992 			/* XXX: This won't be shown in practice now
61993 			 * because this code is not run when builtins
61994 			 * are in ROM.
61995 			 */
61996 			"Z"
61997 #endif
61998 #if defined(DUK_USE_LITCACHE_SIZE)
61999 			"l"
62000 #endif
62001 	                " "
62002 			/* Object property allocation layout */
62003 #if defined(DUK_USE_HOBJECT_LAYOUT_1)
62004 			"p1"
62005 #elif defined(DUK_USE_HOBJECT_LAYOUT_2)
62006 			"p2"
62007 #elif defined(DUK_USE_HOBJECT_LAYOUT_3)
62008 			"p3"
62009 #else
62010 			"p?"
62011 #endif
62012 			" "
62013 			/* Alignment guarantee */
62014 #if (DUK_USE_ALIGN_BY == 4)
62015 			"a4"
62016 #elif (DUK_USE_ALIGN_BY == 8)
62017 			"a8"
62018 #elif (DUK_USE_ALIGN_BY == 1)
62019 			"a1"
62020 #else
62021 #error invalid DUK_USE_ALIGN_BY
62022 #endif
62023 			" "
62024 			/* Architecture, OS, and compiler strings */
62025 	                DUK_USE_ARCH_STRING
62026 			" "
62027 	                DUK_USE_OS_STRING
62028 			" "
62029 	                DUK_USE_COMPILER_STRING);
62030 	duk_xdef_prop_stridx_short(thr, DUK_BIDX_DUKTAPE, DUK_STRIDX_ENV, DUK_PROPDESC_FLAGS_WC);
62031 
62032 	/*
62033 	 *  Since built-ins are not often extended, compact them.
62034 	 */
62035 
62036 	DUK_DD(DUK_DDPRINT("compact built-ins"));
62037 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
62038 		duk_hobject_compact_props(thr, duk_known_hobject(thr, (duk_idx_t) i));
62039 	}
62040 
62041 	DUK_D(DUK_DPRINT("INITBUILTINS END"));
62042 
62043 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
62044 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
62045 		DUK_DD(DUK_DDPRINT("built-in object %ld after initialization and compacting: %!@iO",
62046 		                   (long) i, (duk_heaphdr *) duk_require_hobject(thr, (duk_idx_t) i)));
62047 	}
62048 #endif
62049 
62050 	/*
62051 	 *  Pop built-ins from stack: they are now INCREF'd and
62052 	 *  reachable from the builtins[] array or indirectly
62053 	 *  through builtins[].
62054 	 */
62055 
62056 	duk_set_top(thr, 0);
62057 	DUK_ASSERT_TOP(thr, 0);
62058 }
62059 #endif  /* DUK_USE_ROM_OBJECTS */
62060 
62061 DUK_INTERNAL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to) {
62062 	duk_small_uint_t i;
62063 
62064 	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
62065 		thr_to->builtins[i] = thr_from->builtins[i];
62066 		DUK_HOBJECT_INCREF_ALLOWNULL(thr_to, thr_to->builtins[i]);  /* side effect free */
62067 	}
62068 }
62069 
62070 /* automatic undefs */
62071 #undef DUK__LENGTH_PROP_BITS
62072 #undef DUK__NARGS_BITS
62073 #undef DUK__NARGS_VARARGS_MARKER
62074 #undef DUK__PROP_FLAGS_BITS
62075 #undef DUK__PROP_TYPE_ACCESSOR
62076 #undef DUK__PROP_TYPE_BITS
62077 #undef DUK__PROP_TYPE_BOOLEAN_FALSE
62078 #undef DUK__PROP_TYPE_BOOLEAN_TRUE
62079 #undef DUK__PROP_TYPE_BUILTIN
62080 #undef DUK__PROP_TYPE_DOUBLE
62081 #undef DUK__PROP_TYPE_STRIDX
62082 #undef DUK__PROP_TYPE_STRING
62083 #undef DUK__PROP_TYPE_UNDEFINED
62084 /*
62085  *  Thread support.
62086  */
62087 
62088 /* #include duk_internal.h -> already included */
62089 
62090 DUK_INTERNAL void duk_hthread_terminate(duk_hthread *thr) {
62091 	DUK_ASSERT(thr != NULL);
62092 
62093 	while (thr->callstack_curr != NULL) {
62094 		duk_hthread_activation_unwind_norz(thr);
62095 	}
62096 
62097 	thr->valstack_bottom = thr->valstack;
62098 	duk_set_top(thr, 0);  /* unwinds valstack, updating refcounts */
62099 
62100 	thr->state = DUK_HTHREAD_STATE_TERMINATED;
62101 
62102 	/* Here we could remove references to built-ins, but it may not be
62103 	 * worth the effort because built-ins are quite likely to be shared
62104 	 * with another (unterminated) thread, and terminated threads are also
62105 	 * usually garbage collected quite quickly.
62106 	 *
62107 	 * We could also shrink the value stack here, but that also may not
62108 	 * be worth the effort for the same reason.
62109 	 */
62110 
62111 	DUK_REFZERO_CHECK_SLOW(thr);
62112 }
62113 
62114 #if defined(DUK_USE_DEBUGGER_SUPPORT)
62115 DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act) {
62116 	duk_instr_t *bcode;
62117 
62118 	DUK_ASSERT(thr != NULL);
62119 	DUK_ASSERT(act != NULL);
62120 	DUK_UNREF(thr);
62121 
62122 	/* XXX: store 'bcode' pointer to activation for faster lookup? */
62123 	if (act->func && DUK_HOBJECT_IS_COMPFUNC(act->func)) {
62124 		bcode = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) (act->func));
62125 		return (duk_uint_fast32_t) (act->curr_pc - bcode);
62126 	}
62127 	return 0;
62128 }
62129 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
62130 
62131 DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act) {
62132 	duk_instr_t *bcode;
62133 	duk_uint_fast32_t ret;
62134 
62135 	DUK_ASSERT(thr != NULL);
62136 	DUK_ASSERT(act != NULL);
62137 	DUK_UNREF(thr);
62138 
62139 	if (act->func && DUK_HOBJECT_IS_COMPFUNC(act->func)) {
62140 		bcode = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) (act->func));
62141 		ret = (duk_uint_fast32_t) (act->curr_pc - bcode);
62142 		if (ret > 0) {
62143 			ret--;
62144 		}
62145 		return ret;
62146 	}
62147 	return 0;
62148 }
62149 
62150 /* Write bytecode executor's curr_pc back to topmost activation (if any). */
62151 DUK_INTERNAL void duk_hthread_sync_currpc(duk_hthread *thr) {
62152 	duk_activation *act;
62153 
62154 	DUK_ASSERT(thr != NULL);
62155 
62156 	if (thr->ptr_curr_pc != NULL) {
62157 		/* ptr_curr_pc != NULL only when bytecode executor is active. */
62158 		DUK_ASSERT(thr->callstack_top > 0);
62159 		DUK_ASSERT(thr->callstack_curr != NULL);
62160 		act = thr->callstack_curr;
62161 		DUK_ASSERT(act != NULL);
62162 		act->curr_pc = *thr->ptr_curr_pc;
62163 	}
62164 }
62165 
62166 DUK_INTERNAL void duk_hthread_sync_and_null_currpc(duk_hthread *thr) {
62167 	duk_activation *act;
62168 
62169 	DUK_ASSERT(thr != NULL);
62170 
62171 	if (thr->ptr_curr_pc != NULL) {
62172 		/* ptr_curr_pc != NULL only when bytecode executor is active. */
62173 		DUK_ASSERT(thr->callstack_top > 0);
62174 		DUK_ASSERT(thr->callstack_curr != NULL);
62175 		act = thr->callstack_curr;
62176 		DUK_ASSERT(act != NULL);
62177 		act->curr_pc = *thr->ptr_curr_pc;
62178 		thr->ptr_curr_pc = NULL;
62179 	}
62180 }
62181 /*
62182  *  Thread stack (mainly call stack) primitives: allocation of activations,
62183  *  unwinding catchers and activations, etc.
62184  *
62185  *  Value stack handling is a part of the API implementation.
62186  */
62187 
62188 /* #include duk_internal.h -> already included */
62189 
62190 /* Unwind the topmost catcher of the current activation (caller must check that
62191  * both exist) without side effects.
62192  */
62193 DUK_INTERNAL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activation *act) {
62194 	duk_catcher *cat;
62195 
62196 	DUK_ASSERT(thr != NULL);
62197 	DUK_ASSERT(act != NULL);
62198 	DUK_ASSERT(act->cat != NULL);  /* caller must check */
62199 	cat = act->cat;
62200 	DUK_ASSERT(cat != NULL);
62201 
62202 	DUK_DDD(DUK_DDDPRINT("unwinding catch stack entry %p (lexenv check is done)", (void *) cat));
62203 
62204 	if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
62205 		duk_hobject *env;
62206 
62207 		env = act->lex_env;             /* current lex_env of the activation (created for catcher) */
62208 		DUK_ASSERT(env != NULL);        /* must be, since env was created when catcher was created */
62209 		act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);  /* prototype is lex_env before catcher created */
62210 		DUK_HOBJECT_INCREF(thr, act->lex_env);
62211 		DUK_HOBJECT_DECREF_NORZ(thr, env);
62212 
62213 		/* There is no need to decref anything else than 'env': if 'env'
62214 		 * becomes unreachable, refzero will handle decref'ing its prototype.
62215 		 */
62216 	}
62217 
62218 	act->cat = cat->parent;
62219 	duk_hthread_catcher_free(thr, cat);
62220 }
62221 
62222 /* Same as above, but caller is certain no catcher-related lexenv may exist. */
62223 DUK_INTERNAL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk_activation *act) {
62224 	duk_catcher *cat;
62225 
62226 	DUK_ASSERT(thr != NULL);
62227 	DUK_ASSERT(act != NULL);
62228 	DUK_ASSERT(act->cat != NULL);  /* caller must check */
62229 	cat = act->cat;
62230 	DUK_ASSERT(cat != NULL);
62231 
62232 	DUK_DDD(DUK_DDDPRINT("unwinding catch stack entry %p (lexenv check is not done)", (void *) cat));
62233 
62234 	DUK_ASSERT(!DUK_CAT_HAS_LEXENV_ACTIVE(cat));
62235 
62236 	act->cat = cat->parent;
62237 	duk_hthread_catcher_free(thr, cat);
62238 }
62239 
62240 DUK_LOCAL
62241 #if defined(DUK_USE_CACHE_CATCHER)
62242 DUK_NOINLINE
62243 #endif
62244 duk_catcher *duk__hthread_catcher_alloc_slow(duk_hthread *thr) {
62245 	duk_catcher *cat;
62246 
62247 	cat = (duk_catcher *) DUK_ALLOC_CHECKED(thr, sizeof(duk_catcher));
62248 	DUK_ASSERT(cat != NULL);
62249 	return cat;
62250 }
62251 
62252 #if defined(DUK_USE_CACHE_CATCHER)
62253 DUK_INTERNAL DUK_INLINE duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr) {
62254 	duk_catcher *cat;
62255 
62256 	DUK_ASSERT(thr != NULL);
62257 
62258 	cat = thr->heap->catcher_free;
62259 	if (DUK_LIKELY(cat != NULL)) {
62260 		thr->heap->catcher_free = cat->parent;
62261 		return cat;
62262 	}
62263 
62264 	return duk__hthread_catcher_alloc_slow(thr);
62265 }
62266 #else  /* DUK_USE_CACHE_CATCHER */
62267 DUK_INTERNAL duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr) {
62268 	return duk__hthread_catcher_alloc_slow(thr);
62269 }
62270 #endif  /* DUK_USE_CACHE_CATCHER */
62271 
62272 DUK_INTERNAL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat) {
62273 	DUK_ASSERT(thr != NULL);
62274 	DUK_ASSERT(cat != NULL);
62275 
62276 #if defined(DUK_USE_CACHE_CATCHER)
62277 	/* Unconditional caching for now; freed in mark-and-sweep. */
62278 	cat->parent = thr->heap->catcher_free;
62279 	thr->heap->catcher_free = cat;
62280 #else
62281 	DUK_FREE_CHECKED(thr, (void *) cat);
62282 #endif
62283 }
62284 
62285 DUK_LOCAL
62286 #if defined(DUK_USE_CACHE_ACTIVATION)
62287 DUK_NOINLINE
62288 #endif
62289 duk_activation *duk__hthread_activation_alloc_slow(duk_hthread *thr) {
62290 	duk_activation *act;
62291 
62292 	act = (duk_activation *) DUK_ALLOC_CHECKED(thr, sizeof(duk_activation));
62293 	DUK_ASSERT(act != NULL);
62294 	return act;
62295 }
62296 
62297 #if defined(DUK_USE_CACHE_ACTIVATION)
62298 DUK_INTERNAL DUK_INLINE duk_activation *duk_hthread_activation_alloc(duk_hthread *thr) {
62299 	duk_activation *act;
62300 
62301 	DUK_ASSERT(thr != NULL);
62302 
62303 	act = thr->heap->activation_free;
62304 	if (DUK_LIKELY(act != NULL)) {
62305 		thr->heap->activation_free = act->parent;
62306 		return act;
62307 	}
62308 
62309 	return duk__hthread_activation_alloc_slow(thr);
62310 }
62311 #else  /* DUK_USE_CACHE_ACTIVATION */
62312 DUK_INTERNAL duk_activation *duk_hthread_activation_alloc(duk_hthread *thr) {
62313 	return duk__hthread_activation_alloc_slow(thr);
62314 }
62315 #endif  /* DUK_USE_CACHE_ACTIVATION */
62316 
62317 
62318 DUK_INTERNAL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act) {
62319 	DUK_ASSERT(thr != NULL);
62320 	DUK_ASSERT(act != NULL);
62321 
62322 #if defined(DUK_USE_CACHE_ACTIVATION)
62323 	/* Unconditional caching for now; freed in mark-and-sweep. */
62324 	act->parent = thr->heap->activation_free;
62325 	thr->heap->activation_free = act;
62326 #else
62327 	DUK_FREE_CHECKED(thr, (void *) act);
62328 #endif
62329 }
62330 
62331 /* Internal helper: process the unwind for the topmost activation of a thread,
62332  * but leave the duk_activation in place for possible tailcall reuse.
62333  */
62334 DUK_LOCAL void duk__activation_unwind_nofree_norz(duk_hthread *thr) {
62335 #if defined(DUK_USE_DEBUGGER_SUPPORT)
62336 	duk_heap *heap;
62337 #endif
62338 	duk_activation *act;
62339 	duk_hobject *func;
62340 	duk_hobject *tmp;
62341 
62342 	DUK_ASSERT(thr != NULL);
62343 	DUK_ASSERT(thr->callstack_curr != NULL);  /* caller must check */
62344 	DUK_ASSERT(thr->callstack_top > 0);
62345 	act = thr->callstack_curr;
62346 	DUK_ASSERT(act != NULL);
62347 	/* With lightfuncs, act 'func' may be NULL. */
62348 
62349 	/* With duk_activation records allocated separately, 'act' is a stable
62350 	 * pointer and not affected by side effects.
62351 	 */
62352 
62353 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
62354 	/*
62355 	 *  Restore 'caller' property for non-strict callee functions.
62356 	 */
62357 
62358 	func = DUK_ACT_GET_FUNC(act);
62359 	if (func != NULL && !DUK_HOBJECT_HAS_STRICT(func)) {
62360 		duk_tval *tv_caller;
62361 		duk_tval tv_tmp;
62362 		duk_hobject *h_tmp;
62363 
62364 		tv_caller = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, func, DUK_STRIDX_CALLER);
62365 
62366 		/* The act->prev_caller should only be set if the entry for 'caller'
62367 		 * exists (as it is only set in that case, and the property is not
62368 		 * configurable), but handle all the cases anyway.
62369 		 */
62370 
62371 		if (tv_caller) {
62372 			DUK_TVAL_SET_TVAL(&tv_tmp, tv_caller);
62373 			if (act->prev_caller) {
62374 				/* Just transfer the refcount from act->prev_caller to tv_caller,
62375 				 * so no need for a refcount update.  This is the expected case.
62376 				 */
62377 				DUK_TVAL_SET_OBJECT(tv_caller, act->prev_caller);
62378 				act->prev_caller = NULL;
62379 			} else {
62380 				DUK_TVAL_SET_NULL(tv_caller);   /* no incref needed */
62381 				DUK_ASSERT(act->prev_caller == NULL);
62382 			}
62383 			DUK_TVAL_DECREF_NORZ(thr, &tv_tmp);
62384 		} else {
62385 			h_tmp = act->prev_caller;
62386 			if (h_tmp) {
62387 				act->prev_caller = NULL;
62388 				DUK_HOBJECT_DECREF_NORZ(thr, h_tmp);
62389 			}
62390 		}
62391 		DUK_ASSERT(act->prev_caller == NULL);
62392 	}
62393 #endif
62394 
62395 	/*
62396 	 *  Unwind debugger state.  If we unwind while stepping
62397 	 *  (for any step type), pause execution.  This is the
62398 	 *  only place explicitly handling a step out.
62399 	 */
62400 
62401 #if defined(DUK_USE_DEBUGGER_SUPPORT)
62402 	heap = thr->heap;
62403 	if (heap->dbg_pause_act == thr->callstack_curr) {
62404 		if (heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_EXIT) {
62405 			DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function exit"));
62406 			duk_debug_set_paused(heap);
62407 		} else {
62408 			DUK_D(DUK_DPRINT("unwound past dbg_pause_act, set to NULL"));
62409 			heap->dbg_pause_act = NULL;  /* avoid stale pointers */
62410 		}
62411 		DUK_ASSERT(heap->dbg_pause_act == NULL);
62412 	}
62413 #endif
62414 
62415 	/*
62416 	 *  Unwind catchers.
62417 	 *
62418 	 *  Since there are no references in the catcher structure,
62419 	 *  unwinding is quite simple.  The only thing we need to
62420 	 *  look out for is popping a possible lexical environment
62421 	 *  established for an active catch clause.
62422 	 */
62423 
62424 	while (act->cat != NULL) {
62425 		duk_hthread_catcher_unwind_norz(thr, act);
62426 	}
62427 
62428 	/*
62429 	 *  Close environment record(s) if they exist.
62430 	 *
62431 	 *  Only variable environments are closed.  If lex_env != var_env, it
62432 	 *  cannot currently contain any register bound declarations.
62433 	 *
62434 	 *  Only environments created for a NEWENV function are closed.  If an
62435 	 *  environment is created for e.g. an eval call, it must not be closed.
62436 	 */
62437 
62438 	func = DUK_ACT_GET_FUNC(act);
62439 	if (func != NULL && !DUK_HOBJECT_HAS_NEWENV(func)) {
62440 		DUK_DDD(DUK_DDDPRINT("skip closing environments, envs not owned by this activation"));
62441 		goto skip_env_close;
62442 	}
62443 	/* func is NULL for lightfunc */
62444 
62445 	/* Catch sites are required to clean up their environments
62446 	 * in FINALLY part before propagating, so this should
62447 	 * always hold here.
62448 	 */
62449 	DUK_ASSERT(act->lex_env == act->var_env);
62450 
62451 	/* XXX: Closing the environment record copies values from registers
62452 	 * into the scope object.  It's side effect free as such, but may
62453 	 * currently run out of memory which causes an error throw.  This is
62454 	 * an actual sandboxing problem for error unwinds, and needs to be
62455 	 * fixed e.g. by preallocating the scope property slots.
62456 	 */
62457 	if (act->var_env != NULL) {
62458 		DUK_DDD(DUK_DDDPRINT("closing var_env record %p -> %!O",
62459 		                     (void *) act->var_env, (duk_heaphdr *) act->var_env));
62460 		duk_js_close_environment_record(thr, act->var_env);
62461 	}
62462 
62463  skip_env_close:
62464 
62465 	/*
62466 	 *  Update preventcount
62467 	 */
62468 
62469 	if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
62470 		DUK_ASSERT(thr->callstack_preventcount >= 1);
62471 		thr->callstack_preventcount--;
62472 	}
62473 
62474 	/*
62475 	 *  Reference count updates, using NORZ macros so we don't
62476 	 *  need to handle side effects.
62477 	 *
62478 	 *  duk_activation pointers like act->var_env are intentionally
62479 	 *  left as garbage and not NULLed.  Without side effects they
62480 	 *  can't be used when the values are dangling/garbage.
62481 	 */
62482 
62483 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, act->var_env);
62484 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, act->lex_env);
62485 	tmp = DUK_ACT_GET_FUNC(act);
62486 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
62487 	DUK_UNREF(tmp);
62488 }
62489 
62490 /* Unwind topmost duk_activation of a thread, caller must ensure that an
62491  * activation exists.  The call is side effect free, except that scope
62492  * closure may currently throw an out-of-memory error.
62493  */
62494 DUK_INTERNAL void duk_hthread_activation_unwind_norz(duk_hthread *thr) {
62495 	duk_activation *act;
62496 
62497 	duk__activation_unwind_nofree_norz(thr);
62498 
62499 	DUK_ASSERT(thr->callstack_curr != NULL);
62500 	DUK_ASSERT(thr->callstack_top > 0);
62501 	act = thr->callstack_curr;
62502 	thr->callstack_curr = act->parent;
62503 	thr->callstack_top--;
62504 
62505 	/* Ideally we'd restore value stack reserve here to caller's value.
62506 	 * This doesn't work for current unwind call sites however, because
62507 	 * the current (unwound) value stack top may be above the reserve.
62508 	 * Thus value stack reserve is restored by the call sites.
62509 	 */
62510 
62511 	/* XXX: inline for performance builds? */
62512 	duk_hthread_activation_free(thr, act);
62513 
62514 	/* We could clear the book-keeping variables like retval_byteoff for
62515 	 * the topmost activation, but don't do so now as it's not necessary.
62516 	 */
62517 }
62518 
62519 DUK_INTERNAL void duk_hthread_activation_unwind_reuse_norz(duk_hthread *thr) {
62520 	duk__activation_unwind_nofree_norz(thr);
62521 }
62522 
62523 /* Get duk_activation for given callstack level or NULL if level is invalid
62524  * or deeper than the call stack.  Level -1 refers to current activation, -2
62525  * to its caller, etc.  Starting from Duktape 2.2 finding the activation is
62526  * a linked list scan which gets more expensive the deeper the lookup is.
62527  */
62528 DUK_INTERNAL duk_activation *duk_hthread_get_activation_for_level(duk_hthread *thr, duk_int_t level) {
62529 	duk_activation *act;
62530 
62531 	if (level >= 0) {
62532 		return NULL;
62533 	}
62534 	act = thr->callstack_curr;
62535 	for (;;) {
62536 		if (act == NULL) {
62537 			return act;
62538 		}
62539 		if (level == -1) {
62540 			return act;
62541 		}
62542 		level++;
62543 		act = act->parent;
62544 	}
62545 	/* never here */
62546 }
62547 
62548 #if defined(DUK_USE_FINALIZER_TORTURE)
62549 DUK_INTERNAL void duk_hthread_valstack_torture_realloc(duk_hthread *thr) {
62550 	duk_size_t alloc_size;
62551 	duk_tval *new_ptr;
62552 	duk_ptrdiff_t alloc_end_off;
62553 	duk_ptrdiff_t end_off;
62554 	duk_ptrdiff_t bottom_off;
62555 	duk_ptrdiff_t top_off;
62556 
62557 	if (thr->valstack == NULL) {
62558 		DUK_D(DUK_DPRINT("skip valstack torture realloc, valstack is NULL"));
62559 		return;
62560 	}
62561 
62562 	alloc_end_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_alloc_end - (duk_uint8_t *) thr->valstack);
62563 	end_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
62564 	bottom_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
62565 	top_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack);
62566 	alloc_size = (duk_size_t) alloc_end_off;
62567 	if (alloc_size == 0) {
62568 		DUK_D(DUK_DPRINT("skip valstack torture realloc, alloc_size is zero"));
62569 		return;
62570 	}
62571 
62572 	/* Use DUK_ALLOC_RAW() to avoid side effects. */
62573 	new_ptr = (duk_tval *) DUK_ALLOC_RAW(thr->heap, alloc_size);
62574 	if (new_ptr != NULL) {
62575 		duk_memcpy((void *) new_ptr, (const void *) thr->valstack, alloc_size);
62576 		duk_memset((void *) thr->valstack, 0x55, alloc_size);
62577 		DUK_FREE_CHECKED(thr, (void *) thr->valstack);
62578 		thr->valstack = new_ptr;
62579 		thr->valstack_alloc_end = (duk_tval *) ((duk_uint8_t *) new_ptr + alloc_end_off);
62580 		thr->valstack_end = (duk_tval *) ((duk_uint8_t *) new_ptr + end_off);
62581 		thr->valstack_bottom = (duk_tval *) ((duk_uint8_t *) new_ptr + bottom_off);
62582 		thr->valstack_top = (duk_tval *) ((duk_uint8_t *) new_ptr + top_off);
62583 	} else {
62584 		DUK_D(DUK_DPRINT("failed to realloc valstack for torture, ignore"));
62585 	}
62586 }
62587 #endif  /* DUK_USE_FINALIZER_TORTURE */
62588 /*
62589  *  Shared helpers for arithmetic operations
62590  */
62591 
62592 /* #include duk_internal.h -> already included */
62593 
62594 /* ECMAScript modulus ('%') does not match IEEE 754 "remainder" operation
62595  * (implemented by remainder() in C99) but does seem to match ANSI C fmod().
62596  * Compare E5 Section 11.5.3 and "man fmod".
62597  */
62598 DUK_INTERNAL double duk_js_arith_mod(double d1, double d2) {
62599 #if defined(DUK_USE_POW_WORKAROUNDS)
62600 	/* Specific fixes to common fmod() implementation issues:
62601 	 * - test-bug-mingw-math-issues.js
62602 	 */
62603 	if (DUK_ISINF(d2)) {
62604 		if (DUK_ISINF(d1)) {
62605 			return DUK_DOUBLE_NAN;
62606 		} else {
62607 			return d1;
62608 		}
62609 	} else if (d1 == 0.0) {
62610 		/* d1 +/-0 is returned as is (preserving sign) except when
62611 		 * d2 is zero or NaN.
62612 		 */
62613 		if (d2 == 0.0 || DUK_ISNAN(d2)) {
62614 			return DUK_DOUBLE_NAN;
62615 		} else {
62616 			return d1;
62617 		}
62618 	}
62619 #else
62620 	/* Some ISO C assumptions. */
62621 	DUK_ASSERT(DUK_FMOD(1.0, DUK_DOUBLE_INFINITY) == 1.0);
62622 	DUK_ASSERT(DUK_FMOD(-1.0, DUK_DOUBLE_INFINITY) == -1.0);
62623 	DUK_ASSERT(DUK_FMOD(1.0, -DUK_DOUBLE_INFINITY) == 1.0);
62624 	DUK_ASSERT(DUK_FMOD(-1.0, -DUK_DOUBLE_INFINITY) == -1.0);
62625 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY)));
62626 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY)));
62627 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY)));
62628 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY)));
62629 	DUK_ASSERT(DUK_FMOD(0.0, 1.0) == 0.0 && DUK_SIGNBIT(DUK_FMOD(0.0, 1.0)) == 0);
62630 	DUK_ASSERT(DUK_FMOD(-0.0, 1.0) == 0.0 && DUK_SIGNBIT(DUK_FMOD(-0.0, 1.0)) != 0);
62631 	DUK_ASSERT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);
62632 	DUK_ASSERT(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY)) != 0);
62633 	DUK_ASSERT(DUK_FMOD(0.0, -DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);
62634 	DUK_ASSERT(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY)) != 0);
62635 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, 0.0)));
62636 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, 0.0)));
62637 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, -0.0)));
62638 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, -0.0)));
62639 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, DUK_DOUBLE_NAN)));
62640 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, DUK_DOUBLE_NAN)));
62641 #endif
62642 
62643 	return (duk_double_t) DUK_FMOD((double) d1, (double) d2);
62644 }
62645 
62646 /* Shared helper for Math.pow() and exponentiation operator. */
62647 DUK_INTERNAL double duk_js_arith_pow(double x, double y) {
62648 	/* The ANSI C pow() semantics differ from ECMAScript.
62649 	 *
62650 	 * E.g. when x==1 and y is +/- infinite, the ECMAScript required
62651 	 * result is NaN, while at least Linux pow() returns 1.
62652 	 */
62653 
62654 	duk_small_int_t cx, cy, sx;
62655 
62656 	DUK_UNREF(cx);
62657 	DUK_UNREF(sx);
62658 	cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
62659 
62660 	if (cy == DUK_FP_NAN) {
62661 		goto ret_nan;
62662 	}
62663 	if (DUK_FABS(x) == 1.0 && cy == DUK_FP_INFINITE) {
62664 		goto ret_nan;
62665 	}
62666 
62667 #if defined(DUK_USE_POW_WORKAROUNDS)
62668 	/* Specific fixes to common pow() implementation issues:
62669 	 *   - test-bug-netbsd-math-pow.js: NetBSD 6.0 on x86 (at least)
62670 	 *   - test-bug-mingw-math-issues.js
62671 	 */
62672 	cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
62673 	if (cx == DUK_FP_ZERO && y < 0.0) {
62674 		sx = (duk_small_int_t) DUK_SIGNBIT(x);
62675 		if (sx == 0) {
62676 			/* Math.pow(+0,y) should be Infinity when y<0.  NetBSD pow()
62677 			 * returns -Infinity instead when y is <0 and finite.  The
62678 			 * if-clause also catches y == -Infinity (which works even
62679 			 * without the fix).
62680 			 */
62681 			return DUK_DOUBLE_INFINITY;
62682 		} else {
62683 			/* Math.pow(-0,y) where y<0 should be:
62684 			 *   - -Infinity if y<0 and an odd integer
62685 			 *   - Infinity if y<0 but not an odd integer
62686 			 * NetBSD pow() returns -Infinity for all finite y<0.  The
62687 			 * if-clause also catches y == -Infinity (which works even
62688 			 * without the fix).
62689 			 */
62690 
62691 			/* fmod() return value has same sign as input (negative) so
62692 			 * the result here will be in the range ]-2,0], -1 indicates
62693 			 * odd.  If x is -Infinity, NaN is returned and the odd check
62694 			 * always concludes "not odd" which results in desired outcome.
62695 			 */
62696 			double tmp = DUK_FMOD(y, 2);
62697 			if (tmp == -1.0) {
62698 				return -DUK_DOUBLE_INFINITY;
62699 			} else {
62700 				/* Not odd, or y == -Infinity */
62701 				return DUK_DOUBLE_INFINITY;
62702 			}
62703 		}
62704 	} else if (cx == DUK_FP_NAN) {
62705 		if (y == 0.0) {
62706 			/* NaN ** +/- 0 should always be 1, but is NaN on
62707 			 * at least some Cygwin/MinGW versions.
62708 			 */
62709 			return 1.0;
62710 		}
62711 	}
62712 #else
62713 	/* Some ISO C assumptions. */
62714 	DUK_ASSERT(DUK_POW(DUK_DOUBLE_NAN, 0.0) == 1.0);
62715 	DUK_ASSERT(DUK_ISINF(DUK_POW(0.0, -1.0)) && DUK_SIGNBIT(DUK_POW(0.0, -1.0)) == 0);
62716 	DUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -2.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -2.0)) == 0);
62717 	DUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -3.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -3.0)) != 0);
62718 #endif
62719 
62720 	return DUK_POW(x, y);
62721 
62722  ret_nan:
62723 	return DUK_DOUBLE_NAN;
62724 }
62725 /*
62726  *  Call handling.
62727  *
62728  *  duk_handle_call_unprotected():
62729  *
62730  *    - Unprotected call to ECMAScript or Duktape/C function, from native
62731  *      code or bytecode executor.
62732  *
62733  *    - Also handles Ecma-to-Ecma calls which reuses a currently running
62734  *      executor instance to avoid native recursion.  Call setup is done
62735  *      normally, but just before calling the bytecode executor a special
62736  *      return code is used to indicate that a calling executor is reused.
62737  *
62738  *    - Also handles tailcalls, i.e. reuse of current duk_activation.
62739  *
62740  *    - Also handles setup for initial Duktape.Thread.resume().
62741  *
62742  *  duk_handle_safe_call():
62743  *
62744  *    - Protected C call within current activation.
62745  *
62746  *  setjmp() and local variables have a nasty interaction, see execution.rst;
62747  *  non-volatile locals modified after setjmp() call are not guaranteed to
62748  *  keep their value and can cause compiler or compiler version specific
62749  *  difficult to replicate issues.
62750  *
62751  *  See 'execution.rst'.
62752  */
62753 
62754 /* #include duk_internal.h -> already included */
62755 
62756 /* XXX: heap->error_not_allowed for success path too? */
62757 
62758 /*
62759  *  Limit check helpers.
62760  */
62761 
62762 /* Check native stack space if DUK_USE_NATIVE_STACK_CHECK() defined. */
62763 DUK_INTERNAL void duk_native_stack_check(duk_hthread *thr) {
62764 #if defined(DUK_USE_NATIVE_STACK_CHECK)
62765 	if (DUK_USE_NATIVE_STACK_CHECK() != 0) {
62766 		DUK_ERROR_RANGE(thr, DUK_STR_NATIVE_STACK_LIMIT);
62767 	}
62768 #else
62769 	DUK_UNREF(thr);
62770 #endif
62771 }
62772 
62773 /* Allow headroom for calls during error augmentation (see GH-191).
62774  * We allow space for 10 additional recursions, with one extra
62775  * for, e.g. a print() call at the deepest level, and an extra
62776  * +1 for protected call wrapping.
62777  */
62778 #define DUK__AUGMENT_CALL_RELAX_COUNT  (10 + 2)
62779 
62780 /* Stack space required by call handling entry. */
62781 #define DUK__CALL_HANDLING_REQUIRE_STACK  8
62782 
62783 DUK_LOCAL DUK_NOINLINE void duk__call_c_recursion_limit_check_slowpath(duk_hthread *thr) {
62784 	/* When augmenting an error, the effective limit is a bit higher.
62785 	 * Check for it only if the fast path check fails.
62786 	 */
62787 #if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
62788 	if (thr->heap->augmenting_error) {
62789 		if (thr->heap->call_recursion_depth < thr->heap->call_recursion_limit + DUK__AUGMENT_CALL_RELAX_COUNT) {
62790 			DUK_D(DUK_DPRINT("C recursion limit reached but augmenting error and within relaxed limit"));
62791 			return;
62792 		}
62793 	}
62794 #endif
62795 
62796 	DUK_D(DUK_DPRINT("call prevented because C recursion limit reached"));
62797 	DUK_ERROR_RANGE(thr, DUK_STR_NATIVE_STACK_LIMIT);
62798 	DUK_WO_NORETURN(return;);
62799 }
62800 
62801 DUK_LOCAL DUK_ALWAYS_INLINE void duk__call_c_recursion_limit_check(duk_hthread *thr) {
62802 	DUK_ASSERT(thr->heap->call_recursion_depth >= 0);
62803 	DUK_ASSERT(thr->heap->call_recursion_depth <= thr->heap->call_recursion_limit);
62804 
62805 	duk_native_stack_check(thr);
62806 
62807 	/* This check is forcibly inlined because it's very cheap and almost
62808 	 * always passes.  The slow path is forcibly noinline.
62809 	 */
62810 	if (DUK_LIKELY(thr->heap->call_recursion_depth < thr->heap->call_recursion_limit)) {
62811 		return;
62812 	}
62813 
62814 	duk__call_c_recursion_limit_check_slowpath(thr);
62815 }
62816 
62817 DUK_LOCAL DUK_NOINLINE void duk__call_callstack_limit_check_slowpath(duk_hthread *thr) {
62818 	/* When augmenting an error, the effective limit is a bit higher.
62819 	 * Check for it only if the fast path check fails.
62820 	 */
62821 #if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
62822 	if (thr->heap->augmenting_error) {
62823 		if (thr->callstack_top < DUK_USE_CALLSTACK_LIMIT + DUK__AUGMENT_CALL_RELAX_COUNT) {
62824 			DUK_D(DUK_DPRINT("call stack limit reached but augmenting error and within relaxed limit"));
62825 			return;
62826 		}
62827 	}
62828 #endif
62829 
62830 	/* XXX: error message is a bit misleading: we reached a recursion
62831 	 * limit which is also essentially the same as a C callstack limit
62832 	 * (except perhaps with some relaxed threading assumptions).
62833 	 */
62834 	DUK_D(DUK_DPRINT("call prevented because call stack limit reached"));
62835 	DUK_ERROR_RANGE(thr, DUK_STR_CALLSTACK_LIMIT);
62836 	DUK_WO_NORETURN(return;);
62837 }
62838 
62839 DUK_LOCAL DUK_ALWAYS_INLINE void duk__call_callstack_limit_check(duk_hthread *thr) {
62840 	/* This check is forcibly inlined because it's very cheap and almost
62841 	 * always passes.  The slow path is forcibly noinline.
62842 	 */
62843 	if (DUK_LIKELY(thr->callstack_top < DUK_USE_CALLSTACK_LIMIT)) {
62844 		return;
62845 	}
62846 
62847 	duk__call_callstack_limit_check_slowpath(thr);
62848 }
62849 
62850 /*
62851  *  Interrupt counter fixup (for development only).
62852  */
62853 
62854 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
62855 DUK_LOCAL void duk__interrupt_fixup(duk_hthread *thr, duk_hthread *entry_curr_thread) {
62856 	/* Currently the bytecode executor and executor interrupt
62857 	 * instruction counts are off because we don't execute the
62858 	 * interrupt handler when we're about to exit from the initial
62859 	 * user call into Duktape.
62860 	 *
62861 	 * If we were to execute the interrupt handler here, the counts
62862 	 * would match.  You can enable this block manually to check
62863 	 * that this is the case.
62864 	 */
62865 
62866 	DUK_ASSERT(thr != NULL);
62867 	DUK_ASSERT(thr->heap != NULL);
62868 
62869 #if defined(DUK_USE_INTERRUPT_DEBUG_FIXUP)
62870 	if (entry_curr_thread == NULL) {
62871 		thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
62872 		thr->heap->inst_count_interrupt += thr->interrupt_init;
62873 		DUK_DD(DUK_DDPRINT("debug test: updated interrupt count on exit to "
62874 		                   "user code, instruction counts: executor=%ld, interrupt=%ld",
62875 		                   (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
62876 		DUK_ASSERT(thr->heap->inst_count_exec == thr->heap->inst_count_interrupt);
62877 	}
62878 #else
62879 	DUK_UNREF(thr);
62880 	DUK_UNREF(entry_curr_thread);
62881 #endif
62882 }
62883 #endif
62884 
62885 /*
62886  *  Arguments object creation.
62887  *
62888  *  Creating arguments objects involves many small details, see E5 Section
62889  *  10.6 for the specific requirements.  Much of the arguments object exotic
62890  *  behavior is implemented in duk_hobject_props.c, and is enabled by the
62891  *  object flag DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS.
62892  */
62893 
62894 DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
62895                                             duk_hobject *func,
62896                                             duk_hobject *varenv,
62897                                             duk_idx_t idx_args) {
62898 	duk_hobject *arg;          /* 'arguments' */
62899 	duk_hobject *formals;      /* formals for 'func' (may be NULL if func is a C function) */
62900 	duk_idx_t i_arg;
62901 	duk_idx_t i_map;
62902 	duk_idx_t i_mappednames;
62903 	duk_idx_t i_formals;
62904 	duk_idx_t i_argbase;
62905 	duk_idx_t n_formals;
62906 	duk_idx_t idx;
62907 	duk_idx_t num_stack_args;
62908 	duk_bool_t need_map;
62909 
62910 	DUK_ASSERT(thr != NULL);
62911 	DUK_ASSERT(func != NULL);
62912 	DUK_ASSERT(DUK_HOBJECT_IS_NONBOUND_FUNCTION(func));
62913 	DUK_ASSERT(varenv != NULL);
62914 
62915 	/* [ ... func this arg1(@idx_args) ... argN envobj ]
62916 	 * [ arg1(@idx_args) ... argN envobj ] (for tailcalls)
62917 	 */
62918 
62919 	need_map = 0;
62920 
62921 	i_argbase = idx_args;
62922 	num_stack_args = duk_get_top(thr) - i_argbase - 1;
62923 	DUK_ASSERT(i_argbase >= 0);
62924 	DUK_ASSERT(num_stack_args >= 0);
62925 
62926 	formals = (duk_hobject *) duk_hobject_get_formals(thr, (duk_hobject *) func);
62927 	if (formals) {
62928 		n_formals = (duk_idx_t) ((duk_harray *) formals)->length;
62929 		duk_push_hobject(thr, formals);
62930 	} else {
62931 		/* This shouldn't happen without tampering of internal
62932 		 * properties: if a function accesses 'arguments', _Formals
62933 		 * is kept.  Check for the case anyway in case internal
62934 		 * properties have been modified manually.
62935 		 */
62936 		DUK_D(DUK_DPRINT("_Formals is undefined when creating arguments, use n_formals == 0"));
62937 		n_formals = 0;
62938 		duk_push_undefined(thr);
62939 	}
62940 	i_formals = duk_require_top_index(thr);
62941 
62942 	DUK_ASSERT(n_formals >= 0);
62943 	DUK_ASSERT(formals != NULL || n_formals == 0);
62944 
62945 	DUK_DDD(DUK_DDDPRINT("func=%!O, formals=%!O, n_formals=%ld",
62946 	                     (duk_heaphdr *) func, (duk_heaphdr *) formals,
62947 	                     (long) n_formals));
62948 
62949 	/* [ ... formals ] */
62950 
62951 	/*
62952 	 *  Create required objects:
62953 	 *    - 'arguments' object: array-like, but not an array
62954 	 *    - 'map' object: internal object, tied to 'arguments' (bare)
62955 	 *    - 'mappedNames' object: temporary value used during construction (bare)
62956 	 */
62957 
62958 	arg = duk_push_object_helper(thr,
62959 	                             DUK_HOBJECT_FLAG_EXTENSIBLE |
62960 	                             DUK_HOBJECT_FLAG_FASTREFS |
62961 	                             DUK_HOBJECT_FLAG_ARRAY_PART |
62962 	                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARGUMENTS),
62963 	                             DUK_BIDX_OBJECT_PROTOTYPE);
62964 	DUK_ASSERT(arg != NULL);
62965 	(void) duk_push_object_helper(thr,
62966 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
62967 	                              DUK_HOBJECT_FLAG_FASTREFS |
62968 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
62969 	                              -1);  /* no prototype */
62970 	(void) duk_push_object_helper(thr,
62971 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
62972 	                              DUK_HOBJECT_FLAG_FASTREFS |
62973 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
62974 	                              -1);  /* no prototype */
62975 	i_arg = duk_get_top(thr) - 3;
62976 	i_map = i_arg + 1;
62977 	i_mappednames = i_arg + 2;
62978 	DUK_ASSERT(!duk_is_bare_object(thr, -3));  /* arguments */
62979 	DUK_ASSERT(duk_is_bare_object(thr, -2));  /* map */
62980 	DUK_ASSERT(duk_is_bare_object(thr, -1));  /* mappedNames */
62981 
62982 	/* [ ... formals arguments map mappedNames ] */
62983 
62984 	DUK_DDD(DUK_DDDPRINT("created arguments related objects: "
62985 	                     "arguments at index %ld -> %!O "
62986 	                     "map at index %ld -> %!O "
62987 	                     "mappednames at index %ld -> %!O",
62988 	                     (long) i_arg, (duk_heaphdr *) duk_get_hobject(thr, i_arg),
62989 	                     (long) i_map, (duk_heaphdr *) duk_get_hobject(thr, i_map),
62990 	                     (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));
62991 
62992 	/*
62993 	 *  Init arguments properties, map, etc.
62994 	 */
62995 
62996 	duk_push_int(thr, num_stack_args);
62997 	duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_WC);
62998 
62999 	/*
63000 	 *  Init argument related properties.
63001 	 */
63002 
63003 	/* step 11 */
63004 	idx = num_stack_args - 1;
63005 	while (idx >= 0) {
63006 		DUK_DDD(DUK_DDDPRINT("arg idx %ld, argbase=%ld, argidx=%ld",
63007 		                     (long) idx, (long) i_argbase, (long) (i_argbase + idx)));
63008 
63009 		DUK_DDD(DUK_DDDPRINT("define arguments[%ld]=arg", (long) idx));
63010 		duk_dup(thr, i_argbase + idx);
63011 		duk_xdef_prop_index_wec(thr, i_arg, (duk_uarridx_t) idx);
63012 		DUK_DDD(DUK_DDDPRINT("defined arguments[%ld]=arg", (long) idx));
63013 
63014 		/* step 11.c is relevant only if non-strict (checked in 11.c.ii) */
63015 		if (!DUK_HOBJECT_HAS_STRICT(func) && idx < n_formals) {
63016 			DUK_ASSERT(formals != NULL);
63017 
63018 			DUK_DDD(DUK_DDDPRINT("strict function, index within formals (%ld < %ld)",
63019 			                     (long) idx, (long) n_formals));
63020 
63021 			duk_get_prop_index(thr, i_formals, (duk_uarridx_t) idx);
63022 			DUK_ASSERT(duk_is_string(thr, -1));
63023 
63024 			duk_dup_top(thr);  /* [ ... name name ] */
63025 
63026 			if (!duk_has_prop(thr, i_mappednames)) {
63027 				/* steps 11.c.ii.1 - 11.c.ii.4, but our internal book-keeping
63028 				 * differs from the reference model
63029 				 */
63030 
63031 				/* [ ... name ] */
63032 
63033 				need_map = 1;
63034 
63035 				DUK_DDD(DUK_DDDPRINT("set mappednames[%s]=%ld",
63036 				                     (const char *) duk_get_string(thr, -1),
63037 				                     (long) idx));
63038 				duk_dup_top(thr);                      /* name */
63039 				(void) duk_push_uint_to_hstring(thr, (duk_uint_t) idx);  /* index */
63040 				duk_xdef_prop_wec(thr, i_mappednames);  /* out of spec, must be configurable */
63041 
63042 				DUK_DDD(DUK_DDDPRINT("set map[%ld]=%s",
63043 				                     (long) idx,
63044 				                     duk_get_string(thr, -1)));
63045 				duk_dup_top(thr);         /* name */
63046 				duk_xdef_prop_index_wec(thr, i_map, (duk_uarridx_t) idx);  /* out of spec, must be configurable */
63047 			} else {
63048 				/* duk_has_prop() popped the second 'name' */
63049 			}
63050 
63051 			/* [ ... name ] */
63052 			duk_pop(thr);  /* pop 'name' */
63053 		}
63054 
63055 		idx--;
63056 	}
63057 
63058 	DUK_DDD(DUK_DDDPRINT("actual arguments processed"));
63059 
63060 	/* step 12 */
63061 	if (need_map) {
63062 		DUK_DDD(DUK_DDDPRINT("adding 'map' and 'varenv' to arguments object"));
63063 
63064 		/* should never happen for a strict callee */
63065 		DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));
63066 
63067 		duk_dup(thr, i_map);
63068 		duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_MAP, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */
63069 
63070 		/* The variable environment for magic variable bindings needs to be
63071 		 * given by the caller and recorded in the arguments object.
63072 		 *
63073 		 * See E5 Section 10.6, the creation of setters/getters.
63074 		 *
63075 		 * The variable environment also provides access to the callee, so
63076 		 * an explicit (internal) callee property is not needed.
63077 		 */
63078 
63079 		duk_push_hobject(thr, varenv);
63080 		duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */
63081 	}
63082 
63083 	/* steps 13-14 */
63084 	if (DUK_HOBJECT_HAS_STRICT(func)) {
63085 		/* Callee/caller are throwers and are not deletable etc.  They
63086 		 * could be implemented as virtual properties, but currently
63087 		 * there is no support for virtual properties which are accessors
63088 		 * (only plain virtual properties).  This would not be difficult
63089 		 * to change in duk_hobject_props, but we can make the throwers
63090 		 * normal, concrete properties just as easily.
63091 		 *
63092 		 * Note that the specification requires that the *same* thrower
63093 		 * built-in object is used here!  See E5 Section 10.6 main
63094 		 * algoritm, step 14, and Section 13.2.3 which describes the
63095 		 * thrower.  See test case test-arguments-throwers.js.
63096 		 */
63097 
63098 		DUK_DDD(DUK_DDDPRINT("strict function, setting caller/callee to throwers"));
63099 
63100 		/* In ES2017 .caller is no longer set at all. */
63101 		duk_xdef_prop_stridx_thrower(thr, i_arg, DUK_STRIDX_CALLEE);
63102 	} else {
63103 		DUK_DDD(DUK_DDDPRINT("non-strict function, setting callee to actual value"));
63104 		duk_push_hobject(thr, func);
63105 		duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_CALLEE, DUK_PROPDESC_FLAGS_WC);
63106 	}
63107 
63108 	/* set exotic behavior only after we're done */
63109 	if (need_map) {
63110 		/* Exotic behaviors are only enabled for arguments objects
63111 		 * which have a parameter map (see E5 Section 10.6 main
63112 		 * algorithm, step 12).
63113 		 *
63114 		 * In particular, a non-strict arguments object with no
63115 		 * mapped formals does *NOT* get exotic behavior, even
63116 		 * for e.g. "caller" property.  This seems counterintuitive
63117 		 * but seems to be the case.
63118 		 */
63119 
63120 		/* cannot be strict (never mapped variables) */
63121 		DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));
63122 
63123 		DUK_DDD(DUK_DDDPRINT("enabling exotic behavior for arguments object"));
63124 		DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(arg);
63125 	} else {
63126 		DUK_DDD(DUK_DDDPRINT("not enabling exotic behavior for arguments object"));
63127 	}
63128 
63129 	DUK_DDD(DUK_DDDPRINT("final arguments related objects: "
63130 	                     "arguments at index %ld -> %!O "
63131 	                     "map at index %ld -> %!O "
63132 	                     "mappednames at index %ld -> %!O",
63133 	                     (long) i_arg, (duk_heaphdr *) duk_get_hobject(thr, i_arg),
63134 	                     (long) i_map, (duk_heaphdr *) duk_get_hobject(thr, i_map),
63135 	                     (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));
63136 
63137 	/* [ args(n) envobj formals arguments map mappednames ] */
63138 
63139 	duk_pop_2(thr);
63140 	duk_remove_m2(thr);
63141 
63142 	/* [ args(n) envobj arguments ] */
63143 }
63144 
63145 /* Helper for creating the arguments object and adding it to the env record
63146  * on top of the value stack.
63147  */
63148 DUK_LOCAL void duk__handle_createargs_for_call(duk_hthread *thr,
63149                                                duk_hobject *func,
63150                                                duk_hobject *env,
63151                                                duk_idx_t idx_args) {
63152 	DUK_DDD(DUK_DDDPRINT("creating arguments object for function call"));
63153 
63154 	DUK_ASSERT(thr != NULL);
63155 	DUK_ASSERT(func != NULL);
63156 	DUK_ASSERT(env != NULL);
63157 	DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
63158 
63159 	/* [ ... arg1 ... argN envobj ] */
63160 
63161 	duk__create_arguments_object(thr,
63162 	                             func,
63163 	                             env,
63164 	                             idx_args);
63165 
63166 	/* [ ... arg1 ... argN envobj argobj ] */
63167 
63168 	duk_xdef_prop_stridx_short(thr,
63169 	                           -2,
63170 	                           DUK_STRIDX_LC_ARGUMENTS,
63171 	                           DUK_HOBJECT_HAS_STRICT(func) ? DUK_PROPDESC_FLAGS_E :   /* strict: non-deletable, non-writable */
63172 	                                                          DUK_PROPDESC_FLAGS_WE);  /* non-strict: non-deletable, writable */
63173 	/* [ ... arg1 ... argN envobj ] */
63174 }
63175 
63176 /*
63177  *  Helpers for constructor call handling.
63178  *
63179  *  There are two [[Construct]] operations in the specification:
63180  *
63181  *    - E5 Section 13.2.2: for Function objects
63182  *    - E5 Section 15.3.4.5.2: for "bound" Function objects
63183  *
63184  *  The chain of bound functions is resolved in Section 15.3.4.5.2,
63185  *  with arguments "piling up" until the [[Construct]] internal
63186  *  method is called on the final, actual Function object.  Note
63187  *  that the "prototype" property is looked up *only* from the
63188  *  final object, *before* calling the constructor.
63189  *
63190  *  Since Duktape 2.2 bound functions are represented with the
63191  *  duk_hboundfunc internal type, and bound function chains are
63192  *  collapsed when a bound function is created.  As a result, the
63193  *  direct target of a duk_hboundfunc is always non-bound and the
63194  *  this/argument lists have been resolved.
63195  *
63196  *  When constructing new Array instances, an unnecessary object is
63197  *  created and discarded now: the standard [[Construct]] creates an
63198  *  object, and calls the Array constructor.  The Array constructor
63199  *  returns an Array instance, which is used as the result value for
63200  *  the "new" operation; the object created before the Array constructor
63201  *  call is discarded.
63202  *
63203  *  This would be easy to fix, e.g. by knowing that the Array constructor
63204  *  will always create a replacement object and skip creating the fallback
63205  *  object in that case.
63206  */
63207 
63208 /* Update default instance prototype for constructor call. */
63209 DUK_LOCAL void duk__update_default_instance_proto(duk_hthread *thr, duk_idx_t idx_func) {
63210 	duk_hobject *proto;
63211 	duk_hobject *fallback;
63212 
63213 	DUK_ASSERT(duk_is_constructable(thr, idx_func));
63214 
63215 	duk_get_prop_stridx_short(thr, idx_func, DUK_STRIDX_PROTOTYPE);
63216 	proto = duk_get_hobject(thr, -1);
63217 	if (proto == NULL) {
63218 		DUK_DDD(DUK_DDDPRINT("constructor has no 'prototype' property, or value not an object "
63219 		                     "-> leave standard Object prototype as fallback prototype"));
63220 	} else {
63221 		DUK_DDD(DUK_DDDPRINT("constructor has 'prototype' property with object value "
63222 		                     "-> set fallback prototype to that value: %!iO", (duk_heaphdr *) proto));
63223 		/* Original fallback (default instance) is untouched when
63224 		 * resolving bound functions etc.
63225 		 */
63226 		fallback = duk_known_hobject(thr, idx_func + 1);
63227 		DUK_ASSERT(fallback != NULL);
63228 		DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, fallback, proto);
63229 	}
63230 	duk_pop(thr);
63231 }
63232 
63233 /* Postprocess: return value special handling, error augmentation. */
63234 DUK_INTERNAL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uint_t proxy_invariant) {
63235 	/* Use either fallback (default instance) or retval depending
63236 	 * on retval type.  Needs to be called before unwind because
63237 	 * the default instance is read from the current (immutable)
63238 	 * 'this' binding.
63239 	 *
63240 	 * For Proxy 'construct' calls the return value must be an
63241 	 * Object (we accept object-like values like buffers and
63242 	 * lightfuncs too).  If not, TypeError.
63243 	 */
63244 	if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
63245 	                                 DUK_TYPE_MASK_BUFFER |
63246 	                                 DUK_TYPE_MASK_LIGHTFUNC)) {
63247 		DUK_DDD(DUK_DDDPRINT("replacement value"));
63248 	} else {
63249 		if (DUK_UNLIKELY(proxy_invariant != 0U)) {
63250 			/* Proxy 'construct' return value invariant violated. */
63251 			DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr);
63252 			DUK_WO_NORETURN(return;);
63253 		}
63254 		/* XXX: direct value stack access */
63255 		duk_pop(thr);
63256 		duk_push_this(thr);
63257 	}
63258 
63259 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
63260 	/* Augment created errors upon creation, not when they are thrown or
63261 	 * rethrown.  __FILE__ and __LINE__ are not desirable here; the call
63262 	 * stack reflects the caller which is correct.  Skip topmost, unwound
63263 	 * activation when creating a traceback.  If thr->ptr_curr_pc was !=
63264 	 * NULL we'd need to sync the current PC so that the traceback comes
63265 	 * out right; however it is always synced here so just assert for it.
63266 	 */
63267 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
63268 	duk_err_augment_error_create(thr, thr, NULL, 0, DUK_AUGMENT_FLAG_NOBLAME_FILELINE |
63269 	                                                DUK_AUGMENT_FLAG_SKIP_ONE);
63270 #endif
63271 }
63272 
63273 /*
63274  *  Helper for handling a bound function when a call is being made.
63275  *
63276  *  Assumes that bound function chains have been "collapsed" so that either
63277  *  the target is non-bound or there is one bound function that points to a
63278  *  nonbound target.
63279  *
63280  *  Prepends the bound arguments to the value stack (at idx_func + 2).
63281  *  The 'this' binding is also updated if necessary (at idx_func + 1).
63282  *  Note that for constructor calls the 'this' binding is never updated by
63283  *  [[BoundThis]].
63284  */
63285 
63286 DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr,
63287                                                 duk_idx_t idx_func,
63288                                                 duk_bool_t is_constructor_call) {
63289 	duk_tval *tv_func;
63290 	duk_hobject *func;
63291 	duk_idx_t len;
63292 
63293 	DUK_ASSERT(thr != NULL);
63294 
63295 	/* On entry, item at idx_func is a bound, non-lightweight function,
63296 	 * but we don't rely on that below.
63297 	 */
63298 
63299 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
63300 
63301 	tv_func = duk_require_tval(thr, idx_func);
63302 	DUK_ASSERT(tv_func != NULL);
63303 
63304 	if (DUK_TVAL_IS_OBJECT(tv_func)) {
63305 		func = DUK_TVAL_GET_OBJECT(tv_func);
63306 
63307 		/* XXX: separate helper function, out of fast path? */
63308 		if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
63309 			duk_hboundfunc *h_bound;
63310 			duk_tval *tv_args;
63311 			duk_tval *tv_gap;
63312 
63313 			h_bound = (duk_hboundfunc *) (void *) func;
63314 			tv_args = h_bound->args;
63315 			len = h_bound->nargs;
63316 			DUK_ASSERT(len == 0 || tv_args != NULL);
63317 
63318 			DUK_DDD(DUK_DDDPRINT("bound function encountered, ptr=%p: %!T",
63319 			                     (void *) DUK_TVAL_GET_OBJECT(tv_func), tv_func));
63320 
63321 			/* [ ... func this arg1 ... argN ] */
63322 
63323 			if (is_constructor_call) {
63324 				/* See: tests/ecmascript/test-spec-bound-constructor.js */
63325 				DUK_DDD(DUK_DDDPRINT("constructor call: don't update this binding"));
63326 			} else {
63327 				/* XXX: duk_replace_tval */
63328 				duk_push_tval(thr, &h_bound->this_binding);
63329 				duk_replace(thr, idx_func + 1);  /* idx_this = idx_func + 1 */
63330 			}
63331 
63332 			/* [ ... func this arg1 ... argN ] */
63333 
63334 			duk_require_stack(thr, len);
63335 
63336 			tv_gap = duk_reserve_gap(thr, idx_func + 2, len);
63337 			duk_copy_tvals_incref(thr, tv_gap, tv_args, (duk_size_t) len);
63338 
63339 			/* [ ... func this <bound args> arg1 ... argN ] */
63340 
63341 			duk_push_tval(thr, &h_bound->target);
63342 			duk_replace(thr, idx_func);  /* replace in stack */
63343 
63344 			DUK_DDD(DUK_DDDPRINT("bound function handled, idx_func=%ld, curr func=%!T",
63345 			                     (long) idx_func, duk_get_tval(thr, idx_func)));
63346 		}
63347 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
63348 		/* Lightweight function: never bound, so terminate. */
63349 		;
63350 	} else {
63351 		/* Shouldn't happen, so ugly error is enough. */
63352 		DUK_ERROR_INTERNAL(thr);
63353 		DUK_WO_NORETURN(return;);
63354 	}
63355 
63356 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
63357 
63358 	DUK_DDD(DUK_DDDPRINT("final non-bound function is: %!T", duk_get_tval(thr, idx_func)));
63359 
63360 #if defined(DUK_USE_ASSERTIONS)
63361 	tv_func = duk_require_tval(thr, idx_func);
63362 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func) || DUK_TVAL_IS_OBJECT(tv_func));
63363 	if (DUK_TVAL_IS_OBJECT(tv_func)) {
63364 		func = DUK_TVAL_GET_OBJECT(tv_func);
63365 		DUK_ASSERT(func != NULL);
63366 		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
63367 		DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func) ||
63368 		           DUK_HOBJECT_HAS_NATFUNC(func) ||
63369 		           DUK_HOBJECT_IS_PROXY(func));
63370 	}
63371 #endif
63372 }
63373 
63374 /*
63375  *  Helper for inline handling of .call(), .apply(), and .construct().
63376  */
63377 
63378 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) {
63379 #if defined(DUK_USE_ASSERTIONS)
63380 	duk_c_function natfunc;
63381 #endif
63382 	duk_tval *tv_args;
63383 
63384 	DUK_ASSERT(func != NULL);
63385 	DUK_ASSERT((*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0);  /* Caller. */
63386 
63387 #if defined(DUK_USE_ASSERTIONS)
63388 	natfunc = ((duk_hnatfunc *) func)->func;
63389 	DUK_ASSERT(natfunc != NULL);
63390 #endif
63391 
63392 	/* On every round of function resolution at least target function and
63393 	 * 'this' binding are set.  We can assume that here, and must guarantee
63394 	 * it on exit.  Value stack reserve is extended for bound function and
63395 	 * .apply() unpacking so we don't need to extend it here when we need a
63396 	 * few slots.
63397 	 */
63398 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
63399 
63400 	/* Handle native 'eval' specially.  A direct eval check is only made
63401 	 * for the first resolution attempt; e.g. a bound eval call is -not-
63402 	 * a direct eval call.
63403 	 */
63404 	if (DUK_UNLIKELY(((duk_hnatfunc *) func)->magic == 15)) {
63405 		/* For now no special handling except for direct eval
63406 		 * detection.
63407 		 */
63408 		DUK_ASSERT(((duk_hnatfunc *) func)->func == duk_bi_global_object_eval);
63409 		if (first && (*call_flags & DUK_CALL_FLAG_CALLED_AS_EVAL)) {
63410 			*call_flags = (*call_flags & ~DUK_CALL_FLAG_CALLED_AS_EVAL) | DUK_CALL_FLAG_DIRECT_EVAL;
63411 		}
63412 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
63413 		return 1;  /* stop resolving */
63414 	}
63415 
63416 	/* Handle special functions based on the DUK_HOBJECT_FLAG_SPECIAL_CALL
63417 	 * flag; their magic value is used for switch-case.
63418 	 *
63419 	 * NOTE: duk_unpack_array_like() reserves value stack space
63420 	 * for the result values (unlike most other value stack calls).
63421 	 */
63422 	switch (((duk_hnatfunc *) func)->magic) {
63423 	case 0: {  /* 0=Function.prototype.call() */
63424 		/* Value stack:
63425 		 * idx_func + 0: Function.prototype.call()  [removed]
63426 		 * idx_func + 1: this binding for .call (target function)
63427 		 * idx_func + 2: 1st argument to .call, desired 'this' binding
63428 		 * idx_func + 3: 2nd argument to .call, desired 1st argument for ultimate target
63429 		 * ...
63430 		 *
63431 		 * Remove idx_func + 0 to get:
63432 		 * idx_func + 0: target function
63433 		 * idx_func + 1: this binding
63434 		 * idx_func + 2: call arguments
63435 		 * ...
63436 		 */
63437 		DUK_ASSERT(natfunc == duk_bi_function_prototype_call);
63438 		duk_remove_unsafe(thr, idx_func);
63439 		tv_args = thr->valstack_bottom + idx_func + 2;
63440 		if (thr->valstack_top < tv_args) {
63441 			DUK_ASSERT(tv_args <= thr->valstack_end);
63442 			thr->valstack_top = tv_args;  /* at least target function and 'this' binding present */
63443 		}
63444 		break;
63445 	}
63446 	case 1: {  /* 1=Function.prototype.apply() */
63447 		/* Value stack:
63448 		 * idx_func + 0: Function.prototype.apply()  [removed]
63449 		 * idx_func + 1: this binding for .apply (target function)
63450 		 * idx_func + 2: 1st argument to .apply, desired 'this' binding
63451 		 * idx_func + 3: 2nd argument to .apply, argArray
63452 		 * [anything after this MUST be ignored]
63453 		 *
63454 		 * Remove idx_func + 0 and unpack the argArray to get:
63455 		 * idx_func + 0: target function
63456 		 * idx_func + 1: this binding
63457 		 * idx_func + 2: call arguments
63458 		 * ...
63459 		 */
63460 		DUK_ASSERT(natfunc == duk_bi_function_prototype_apply);
63461 		duk_remove_unsafe(thr, idx_func);
63462 		goto apply_shared;
63463 	}
63464 #if defined(DUK_USE_REFLECT_BUILTIN)
63465 	case 2: {  /* 2=Reflect.apply() */
63466 		/* Value stack:
63467 		 * idx_func + 0: Reflect.apply()  [removed]
63468 		 * idx_func + 1: this binding for .apply (ignored, usually Reflect)  [removed]
63469 		 * idx_func + 2: 1st argument to .apply, target function
63470 		 * idx_func + 3: 2nd argument to .apply, desired 'this' binding
63471 		 * idx_func + 4: 3rd argument to .apply, argArray
63472 		 * [anything after this MUST be ignored]
63473 		 *
63474 		 * Remove idx_func + 0 and idx_func + 1, and unpack the argArray to get:
63475 		 * idx_func + 0: target function
63476 		 * idx_func + 1: this binding
63477 		 * idx_func + 2: call arguments
63478 		 * ...
63479 		 */
63480 		DUK_ASSERT(natfunc == duk_bi_reflect_apply);
63481 		duk_remove_n_unsafe(thr, idx_func, 2);
63482 		goto apply_shared;
63483 	}
63484 	case 3: {  /* 3=Reflect.construct() */
63485 		/* Value stack:
63486 		 * idx_func + 0: Reflect.construct()  [removed]
63487 		 * idx_func + 1: this binding for .construct (ignored, usually Reflect)  [removed]
63488 		 * idx_func + 2: 1st argument to .construct, target function
63489 		 * idx_func + 3: 2nd argument to .construct, argArray
63490 		 * idx_func + 4: 3rd argument to .construct, newTarget
63491 		 * [anything after this MUST be ignored]
63492 		 *
63493 		 * Remove idx_func + 0 and idx_func + 1, unpack the argArray,
63494 		 * and insert default instance (prototype not yet updated), to get:
63495 		 * idx_func + 0: target function
63496 		 * idx_func + 1: this binding (default instance)
63497 		 * idx_func + 2: constructor call arguments
63498 		 * ...
63499 		 *
63500 		 * Call flags must be updated to reflect the fact that we're
63501 		 * now dealing with a constructor call, and e.g. the 'this'
63502 		 * binding cannot be overwritten if the target is bound.
63503 		 *
63504 		 * newTarget is checked but not yet passed onwards.
63505 		 */
63506 
63507 		duk_idx_t top;
63508 
63509 		DUK_ASSERT(natfunc == duk_bi_reflect_construct);
63510 		*call_flags |= DUK_CALL_FLAG_CONSTRUCT;
63511 		duk_remove_n_unsafe(thr, idx_func, 2);
63512 		top = duk_get_top(thr);
63513 		if (!duk_is_constructable(thr, idx_func)) {
63514 			/* Target constructability must be checked before
63515 			 * unpacking argArray (which may cause side effects).
63516 			 * Just return; caller will throw the error.
63517 			 */
63518 			duk_set_top_unsafe(thr, idx_func + 2);  /* satisfy asserts */
63519 			break;
63520 		}
63521 		duk_push_object(thr);
63522 		duk_insert(thr, idx_func + 1);  /* default instance */
63523 
63524 		/* [ ... func default_instance argArray newTarget? ] */
63525 
63526 		top = duk_get_top(thr);
63527 		if (top < idx_func + 3) {
63528 			/* argArray is a mandatory argument for Reflect.construct(). */
63529 			DUK_ERROR_TYPE_INVALID_ARGS(thr);
63530 			DUK_WO_NORETURN(return 0;);
63531 		}
63532 		if (top > idx_func + 3) {
63533 			if (!duk_strict_equals(thr, idx_func, idx_func + 3)) {
63534 				/* XXX: [[Construct]] newTarget currently unsupported */
63535 				DUK_ERROR_UNSUPPORTED(thr);
63536 				DUK_WO_NORETURN(return 0;);
63537 			}
63538 			duk_set_top_unsafe(thr, idx_func + 3);  /* remove any args beyond argArray */
63539 		}
63540 		DUK_ASSERT(duk_get_top(thr) == idx_func + 3);
63541 		DUK_ASSERT(duk_is_valid_index(thr, idx_func + 2));
63542 		(void) duk_unpack_array_like(thr, idx_func + 2);  /* XXX: should also remove target to be symmetric with duk_pack()? */
63543 		duk_remove(thr, idx_func + 2);
63544 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
63545 		break;
63546 	}
63547 #endif  /* DUK_USE_REFLECT_BUILTIN */
63548 	default: {
63549 		DUK_ASSERT(0);
63550 		DUK_UNREACHABLE();
63551 	}
63552 	}
63553 
63554 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
63555 	return 0;  /* keep resolving */
63556 
63557  apply_shared:
63558 	tv_args = thr->valstack_bottom + idx_func + 2;
63559 	if (thr->valstack_top <= tv_args) {
63560 		DUK_ASSERT(tv_args <= thr->valstack_end);
63561 		thr->valstack_top = tv_args;  /* at least target func and 'this' binding present */
63562 		/* No need to check for argArray. */
63563 	} else {
63564 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 3);  /* idx_func + 2 covered above */
63565 		if (thr->valstack_top > tv_args + 1) {
63566 			duk_set_top_unsafe(thr, idx_func + 3);  /* remove any args beyond argArray */
63567 		}
63568 		DUK_ASSERT(duk_is_valid_index(thr, idx_func + 2));
63569 		if (!duk_is_callable(thr, idx_func)) {
63570 			/* Avoid unpack side effects if the target isn't callable.
63571 			 * Calling code will throw the actual error.
63572 			 */
63573 		} else {
63574 			(void) duk_unpack_array_like(thr, idx_func + 2);
63575 			duk_remove(thr, idx_func + 2);
63576 		}
63577 	}
63578 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
63579 	return 0;  /* keep resolving */
63580 }
63581 
63582 /*
63583  *  Helper for Proxy handling.
63584  */
63585 
63586 #if defined(DUK_USE_ES6_PROXY)
63587 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) {
63588 	duk_bool_t rc;
63589 
63590 	/* Value stack:
63591 	 * idx_func + 0: Proxy object
63592 	 * idx_func + 1: this binding for call
63593 	 * idx_func + 2: 1st argument for call
63594 	 * idx_func + 3: 2nd argument for call
63595 	 * ...
63596 	 *
63597 	 * If Proxy doesn't have a trap for the call ('apply' or 'construct'),
63598 	 * replace Proxy object with target object.
63599 	 *
63600 	 * If we're dealing with a normal call and the Proxy has an 'apply'
63601 	 * trap, manipulate value stack to:
63602 	 *
63603 	 * idx_func + 0: trap
63604 	 * idx_func + 1: Proxy's handler
63605 	 * idx_func + 2: Proxy's target
63606 	 * idx_func + 3: this binding for call (from idx_func + 1)
63607 	 * idx_func + 4: call arguments packed to an array
63608 	 *
63609 	 * If we're dealing with a constructor call and the Proxy has a
63610 	 * 'construct' trap, manipulate value stack to:
63611 	 *
63612 	 * idx_func + 0: trap
63613 	 * idx_func + 1: Proxy's handler
63614 	 * idx_func + 2: Proxy's target
63615 	 * idx_func + 3: call arguments packed to an array
63616 	 * idx_func + 4: newTarget == Proxy object here
63617 	 *
63618 	 * As we don't yet have proper newTarget support, the newTarget at
63619 	 * idx_func + 3 is just the original constructor being called, i.e.
63620 	 * the Proxy object (not the target).  Note that the default instance
63621 	 * (original 'this' binding) is dropped and ignored.
63622 	 */
63623 
63624 	duk_push_hobject(thr, h_proxy->handler);
63625 	rc = duk_get_prop_stridx_short(thr, -1, (*call_flags & DUK_CALL_FLAG_CONSTRUCT) ? DUK_STRIDX_CONSTRUCT : DUK_STRIDX_APPLY);
63626 	if (rc == 0) {
63627 		/* Not found, continue to target.  If this is a construct
63628 		 * call, update default instance prototype using the Proxy,
63629 		 * not the target.
63630 		 */
63631 		if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
63632 			if (!(*call_flags & DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED)) {
63633 				*call_flags |= DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED;
63634 				duk__update_default_instance_proto(thr, idx_func);
63635 			}
63636 		}
63637 		duk_pop_2(thr);
63638 		duk_push_hobject(thr, h_proxy->target);
63639 		duk_replace(thr, idx_func);
63640 		return;
63641 	}
63642 
63643 	/* Here we must be careful not to replace idx_func while
63644 	 * h_proxy is still needed, otherwise h_proxy may become
63645 	 * dangling.  This could be improved e.g. using a
63646 	 * duk_pack_slice() with a freeform slice.
63647 	 */
63648 
63649 	/* Here:
63650 	 * idx_func + 0: Proxy object
63651 	 * idx_func + 1: this binding for call
63652 	 * idx_func + 2: 1st argument for call
63653 	 * idx_func + 3: 2nd argument for call
63654 	 * ...
63655 	 * idx_func + N: handler
63656 	 * idx_func + N + 1: trap
63657 	 */
63658 
63659 	duk_insert(thr, idx_func + 1);
63660 	duk_insert(thr, idx_func + 2);
63661 	duk_push_hobject(thr, h_proxy->target);
63662 	duk_insert(thr, idx_func + 3);
63663 	duk_pack(thr, duk_get_top(thr) - (idx_func + 5));
63664 	DUK_ASSERT(!duk_is_bare_object(thr, -1));
63665 
63666 	/* Here:
63667 	 * idx_func + 0: Proxy object
63668 	 * idx_func + 1: trap
63669 	 * idx_func + 2: Proxy's handler
63670 	 * idx_func + 3: Proxy's target
63671 	 * idx_func + 4: this binding for call
63672 	 * idx_func + 5: arguments array
63673 	 */
63674 	DUK_ASSERT(duk_get_top(thr) == idx_func + 6);
63675 
63676 	if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
63677 		*call_flags |= DUK_CALL_FLAG_CONSTRUCT_PROXY;  /* Enable 'construct' trap return invariant check. */
63678 		*call_flags &= ~(DUK_CALL_FLAG_CONSTRUCT);     /* Resume as non-constructor call to the trap. */
63679 
63680 		/* 'apply' args: target, thisArg, argArray
63681 		 * 'construct' args: target, argArray, newTarget
63682 		 */
63683 		duk_remove(thr, idx_func + 4);
63684 		duk_push_hobject(thr, (duk_hobject *) h_proxy);
63685 	}
63686 
63687 	/* Finalize value stack layout by removing Proxy reference. */
63688 	duk_remove(thr, idx_func);
63689 	h_proxy = NULL;  /* invalidated */
63690 	DUK_ASSERT(duk_get_top(thr) == idx_func + 5);
63691 }
63692 #endif  /* DUK_USE_ES6_PROXY */
63693 
63694 /*
63695  *  Helper for setting up var_env and lex_env of an activation,
63696  *  assuming it does NOT have the DUK_HOBJECT_FLAG_NEWENV flag.
63697  */
63698 
63699 DUK_LOCAL void duk__handle_oldenv_for_call(duk_hthread *thr,
63700                                            duk_hobject *func,
63701                                            duk_activation *act) {
63702 	duk_hcompfunc *f;
63703 	duk_hobject *h_lex;
63704 	duk_hobject *h_var;
63705 
63706 	DUK_ASSERT(thr != NULL);
63707 	DUK_ASSERT(func != NULL);
63708 	DUK_ASSERT(act != NULL);
63709 	DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV(func));
63710 	DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
63711 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(func));
63712 	DUK_UNREF(thr);
63713 
63714 	f = (duk_hcompfunc *) func;
63715 	h_lex = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
63716 	h_var = DUK_HCOMPFUNC_GET_VARENV(thr->heap, f);
63717 	DUK_ASSERT(h_lex != NULL);  /* Always true for closures (not for templates) */
63718 	DUK_ASSERT(h_var != NULL);
63719 	act->lex_env = h_lex;
63720 	act->var_env = h_var;
63721 	DUK_HOBJECT_INCREF(thr, h_lex);
63722 	DUK_HOBJECT_INCREF(thr, h_var);
63723 }
63724 
63725 /*
63726  *  Helper for updating callee 'caller' property.
63727  */
63728 
63729 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
63730 DUK_LOCAL void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func) {
63731 	duk_tval *tv_caller;
63732 	duk_hobject *h_tmp;
63733 	duk_activation *act_callee;
63734 	duk_activation *act_caller;
63735 
63736 	DUK_ASSERT(thr != NULL);
63737 	DUK_ASSERT(func != NULL);
63738 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound chain resolved */
63739 	DUK_ASSERT(thr->callstack_top >= 1);
63740 
63741 	if (DUK_HOBJECT_HAS_STRICT(func)) {
63742 		/* Strict functions don't get their 'caller' updated. */
63743 		return;
63744 	}
63745 
63746 	DUK_ASSERT(thr->callstack_top > 0);
63747 	act_callee = thr->callstack_curr;
63748 	DUK_ASSERT(act_callee != NULL);
63749 	act_caller = (thr->callstack_top >= 2 ? act_callee->parent : NULL);
63750 
63751 	/* XXX: check .caller writability? */
63752 
63753 	/* Backup 'caller' property and update its value. */
63754 	tv_caller = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, func, DUK_STRIDX_CALLER);
63755 	if (tv_caller) {
63756 		/* If caller is global/eval code, 'caller' should be set to
63757 		 * 'null'.
63758 		 *
63759 		 * XXX: there is no exotic flag to infer this correctly now.
63760 		 * The NEWENV flag is used now which works as intended for
63761 		 * everything (global code, non-strict eval code, and functions)
63762 		 * except strict eval code.  Bound functions are never an issue
63763 		 * because 'func' has been resolved to a non-bound function.
63764 		 */
63765 
63766 		if (act_caller != NULL) {
63767 			/* act_caller->func may be NULL in some finalization cases,
63768 			 * just treat like we don't know the caller.
63769 			 */
63770 			if (act_caller->func && !DUK_HOBJECT_HAS_NEWENV(act_caller->func)) {
63771 				/* Setting to NULL causes 'caller' to be set to
63772 				 * 'null' as desired.
63773 				 */
63774 				act_caller = NULL;
63775 			}
63776 		}
63777 
63778 		if (DUK_TVAL_IS_OBJECT(tv_caller)) {
63779 			h_tmp = DUK_TVAL_GET_OBJECT(tv_caller);
63780 			DUK_ASSERT(h_tmp != NULL);
63781 			act_callee->prev_caller = h_tmp;
63782 
63783 			/* Previous value doesn't need refcount changes because its ownership
63784 			 * is transferred to prev_caller.
63785 			 */
63786 
63787 			if (act_caller != NULL) {
63788 				DUK_ASSERT(act_caller->func != NULL);
63789 				DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
63790 				DUK_TVAL_INCREF(thr, tv_caller);
63791 			} else {
63792 				DUK_TVAL_SET_NULL(tv_caller);  /* no incref */
63793 			}
63794 		} else {
63795 			/* 'caller' must only take on 'null' or function value */
63796 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_caller));
63797 			DUK_ASSERT(act_callee->prev_caller == NULL);
63798 			if (act_caller != NULL && act_caller->func) {
63799 				/* Tolerate act_caller->func == NULL which happens in
63800 				 * some finalization cases; treat like unknown caller.
63801 				 */
63802 				DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
63803 				DUK_TVAL_INCREF(thr, tv_caller);
63804 			} else {
63805 				DUK_TVAL_SET_NULL(tv_caller);  /* no incref */
63806 			}
63807 		}
63808 	}
63809 }
63810 #endif  /* DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
63811 
63812 /*
63813  *  Shared helpers for resolving the final, non-bound target function of the
63814  *  call and the effective 'this' binding.  Resolves bound functions and
63815  *  applies .call(), .apply(), and .construct() inline.
63816  *
63817  *  Proxy traps are also handled inline so that if the target is a Proxy with
63818  *  a 'call' or 'construct' trap, the trap handler is called with a modified
63819  *  argument list.
63820  *
63821  *  Once the bound function / .call() / .apply() / .construct() sequence has
63822  *  been resolved, the value at idx_func + 1 may need coercion described in
63823  *  E5 Section 10.4.3.
63824  *
63825  *  A call that begins as a non-constructor call may be converted into a
63826  *  constructor call during the resolution process if Reflect.construct()
63827  *  is invoked.  This is handled by updating the caller's call_flags.
63828  *
63829  *  For global and eval code (E5 Sections 10.4.1 and 10.4.2), we assume
63830  *  that the caller has provided the correct 'this' binding explicitly
63831  *  when calling, i.e.:
63832  *
63833  *    - global code: this=global object
63834  *    - direct eval: this=copy from eval() caller's this binding
63835  *    - other eval:  this=global object
63836  *
63837  *  The 'this' coercion may cause a recursive function call with arbitrary
63838  *  side effects, because ToObject() may be called.
63839  */
63840 
63841 DUK_LOCAL DUK_INLINE void duk__coerce_nonstrict_this_binding(duk_hthread *thr, duk_idx_t idx_this) {
63842 	duk_tval *tv_this;
63843 	duk_hobject *obj_global;
63844 
63845 	tv_this = thr->valstack_bottom + idx_this;
63846 	switch (DUK_TVAL_GET_TAG(tv_this)) {
63847 	case DUK_TAG_OBJECT:
63848 		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, object -> use directly"));
63849 		break;
63850 	case DUK_TAG_UNDEFINED:
63851 	case DUK_TAG_NULL:
63852 		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, undefined/null -> use global object"));
63853 		obj_global = thr->builtins[DUK_BIDX_GLOBAL];
63854 		/* XXX: avoid this check somehow */
63855 		if (DUK_LIKELY(obj_global != NULL)) {
63856 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this));  /* no need to decref previous value */
63857 			DUK_TVAL_SET_OBJECT(tv_this, obj_global);
63858 			DUK_HOBJECT_INCREF(thr, obj_global);
63859 		} else {
63860 			/* This may only happen if built-ins are being "torn down".
63861 			 * This behavior is out of specification scope.
63862 			 */
63863 			DUK_D(DUK_DPRINT("this binding: wanted to use global object, but it is NULL -> using undefined instead"));
63864 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this));  /* no need to decref previous value */
63865 			DUK_TVAL_SET_UNDEFINED(tv_this);  /* nothing to incref */
63866 		}
63867 		break;
63868 	default:
63869 		/* Plain buffers and lightfuncs are object coerced.  Lightfuncs
63870 		 * very rarely come here however, because the call target would
63871 		 * need to be a non-strict non-lightfunc (lightfuncs are considered
63872 		 * strict) with an explicit lightfunc 'this' binding.
63873 		 */
63874 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_this));
63875 		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, not object/undefined/null -> use ToObject(value)"));
63876 		duk_to_object(thr, idx_this);  /* may have side effects */
63877 		break;
63878 	}
63879 }
63880 
63881 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) {
63882 #if defined(DUK_USE_PREFER_SIZE)
63883 	DUK_UNREF(thr);
63884 	DUK_UNREF(idx_func);
63885 	DUK_UNREF(out_func);
63886 	DUK_UNREF(call_flags);
63887 #else  /* DUK_USE_PREFER_SIZE */
63888 	duk_tval *tv_func;
63889 	duk_hobject *func;
63890 
63891 	if (DUK_UNLIKELY(call_flags & DUK_CALL_FLAG_CONSTRUCT)) {
63892 		return 0;
63893 	}
63894 
63895 	tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
63896 	DUK_ASSERT(tv_func != NULL);
63897 
63898 	if (DUK_LIKELY(DUK_TVAL_IS_OBJECT(tv_func))) {
63899 		func = DUK_TVAL_GET_OBJECT(tv_func);
63900 		if (DUK_HOBJECT_IS_CALLABLE(func) &&
63901 		    !DUK_HOBJECT_HAS_BOUNDFUNC(func) &&
63902 		    !DUK_HOBJECT_HAS_SPECIAL_CALL(func)) {
63903 			*out_func = func;
63904 
63905 			if (DUK_HOBJECT_HAS_STRICT(func)) {
63906 				/* Strict function: no 'this' coercion. */
63907 				return 1;
63908 			}
63909 
63910 			duk__coerce_nonstrict_this_binding(thr, idx_func + 1);
63911 			return 1;
63912 		}
63913 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
63914 		*out_func = NULL;
63915 
63916 		/* Lightfuncs are considered strict, so 'this' binding is
63917 		 * used as is.  They're never bound, always constructable,
63918 		 * and never special functions.
63919 		 */
63920 		return 1;
63921 	}
63922 #endif  /* DUK_USE_PREFER_SIZE */
63923 	return 0;  /* let slow path deal with it */
63924 }
63925 
63926 DUK_LOCAL duk_hobject *duk__resolve_target_func_and_this_binding(duk_hthread *thr,
63927                                                                  duk_idx_t idx_func,
63928                                                                  duk_small_uint_t *call_flags) {
63929 	duk_tval *tv_func;
63930 	duk_hobject *func;
63931 	duk_bool_t first;
63932 
63933 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
63934 
63935 	for (first = 1;; first = 0) {
63936 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
63937 
63938 		tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
63939 		DUK_ASSERT(tv_func != NULL);
63940 
63941 		DUK_DD(DUK_DDPRINT("target func: %!iT", tv_func));
63942 
63943 		if (DUK_TVAL_IS_OBJECT(tv_func)) {
63944 			func = DUK_TVAL_GET_OBJECT(tv_func);
63945 
63946 			if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
63947 				if (DUK_UNLIKELY(!DUK_HOBJECT_HAS_CONSTRUCTABLE(func))) {
63948 					goto not_constructable;
63949 				}
63950 			} else {
63951 				if (DUK_UNLIKELY(!DUK_HOBJECT_IS_CALLABLE(func))) {
63952 					goto not_callable;
63953 				}
63954 			}
63955 
63956 			if (DUK_LIKELY(!DUK_HOBJECT_HAS_BOUNDFUNC(func) &&
63957 			               !DUK_HOBJECT_HAS_SPECIAL_CALL(func) &&
63958 			               !DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(func))) {
63959 				/* Common case, so test for using a single bitfield test.
63960 				 * Break out to handle this coercion etc.
63961 				 */
63962 				break;
63963 			}
63964 
63965 			/* XXX: could set specialcall for boundfuncs too, simplify check above */
63966 
63967 			if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
63968 				DUK_ASSERT(!DUK_HOBJECT_HAS_SPECIAL_CALL(func));
63969 				DUK_ASSERT(!DUK_HOBJECT_IS_NATFUNC(func));
63970 
63971 				/* Callable/constructable flags are the same
63972 				 * for the bound function and its target, so
63973 				 * we don't need to check them here, we can
63974 				 * check them from the target only.
63975 				 */
63976 				duk__handle_bound_chain_for_call(thr, idx_func, *call_flags & DUK_CALL_FLAG_CONSTRUCT);
63977 
63978 				DUK_ASSERT(DUK_TVAL_IS_OBJECT(duk_require_tval(thr, idx_func)) ||
63979 				           DUK_TVAL_IS_LIGHTFUNC(duk_require_tval(thr, idx_func)));
63980 			} else {
63981 				DUK_ASSERT(DUK_HOBJECT_HAS_SPECIAL_CALL(func));
63982 
63983 #if defined(DUK_USE_ES6_PROXY)
63984 				if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(func)) {
63985 					/* If no trap, resume processing from Proxy trap.
63986 					 * If trap exists, helper converts call into a trap
63987 					 * call; this may change a constructor call into a
63988 					 * normal (non-constructor) trap call.  We must
63989 					 * continue processing even when a trap is found as
63990 					 * the trap may be bound.
63991 					 */
63992 					duk__handle_proxy_for_call(thr, idx_func, (duk_hproxy *) func, call_flags);
63993 				}
63994 				else
63995 #endif
63996 				{
63997 					DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(func));
63998 					DUK_ASSERT(DUK_HOBJECT_HAS_CALLABLE(func));
63999 					DUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE(func));
64000 					/* Constructable check already done above. */
64001 
64002 					if (duk__handle_specialfuncs_for_call(thr, idx_func, func, call_flags, first) != 0) {
64003 						/* Encountered native eval call, normal call
64004 						 * context.  Break out, handle this coercion etc.
64005 						 */
64006 						break;
64007 					}
64008 				}
64009 			}
64010 			/* Retry loop. */
64011 		} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
64012 			/* Lightfuncs are:
64013 			 *   - Always strict, so no 'this' coercion.
64014 			 *   - Always callable.
64015 			 *   - Always constructable.
64016 			 *   - Never specialfuncs.
64017 			 */
64018 			func = NULL;
64019 			goto finished;
64020 		} else {
64021 			goto not_callable;
64022 		}
64023 	}
64024 
64025 	DUK_ASSERT(func != NULL);
64026 
64027 	if (!DUK_HOBJECT_HAS_STRICT(func)) {
64028 		/* Non-strict target needs 'this' coercion.
64029 		 * This has potential side effects invalidating
64030 		 * 'tv_func'.
64031 		 */
64032 		duk__coerce_nonstrict_this_binding(thr, idx_func + 1);
64033 	}
64034 	if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
64035 		if (!(*call_flags & DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED)) {
64036 			*call_flags |= DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED;
64037 			duk__update_default_instance_proto(thr, idx_func);
64038 		}
64039 	}
64040 
64041  finished:
64042 
64043 #if defined(DUK_USE_ASSERTIONS)
64044 	{
64045 		duk_tval *tv_tmp;
64046 
64047 		tv_tmp = duk_get_tval(thr, idx_func);
64048 		DUK_ASSERT(tv_tmp != NULL);
64049 
64050 		DUK_ASSERT((DUK_TVAL_IS_OBJECT(tv_tmp) && DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(tv_tmp))) ||
64051 		           DUK_TVAL_IS_LIGHTFUNC(tv_tmp));
64052 		DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
64053 		DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) ||
64054 		                            DUK_HOBJECT_IS_NATFUNC(func)));
64055 		DUK_ASSERT(func == NULL || (DUK_HOBJECT_HAS_CONSTRUCTABLE(func) ||
64056 		                            (*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0));
64057 	}
64058 #endif
64059 
64060 	return func;
64061 
64062  not_callable:
64063 	DUK_ASSERT(tv_func != NULL);
64064 
64065 #if defined(DUK_USE_VERBOSE_ERRORS)
64066 	/* GETPROPC delayed error handling: when target is not callable,
64067 	 * GETPROPC replaces idx_func+0 with a non-callable wrapper object
64068 	 * with a hidden Symbol to signify it's to be handled here.  If
64069 	 * found, unwrap the original Error and throw it as is here.  The
64070 	 * hidden Symbol is only checked as an own property, not inherited
64071 	 * (which would be dangerous).
64072 	 */
64073 	if (DUK_TVAL_IS_OBJECT(tv_func)) {
64074 		duk_tval *tv_wrap = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, DUK_TVAL_GET_OBJECT(tv_func), DUK_STRIDX_INT_TARGET);
64075 		if (tv_wrap != NULL) {
64076 			DUK_DD(DUK_DDPRINT("delayed error from GETPROPC: %!T", tv_wrap));
64077 			duk_push_tval(thr, tv_wrap);
64078 			(void) duk_throw(thr);
64079 			DUK_WO_NORETURN(return NULL;);
64080 		}
64081 	}
64082 #endif
64083 
64084 #if defined(DUK_USE_VERBOSE_ERRORS)
64085 #if defined(DUK_USE_PARANOID_ERRORS)
64086 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_get_type_name(thr, idx_func));
64087 #else
64088 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_push_string_tval_readable(thr, tv_func));
64089 #endif
64090 #else
64091 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
64092 #endif
64093 	DUK_WO_NORETURN(return NULL;);
64094 
64095  not_constructable:
64096 	/* For now GETPROPC delayed error not needed for constructor calls. */
64097 #if defined(DUK_USE_VERBOSE_ERRORS)
64098 #if defined(DUK_USE_PARANOID_ERRORS)
64099 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not constructable", duk_get_type_name(thr, idx_func));
64100 #else
64101 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not constructable", duk_push_string_tval_readable(thr, tv_func));
64102 #endif
64103 #else
64104 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONSTRUCTABLE);
64105 #endif
64106 	DUK_WO_NORETURN(return NULL;);
64107 }
64108 
64109 /*
64110  *  Manipulate value stack so that exactly 'num_stack_rets' return
64111  *  values are at 'idx_retbase' in every case, assuming there are
64112  *  'rc' return values on top of stack.
64113  *
64114  *  This is a bit tricky, because the called C function operates in
64115  *  the same activation record and may have e.g. popped the stack
64116  *  empty (below idx_retbase).
64117  */
64118 
64119 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) {
64120 	duk_idx_t idx_rcbase;
64121 
64122 	DUK_ASSERT(thr != NULL);
64123 	DUK_ASSERT(idx_retbase >= 0);
64124 	DUK_ASSERT(num_stack_rets >= 0);
64125 	DUK_ASSERT(num_actual_rets >= 0);
64126 
64127 	idx_rcbase = duk_get_top(thr) - num_actual_rets;  /* base of known return values */
64128 	if (DUK_UNLIKELY(idx_rcbase < 0)) {
64129 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_CFUNC_RC);
64130 		DUK_WO_NORETURN(return;);
64131 	}
64132 
64133 	DUK_DDD(DUK_DDDPRINT("adjust valstack after func call: "
64134 	                     "num_stack_rets=%ld, num_actual_rets=%ld, stack_top=%ld, idx_retbase=%ld, idx_rcbase=%ld",
64135 	                     (long) num_stack_rets, (long) num_actual_rets, (long) duk_get_top(thr),
64136 	                     (long) idx_retbase, (long) idx_rcbase));
64137 
64138 	DUK_ASSERT(idx_rcbase >= 0);  /* caller must check */
64139 
64140 	/* Space for num_stack_rets was reserved before the safe call.
64141 	 * Because value stack reserve cannot shrink except in call returns,
64142 	 * the reserve is still in place.  Adjust valstack, carefully
64143 	 * ensuring we don't overstep the reserve.
64144 	 */
64145 
64146 	/* Match idx_rcbase with idx_retbase so that the return values
64147 	 * start at the correct index.
64148 	 */
64149 	if (idx_rcbase > idx_retbase) {
64150 		duk_idx_t count = idx_rcbase - idx_retbase;
64151 
64152 		DUK_DDD(DUK_DDDPRINT("elements at/after idx_retbase have enough to cover func retvals "
64153 		                     "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
64154 
64155 		/* Remove values between irc_rcbase (start of intended return
64156 		 * values) and idx_retbase to lower return values to idx_retbase.
64157 		 */
64158 		DUK_ASSERT(count > 0);
64159 		duk_remove_n(thr, idx_retbase, count);  /* may be NORZ */
64160 	} else {
64161 		duk_idx_t count = idx_retbase - idx_rcbase;
64162 
64163 		DUK_DDD(DUK_DDDPRINT("not enough elements at/after idx_retbase to cover func retvals "
64164 		                     "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
64165 
64166 		/* Insert 'undefined' at idx_rcbase (start of intended return
64167 		 * values) to lift return values to idx_retbase.
64168 		 */
64169 		DUK_ASSERT(count >= 0);
64170 		DUK_ASSERT(thr->valstack_end - thr->valstack_top >= count);  /* reserve cannot shrink */
64171 		duk_insert_undefined_n(thr, idx_rcbase, count);
64172 	}
64173 
64174 	/* Chop extra retvals away / extend with undefined. */
64175 	duk_set_top_unsafe(thr, idx_retbase + num_stack_rets);
64176 }
64177 
64178 /*
64179  *  Activation setup for tailcalls and non-tailcalls.
64180  */
64181 
64182 #if defined(DUK_USE_TAILCALL)
64183 DUK_LOCAL duk_small_uint_t duk__call_setup_act_attempt_tailcall(duk_hthread *thr,
64184                                                                 duk_small_uint_t call_flags,
64185                                                                 duk_idx_t idx_func,
64186                                                                 duk_hobject *func,
64187                                                                 duk_size_t entry_valstack_bottom_byteoff,
64188                                                                 duk_size_t entry_valstack_end_byteoff,
64189                                                                 duk_idx_t *out_nargs,
64190                                                                 duk_idx_t *out_nregs,
64191                                                                 duk_size_t *out_vs_min_bytes,
64192                                                                 duk_activation **out_act) {
64193 	duk_activation *act;
64194 	duk_tval *tv1, *tv2;
64195 	duk_idx_t idx_args;
64196 	duk_small_uint_t flags1, flags2;
64197 #if defined(DUK_USE_DEBUGGER_SUPPORT)
64198 	duk_activation *prev_pause_act;
64199 #endif
64200 
64201 	DUK_UNREF(entry_valstack_end_byteoff);
64202 
64203 	/* Tailcall cannot be flagged to resume calls, and a
64204 	 * previous frame must exist.
64205 	 */
64206 	DUK_ASSERT(thr->callstack_top >= 1);
64207 
64208 	act = thr->callstack_curr;
64209 	DUK_ASSERT(act != NULL);
64210 	*out_act = act;
64211 
64212 	if (func == NULL || !DUK_HOBJECT_IS_COMPFUNC(func)) {
64213 		DUK_DDD(DUK_DDDPRINT("tail call prevented by target not being ecma function"));
64214 		return 0;
64215 	}
64216 	if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
64217 		DUK_DDD(DUK_DDDPRINT("tail call prevented by current activation having DUK_ACT_FLAG_PREVENT_YIELD"));
64218 		return 0;
64219 	}
64220 	/* Tailcall is only allowed if current and candidate
64221 	 * function have identical return value handling.  There
64222 	 * are three possible return value handling cases:
64223 	 *   1. Normal function call, no special return value handling.
64224 	 *   2. Constructor call, return value replacement object check.
64225 	 *   3. Proxy 'construct' trap call, return value invariant check.
64226 	 */
64227 	flags1 = (duk_small_uint_t) ((act->flags & DUK_ACT_FLAG_CONSTRUCT) ? 1 : 0)
64228 #if defined(DUK_USE_ES6_PROXY)
64229 	         | (duk_small_uint_t) ((act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) ? 2 : 0)
64230 #endif
64231 	         ;
64232 	flags2 = (duk_small_uint_t) ((call_flags & DUK_CALL_FLAG_CONSTRUCT) ? 1 : 0)
64233 #if defined(DUK_USE_ES6_PROXY)
64234 	         | (duk_small_uint_t) ((call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) ? 2 : 0);
64235 #endif
64236 	         ;
64237 	if (flags1 != flags2) {
64238 		DUK_DDD(DUK_DDDPRINT("tail call prevented by incompatible return value handling"));
64239 		return 0;
64240 	}
64241 	DUK_ASSERT(((act->flags & DUK_ACT_FLAG_CONSTRUCT) && (call_flags & DUK_CALL_FLAG_CONSTRUCT)) ||
64242 	           (!(act->flags & DUK_ACT_FLAG_CONSTRUCT) && !(call_flags & DUK_CALL_FLAG_CONSTRUCT)));
64243 	DUK_ASSERT(((act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) && (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY)) ||
64244 	           (!(act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) && !(call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY)));
64245 	if (DUK_HOBJECT_HAS_NOTAIL(func)) {
64246 		/* See: test-bug-tailcall-preventyield-assert.c. */
64247 		DUK_DDD(DUK_DDDPRINT("tail call prevented by function having a notail flag"));
64248 		return 0;
64249 	}
64250 
64251 	/*
64252 	 *  Tailcall handling
64253 	 *
64254 	 *  Although the callstack entry is reused, we need to explicitly unwind
64255 	 *  the current activation (or simulate an unwind).  In particular, the
64256 	 *  current activation must be closed, otherwise something like
64257 	 *  test-bug-reduce-judofyr.js results.  Also catchers need to be unwound
64258 	 *  because there may be non-error-catching label entries in valid tail calls.
64259 	 *
64260 	 *  Special attention is needed for debugger and pause behavior when
64261 	 *  reusing an activation.
64262 	 *    - Disable StepOut processing for the activation unwind because
64263 	 *      we reuse the activation, see:
64264 	 *      https://github.com/svaarala/duktape/issues/1684.
64265 	 *    - Disable line change pause flag permanently if act == dbg_pause_act
64266 	 *      (if set) because it would no longer be relevant, see:
64267 	 *      https://github.com/svaarala/duktape/issues/1726,
64268 	 *      https://github.com/svaarala/duktape/issues/1786.
64269 	 *    - Check for function entry (e.g. StepInto) pause flag here, because
64270 	 *      the executor pause check won't trigger due to shared activation, see:
64271 	 *      https://github.com/svaarala/duktape/issues/1726.
64272 	 */
64273 
64274 	DUK_DDD(DUK_DDDPRINT("is tail call, reusing activation at callstack top, at index %ld",
64275                              (long) (thr->callstack_top - 1)));
64276 
64277 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
64278 	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(func));
64279 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
64280 	DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
64281 	DUK_ASSERT(call_flags & DUK_CALL_FLAG_ALLOW_ECMATOECMA);
64282 
64283 	/* Unwind the topmost callstack entry before reusing it.  This
64284 	 * also unwinds the catchers related to the topmost entry.
64285 	 */
64286 	DUK_ASSERT(thr->callstack_top > 0);
64287 	DUK_ASSERT(thr->callstack_curr != NULL);
64288 #if defined(DUK_USE_DEBUGGER_SUPPORT)
64289 	if (act == thr->heap->dbg_pause_act) {
64290 		thr->heap->dbg_pause_flags &= ~DUK_PAUSE_FLAG_LINE_CHANGE;
64291 	}
64292 
64293 	prev_pause_act = thr->heap->dbg_pause_act;
64294 	thr->heap->dbg_pause_act = NULL;
64295 	if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) {
64296 		DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function entry (tailcall)"));
64297 		duk_debug_set_paused(thr->heap);
64298 	}
64299 #endif
64300 	duk_hthread_activation_unwind_reuse_norz(thr);
64301 #if defined(DUK_USE_DEBUGGER_SUPPORT)
64302 	thr->heap->dbg_pause_act = prev_pause_act;
64303 #endif
64304 	DUK_ASSERT(act == thr->callstack_curr);
64305 
64306 	/* XXX: We could restore the caller's value stack reserve
64307 	 * here, as if we did an actual unwind-and-call.  Without
64308 	 * the restoration, value stack reserve may remain higher
64309 	 * than would otherwise be possible until we return to a
64310 	 * non-tailcall.
64311 	 */
64312 
64313 	/* Then reuse the unwound activation. */
64314 	act->cat = NULL;
64315 	act->var_env = NULL;
64316 	act->lex_env = NULL;
64317 	DUK_ASSERT(func != NULL);
64318 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
64319 	act->func = func;  /* don't want an intermediate exposed state with func == NULL */
64320 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
64321 	act->prev_caller = NULL;
64322 #endif
64323 	/* don't want an intermediate exposed state with invalid pc */
64324 	act->curr_pc = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) func);
64325 #if defined(DUK_USE_DEBUGGER_SUPPORT)
64326 	act->prev_line = 0;
64327 #endif
64328 	DUK_TVAL_SET_OBJECT(&act->tv_func, func);  /* borrowed, no refcount */
64329 	DUK_HOBJECT_INCREF(thr, func);
64330 
64331 	act->flags = DUK_ACT_FLAG_TAILCALLED;
64332 	if (DUK_HOBJECT_HAS_STRICT(func)) {
64333 		act->flags |= DUK_ACT_FLAG_STRICT;
64334 	}
64335 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
64336 		act->flags |= DUK_ACT_FLAG_CONSTRUCT;
64337 	}
64338 #if defined(DUK_USE_ES6_PROXY)
64339 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) {
64340 		act->flags |= DUK_ACT_FLAG_CONSTRUCT_PROXY;
64341 	}
64342 #endif
64343 
64344 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) == func);      /* already updated */
64345 	DUK_ASSERT(act->var_env == NULL);
64346 	DUK_ASSERT(act->lex_env == NULL);
64347 	act->bottom_byteoff = entry_valstack_bottom_byteoff;  /* tail call -> reuse current "frame" */
64348 #if 0
64349 	/* Topmost activation retval_byteoff is considered garbage, no need to init. */
64350 	act->retval_byteoff = 0;
64351 #endif
64352 	/* Filled in when final reserve is known, dummy value doesn't matter
64353 	 * even in error unwind because reserve_byteoff is only used when
64354 	 * returning to -this- activation.
64355 	 */
64356 	act->reserve_byteoff = 0;
64357 
64358 	/*
64359 	 *  Manipulate valstack so that args are on the current bottom and the
64360 	 *  previous caller's 'this' binding (which is the value preceding the
64361 	 *  current bottom) is replaced with the new 'this' binding:
64362 	 *
64363 	 *       [ ... this_old | (crud) func this_new arg1 ... argN ]
64364 	 *  -->  [ ... this_new | arg1 ... argN ]
64365 	 *
64366 	 *  For tail calling to work properly, the valstack bottom must not grow
64367 	 *  here; otherwise crud would accumulate on the valstack.
64368 	 */
64369 
64370 	tv1 = thr->valstack_bottom - 1;
64371 	tv2 = thr->valstack_bottom + idx_func + 1;
64372 	DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);  /* tv1 is -below- valstack_bottom */
64373 	DUK_ASSERT(tv2 >= thr->valstack_bottom && tv2 < thr->valstack_top);
64374 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
64375 
64376 	idx_args = idx_func + 2;
64377 	duk_remove_n(thr, 0, idx_args);  /* may be NORZ */
64378 
64379 	idx_func = 0; DUK_UNREF(idx_func);  /* really 'not applicable' anymore, should not be referenced after this */
64380 	idx_args = 0;
64381 
64382 	*out_nargs = ((duk_hcompfunc *) func)->nargs;
64383 	*out_nregs = ((duk_hcompfunc *) func)->nregs;
64384 	DUK_ASSERT(*out_nregs >= 0);
64385 	DUK_ASSERT(*out_nregs >= *out_nargs);
64386 	*out_vs_min_bytes = entry_valstack_bottom_byteoff + sizeof(duk_tval) * ((duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);
64387 
64388 
64389 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
64390 #if defined(DUK_USE_TAILCALL)
64391 #error incorrect options: tail calls enabled with function caller property
64392 #endif
64393 	/* XXX: This doesn't actually work properly for tail calls, so
64394 	 * tail calls are disabled when DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
64395 	 * is in use.
64396 	 */
64397 	duk__update_func_caller_prop(thr, func);
64398 #endif
64399 
64400 	/* [ ... this_new | arg1 ... argN ] */
64401 
64402 	return 1;
64403 }
64404 #endif  /* DUK_USE_TAILCALL */
64405 
64406 DUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr,
64407                                                 duk_small_uint_t call_flags,
64408                                                 duk_idx_t idx_func,
64409                                                 duk_hobject *func,
64410                                                 duk_size_t entry_valstack_bottom_byteoff,
64411                                                 duk_size_t entry_valstack_end_byteoff,
64412                                                 duk_idx_t *out_nargs,
64413                                                 duk_idx_t *out_nregs,
64414                                                 duk_size_t *out_vs_min_bytes,
64415                                                 duk_activation **out_act) {
64416 	duk_activation *act;
64417 	duk_activation *new_act;
64418 
64419 	DUK_UNREF(entry_valstack_end_byteoff);
64420 
64421 	DUK_DDD(DUK_DDDPRINT("not a tail call, pushing a new activation to callstack, to index %ld",
64422 	                     (long) (thr->callstack_top)));
64423 
64424 	duk__call_callstack_limit_check(thr);
64425 	new_act = duk_hthread_activation_alloc(thr);
64426 	DUK_ASSERT(new_act != NULL);
64427 
64428 	act = thr->callstack_curr;
64429 	if (act != NULL) {
64430 		/*
64431 		 *  Update return value stack index of current activation (if any).
64432 		 *
64433 		 *  Although it might seem this is not necessary (bytecode executor
64434 		 *  does this for ECMAScript-to-ECMAScript calls; other calls are
64435 		 *  handled here), this turns out to be necessary for handling yield
64436 		 *  and resume.  For them, an ECMAScript-to-native call happens, and
64437 		 *  the ECMAScript call's retval_byteoff must be set for things to work.
64438 		 */
64439 
64440 		act->retval_byteoff = entry_valstack_bottom_byteoff + (duk_size_t) idx_func * sizeof(duk_tval);
64441 	}
64442 
64443 	new_act->parent = act;
64444 	thr->callstack_curr = new_act;
64445 	thr->callstack_top++;
64446 	act = new_act;
64447 	*out_act = act;
64448 
64449 	DUK_ASSERT(thr->valstack_top > thr->valstack_bottom);  /* at least effective 'this' */
64450 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
64451 
64452 	act->cat = NULL;
64453 
64454 	act->flags = 0;
64455 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
64456 		act->flags |= DUK_ACT_FLAG_CONSTRUCT;
64457 	}
64458 #if defined(DUK_USE_ES6_PROXY)
64459 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) {
64460 		act->flags |= DUK_ACT_FLAG_CONSTRUCT_PROXY;
64461 	}
64462 #endif
64463 	if (call_flags & DUK_CALL_FLAG_DIRECT_EVAL) {
64464 		act->flags |= DUK_ACT_FLAG_DIRECT_EVAL;
64465 	}
64466 
64467 	/* start of arguments: idx_func + 2. */
64468 	act->func = func;  /* NULL for lightfunc */
64469 	if (DUK_LIKELY(func != NULL)) {
64470 		DUK_TVAL_SET_OBJECT(&act->tv_func, func);  /* borrowed, no refcount */
64471 		if (DUK_HOBJECT_HAS_STRICT(func)) {
64472 			act->flags |= DUK_ACT_FLAG_STRICT;
64473 		}
64474 		if (DUK_HOBJECT_IS_COMPFUNC(func)) {
64475 			*out_nargs = ((duk_hcompfunc *) func)->nargs;
64476 			*out_nregs = ((duk_hcompfunc *) func)->nregs;
64477 			DUK_ASSERT(*out_nregs >= 0);
64478 			DUK_ASSERT(*out_nregs >= *out_nargs);
64479 			*out_vs_min_bytes = entry_valstack_bottom_byteoff +
64480 				sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);
64481 		} else {
64482 			/* True because of call target lookup checks. */
64483 			DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(func));
64484 
64485 			*out_nargs = ((duk_hnatfunc *) func)->nargs;
64486 			*out_nregs = *out_nargs;
64487 			if (*out_nargs >= 0) {
64488 				*out_vs_min_bytes = entry_valstack_bottom_byteoff +
64489 					sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs + DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
64490 			} else {
64491 				/* Vararg function. */
64492 				duk_size_t valstack_top_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));
64493 				*out_vs_min_bytes = valstack_top_byteoff +
64494 					sizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
64495 			}
64496 		}
64497 	} else {
64498 		duk_small_uint_t lf_flags;
64499 		duk_tval *tv_func;
64500 
64501 		act->flags |= DUK_ACT_FLAG_STRICT;
64502 
64503 		tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
64504 		DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func));
64505 		DUK_TVAL_SET_TVAL(&act->tv_func, tv_func);  /* borrowed, no refcount */
64506 
64507 		lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_func);
64508 		*out_nargs = DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
64509 		if (*out_nargs != DUK_LFUNC_NARGS_VARARGS) {
64510 			*out_vs_min_bytes = entry_valstack_bottom_byteoff +
64511 				sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nargs + DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
64512 		} else {
64513 			duk_size_t valstack_top_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));
64514 			*out_vs_min_bytes = valstack_top_byteoff +
64515 				sizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
64516 			*out_nargs = -1;  /* vararg */
64517 		}
64518 		*out_nregs = *out_nargs;
64519 	}
64520 
64521 	act->var_env = NULL;
64522 	act->lex_env = NULL;
64523 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
64524 	act->prev_caller = NULL;
64525 #endif
64526 	act->curr_pc = NULL;
64527 #if defined(DUK_USE_DEBUGGER_SUPPORT)
64528 	act->prev_line = 0;
64529 #endif
64530 	act->bottom_byteoff = entry_valstack_bottom_byteoff + sizeof(duk_tval) * ((duk_size_t) idx_func + 2U);
64531 #if 0
64532 	act->retval_byteoff = 0;   /* topmost activation retval_byteoff is considered garbage, no need to init */
64533 #endif
64534 	/* Filled in when final reserve is known, dummy value doesn't matter
64535 	 * even in error unwind because reserve_byteoff is only used when
64536 	 * returning to -this- activation.
64537 	 */
64538 	act->reserve_byteoff = 0;  /* filled in by caller */
64539 
64540 	/* XXX: Is this INCREF necessary? 'func' is always a borrowed
64541 	 * reference reachable through the value stack?  If changed, stack
64542 	 * unwind code also needs to be fixed to match.
64543 	 */
64544 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, func);  /* act->func */
64545 
64546 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
64547 	if (func) {
64548 		duk__update_func_caller_prop(thr, func);
64549 	}
64550 #endif
64551 }
64552 
64553 /*
64554  *  Environment setup.
64555  */
64556 
64557 DUK_LOCAL void duk__call_env_setup(duk_hthread *thr, duk_hobject *func, duk_activation *act, duk_idx_t idx_args) {
64558 	duk_hobject *env;
64559 
64560 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound function has already been resolved */
64561 
64562 	if (DUK_LIKELY(func != NULL)) {
64563 		if (DUK_LIKELY(DUK_HOBJECT_HAS_NEWENV(func))) {
64564 			DUK_STATS_INC(thr->heap, stats_envrec_newenv);
64565 			if (DUK_LIKELY(!DUK_HOBJECT_HAS_CREATEARGS(func))) {
64566 				/* Use a new environment but there's no 'arguments' object;
64567 				 * delayed environment initialization.  This is the most
64568 				 * common case.
64569 				 */
64570 				DUK_ASSERT(act->lex_env == NULL);
64571 				DUK_ASSERT(act->var_env == NULL);
64572 			} else {
64573 				/* Use a new environment and there's an 'arguments' object.
64574 				 * We need to initialize it right now.
64575 				 */
64576 
64577 				/* third arg: absolute index (to entire valstack) of bottom_byteoff of new activation */
64578 				env = duk_create_activation_environment_record(thr, func, act->bottom_byteoff);
64579 				DUK_ASSERT(env != NULL);
64580 
64581 				/* [ ... func this arg1 ... argN envobj ] */
64582 
64583 				DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
64584 				duk__handle_createargs_for_call(thr, func, env, idx_args);
64585 
64586 				/* [ ... func this arg1 ... argN envobj ] */
64587 
64588 				act->lex_env = env;
64589 				act->var_env = env;
64590 				DUK_HOBJECT_INCREF(thr, env);
64591 				DUK_HOBJECT_INCREF(thr, env);  /* XXX: incref by count (2) directly */
64592 				duk_pop(thr);
64593 			}
64594 		} else {
64595 			/* Use existing env (e.g. for non-strict eval); cannot have
64596 			 * an own 'arguments' object (but can refer to an existing one).
64597 			 */
64598 
64599 			DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
64600 
64601 			DUK_STATS_INC(thr->heap, stats_envrec_oldenv);
64602 			duk__handle_oldenv_for_call(thr, func, act);
64603 
64604 			DUK_ASSERT(act->lex_env != NULL);
64605 			DUK_ASSERT(act->var_env != NULL);
64606 		}
64607 	} else {
64608 		/* Lightfuncs are always native functions and have "newenv". */
64609 		DUK_ASSERT(act->lex_env == NULL);
64610 		DUK_ASSERT(act->var_env == NULL);
64611 		DUK_STATS_INC(thr->heap, stats_envrec_newenv);
64612 	}
64613 }
64614 
64615 /*
64616  *  Misc shared helpers.
64617  */
64618 
64619 /* Check thread state, update current thread. */
64620 DUK_LOCAL void duk__call_thread_state_update(duk_hthread *thr) {
64621 	DUK_ASSERT(thr != NULL);
64622 
64623 	if (DUK_LIKELY(thr == thr->heap->curr_thread)) {
64624 		if (DUK_UNLIKELY(thr->state != DUK_HTHREAD_STATE_RUNNING)) {
64625 			/* Should actually never happen, but check anyway. */
64626 			goto thread_state_error;
64627 		}
64628 	} else {
64629 		DUK_ASSERT(thr->heap->curr_thread == NULL ||
64630 		           thr->heap->curr_thread->state == DUK_HTHREAD_STATE_RUNNING);
64631 		if (DUK_UNLIKELY(thr->state != DUK_HTHREAD_STATE_INACTIVE)) {
64632 			goto thread_state_error;
64633 		}
64634 		DUK_HEAP_SWITCH_THREAD(thr->heap, thr);
64635 		thr->state = DUK_HTHREAD_STATE_RUNNING;
64636 
64637 		/* Multiple threads may be simultaneously in the RUNNING
64638 		 * state, but not in the same "resume chain".
64639 		 */
64640 	}
64641 	DUK_ASSERT(thr->heap->curr_thread == thr);
64642 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
64643 	return;
64644 
64645  thread_state_error:
64646 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "invalid thread state (%ld)", (long) thr->state);
64647 	DUK_WO_NORETURN(return;);
64648 }
64649 
64650 /*
64651  *  Main unprotected call handler, handles:
64652  *
64653  *    - All combinations of native/ECMAScript caller and native/ECMAScript
64654  *      target.
64655  *
64656  *    - Optimized ECMAScript-to-ECMAScript call where call handling only
64657  *      sets up a new duk_activation but reuses an existing bytecode executor
64658  *      (the caller) without native recursion.
64659  *
64660  *    - Tailcalls, where an activation is reused without increasing call
64661  *      stack (duk_activation) depth.
64662  *
64663  *    - Setup for an initial Duktape.Thread.resume().
64664  *
64665  *  The call handler doesn't provide any protection guarantees, protected calls
64666  *  must be implemented e.g. by wrapping the call in a duk_safe_call().
64667  *  Call setup may fail at any stage, even when the new activation is in
64668  *  place; the only guarantee is that the state is consistent for unwinding.
64669  */
64670 
64671 DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
64672                                          duk_idx_t idx_func,
64673                                          duk_small_uint_t call_flags) {
64674 #if defined(DUK_USE_ASSERTIONS)
64675 	duk_activation *entry_act;
64676 	duk_size_t entry_callstack_top;
64677 #endif
64678 	duk_size_t entry_valstack_bottom_byteoff;
64679 	duk_size_t entry_valstack_end_byteoff;
64680 	duk_int_t entry_call_recursion_depth;
64681 	duk_hthread *entry_curr_thread;
64682 	duk_uint_fast8_t entry_thread_state;
64683 	duk_instr_t **entry_ptr_curr_pc;
64684 	duk_idx_t idx_args;
64685 	duk_idx_t nargs;            /* # argument registers target function wants (< 0 => "as is") */
64686 	duk_idx_t nregs;            /* # total registers target function wants on entry (< 0 => "as is") */
64687 	duk_size_t vs_min_bytes;    /* minimum value stack size (bytes) for handling call */
64688 	duk_hobject *func;          /* 'func' on stack (borrowed reference) */
64689 	duk_activation *act;
64690 	duk_ret_t rc;
64691 	duk_small_uint_t use_tailcall;
64692 
64693 	DUK_ASSERT(thr != NULL);
64694 	DUK_ASSERT(thr->heap != NULL);
64695 	/* Asserts for heap->curr_thread omitted: it may be NULL, 'thr', or
64696 	 * any other thread (e.g. when heap thread is used to run finalizers).
64697 	 */
64698 	DUK_CTX_ASSERT_VALID(thr);
64699 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
64700 	DUK_ASSERT(idx_func >= 0);
64701 
64702 	DUK_STATS_INC(thr->heap, stats_call_all);
64703 
64704 	/* If a tail call:
64705 	 *   - an ECMAScript activation must be on top of the callstack
64706 	 *   - there cannot be any catch stack entries that would catch
64707 	 *     a return
64708 	 */
64709 #if defined(DUK_USE_ASSERTIONS)
64710 	if (call_flags & DUK_CALL_FLAG_TAILCALL) {
64711 		duk_activation *tmp_act;
64712 		duk_catcher *tmp_cat;
64713 
64714 		DUK_ASSERT(thr->callstack_top >= 1);
64715 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
64716 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
64717 
64718 		/* No entry in the catch stack which would actually catch a
64719 		 * throw can refer to the callstack entry being reused.
64720 		 * There *can* be catch stack entries referring to the current
64721 		 * callstack entry as long as they don't catch (e.g. label sites).
64722 		 */
64723 
64724 		tmp_act = thr->callstack_curr;
64725 		for (tmp_cat = tmp_act->cat; tmp_cat != NULL; tmp_cat = tmp_cat->parent) {
64726 			DUK_ASSERT(DUK_CAT_GET_TYPE(tmp_cat) == DUK_CAT_TYPE_LABEL); /* a non-catching entry */
64727 		}
64728 	}
64729 #endif  /* DUK_USE_ASSERTIONS */
64730 
64731 	/*
64732 	 *  Store entry state.
64733 	 */
64734 
64735 #if defined(DUK_USE_ASSERTIONS)
64736 	entry_act = thr->callstack_curr;
64737 	entry_callstack_top = thr->callstack_top;
64738 #endif
64739 	entry_valstack_bottom_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
64740 	entry_valstack_end_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
64741 	entry_call_recursion_depth = thr->heap->call_recursion_depth;
64742 	entry_curr_thread = thr->heap->curr_thread;  /* may be NULL if first call */
64743 	entry_thread_state = thr->state;
64744 	entry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */
64745 
64746 	/* If thr->ptr_curr_pc is set, sync curr_pc to act->pc.  Then NULL
64747 	 * thr->ptr_curr_pc so that it's not accidentally used with an incorrect
64748 	 * activation when side effects occur.
64749 	 */
64750 	duk_hthread_sync_and_null_currpc(thr);
64751 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
64752 
64753 	DUK_DD(DUK_DDPRINT("duk__handle_call_raw: thr=%p, idx_func=%ld, "
64754 	                   "call_flags=0x%08lx (constructor=%ld), "
64755 	                   "valstack_top=%ld, idx_func=%ld, idx_args=%ld, rec_depth=%ld/%ld, "
64756 	                   "entry_valstack_bottom_byteoff=%ld, entry_valstack_end_byteoff=%ld, "
64757 	                   "entry_call_recursion_depth=%ld, "
64758 	                   "entry_curr_thread=%p, entry_thread_state=%ld",
64759 	                   (void *) thr,
64760 	                   (long) idx_func,
64761 	                   (unsigned long) call_flags,
64762 	                   (long) ((call_flags & DUK_CALL_FLAG_CONSTRUCT) != 0 ? 1 : 0),
64763 	                   (long) duk_get_top(thr),
64764 	                   (long) idx_func,
64765 	                   (long) (idx_func + 2),
64766 	                   (long) thr->heap->call_recursion_depth,
64767 	                   (long) thr->heap->call_recursion_limit,
64768 	                   (long) entry_valstack_bottom_byteoff,
64769 	                   (long) entry_valstack_end_byteoff,
64770 	                   (long) entry_call_recursion_depth,
64771 	                   (void *) entry_curr_thread,
64772 	                   (long) entry_thread_state));
64773 
64774 	/*
64775 	 *  Thread state check and book-keeping.
64776 	 */
64777 
64778 	duk__call_thread_state_update(thr);
64779 
64780 	/*
64781 	 *  Increase call recursion depth as early as possible so that if we
64782 	 *  enter a recursive call for any reason there's a backstop to native
64783 	 *  recursion.  This can happen e.g. for almost any property read
64784 	 *  because it may cause a getter call or a Proxy trap (GC and finalizers
64785 	 *  are not an issue because they are not recursive).  If we end up
64786 	 *  doing an Ecma-to-Ecma call, revert the increase.  (See GH-2032.)
64787 	 *
64788 	 *  For similar reasons, ensure there is a known value stack spare
64789 	 *  even before we actually prepare the value stack for the target
64790 	 *  function.  If this isn't done, early recursion may consume the
64791 	 *  value stack space.
64792 	 *
64793 	 *  XXX: Should bump yield preventcount early, for the same reason.
64794 	 */
64795 
64796 	duk__call_c_recursion_limit_check(thr);
64797 	thr->heap->call_recursion_depth++;
64798 	duk_require_stack(thr, DUK__CALL_HANDLING_REQUIRE_STACK);
64799 
64800 	/*
64801 	 *  Resolve final target function; handle bound functions and special
64802 	 *  functions like .call() and .apply().  Also figure out the effective
64803 	 *  'this' binding, which replaces the current value at idx_func + 1.
64804 	 */
64805 
64806 	if (DUK_LIKELY(duk__resolve_target_fastpath_check(thr, idx_func, &func, call_flags) != 0U)) {
64807 		DUK_DDD(DUK_DDDPRINT("fast path target resolve"));
64808 	} else {
64809 		DUK_DDD(DUK_DDDPRINT("slow path target resolve"));
64810 		func = duk__resolve_target_func_and_this_binding(thr, idx_func, &call_flags);
64811 	}
64812 	DUK_ASSERT(duk_get_top(thr) - idx_func >= 2);  /* at least func and this present */
64813 
64814 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
64815 	DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) ||
64816 	                            DUK_HOBJECT_IS_NATFUNC(func)));
64817 
64818 	/* [ ... func this arg1 ... argN ] */
64819 
64820 	/*
64821 	 *  Setup a preliminary activation and figure out nargs/nregs and
64822 	 *  value stack minimum size.
64823 	 *
64824 	 *  Don't touch valstack_bottom or valstack_top yet so that Duktape API
64825 	 *  calls work normally.
64826 	 *
64827 	 *  Because 'act' is not zeroed, all fields must be filled in.
64828 	 */
64829 
64830 	/* Should not be necessary, but initialize to silence warnings. */
64831 	act = NULL;
64832 	nargs = 0;
64833 	nregs = 0;
64834 	vs_min_bytes = 0;
64835 
64836 #if defined(DUK_USE_TAILCALL)
64837 	use_tailcall = (call_flags & DUK_CALL_FLAG_TAILCALL);
64838 	if (use_tailcall) {
64839 		use_tailcall = duk__call_setup_act_attempt_tailcall(thr,
64840 		                                                    call_flags,
64841 		                                                    idx_func,
64842 		                                                    func,
64843 		                                                    entry_valstack_bottom_byteoff,
64844 		                                                    entry_valstack_end_byteoff,
64845 		                                                    &nargs,
64846 		                                                    &nregs,
64847 		                                                    &vs_min_bytes,
64848 		                                                    &act);
64849 	}
64850 #else
64851 	DUK_ASSERT((call_flags & DUK_CALL_FLAG_TAILCALL) == 0);  /* compiler ensures this */
64852 	use_tailcall = 0;
64853 #endif
64854 
64855 	if (use_tailcall) {
64856 		idx_args = 0;
64857 		DUK_STATS_INC(thr->heap, stats_call_tailcall);
64858 	} else {
64859 		duk__call_setup_act_not_tailcall(thr,
64860 		                                 call_flags,
64861 		                                 idx_func,
64862 		                                 func,
64863 		                                 entry_valstack_bottom_byteoff,
64864 		                                 entry_valstack_end_byteoff,
64865 		                                 &nargs,
64866 		                                 &nregs,
64867 		                                 &vs_min_bytes,
64868 		                                 &act);
64869 		idx_args = idx_func + 2;
64870 	}
64871 	/* After this point idx_func is no longer valid for tailcalls. */
64872 
64873 	DUK_ASSERT(act != NULL);
64874 
64875 	/* [ ... func this arg1 ... argN ] */
64876 
64877 	/*
64878 	 *  Environment record creation and 'arguments' object creation.
64879 	 *  Named function expression name binding is handled by the
64880 	 *  compiler; the compiled function's parent env will contain
64881 	 *  the (immutable) binding already.
64882 	 *
64883 	 *  This handling is now identical for C and ECMAScript functions.
64884 	 *  C functions always have the 'NEWENV' flag set, so their
64885 	 *  environment record initialization is delayed (which is good).
64886 	 *
64887 	 *  Delayed creation (on demand) is handled in duk_js_var.c.
64888 	 */
64889 
64890 	duk__call_env_setup(thr, func, act, idx_args);
64891 
64892 	/* [ ... func this arg1 ... argN ] */
64893 
64894 	/*
64895 	 *  Setup value stack: clamp to 'nargs', fill up to 'nregs',
64896 	 *  ensure value stack size matches target requirements, and
64897 	 *  switch value stack bottom.  Valstack top is kept.
64898 	 *
64899 	 *  Value stack can only grow here.
64900 	 */
64901 
64902 	duk_valstack_grow_check_throw(thr, vs_min_bytes);
64903 	act->reserve_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
64904 
64905 	if (use_tailcall) {
64906 		DUK_ASSERT(nregs >= 0);
64907 		DUK_ASSERT(nregs >= nargs);
64908 		duk_set_top_and_wipe(thr, nregs, nargs);
64909 	} else {
64910 		if (nregs >= 0) {
64911 			DUK_ASSERT(nregs >= nargs);
64912 			duk_set_top_and_wipe(thr, idx_func + 2 + nregs, idx_func + 2 + nargs);
64913 		} else {
64914 			;
64915 		}
64916 		thr->valstack_bottom = thr->valstack_bottom + idx_func + 2;
64917 	}
64918 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
64919 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
64920 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
64921 
64922 	/*
64923 	 *  Make the actual call.  For Ecma-to-Ecma calls detect that
64924 	 *  setup is complete, then return with a status code that allows
64925 	 *  the caller to reuse the running executor.
64926 	 */
64927 
64928 	if (func != NULL && DUK_HOBJECT_IS_COMPFUNC(func)) {
64929 		/*
64930 		 *  ECMAScript call.
64931 		 */
64932 
64933 		DUK_ASSERT(func != NULL);
64934 		DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
64935 		act->curr_pc = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) func);
64936 
64937 		if (call_flags & DUK_CALL_FLAG_ALLOW_ECMATOECMA) {
64938 			DUK_DD(DUK_DDPRINT("avoid native call, use existing executor"));
64939 			DUK_STATS_INC(thr->heap, stats_call_ecmatoecma);
64940 			DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
64941 			DUK_REFZERO_CHECK_FAST(thr);
64942 			DUK_ASSERT(thr->ptr_curr_pc == NULL);
64943 			thr->heap->call_recursion_depth--;  /* No recursion increase for this case. */
64944 			return 1;  /* 1=reuse executor */
64945 		}
64946 		DUK_ASSERT(use_tailcall == 0);
64947 
64948 		/* duk_hthread_activation_unwind_norz() will decrease this on unwind */
64949 		DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
64950 		act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;
64951 		thr->callstack_preventcount++;
64952 
64953 		/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
64954 
64955 		/*
64956 		 *  Bytecode executor call.
64957 		 *
64958 		 *  Execute bytecode, handling any recursive function calls and
64959 		 *  thread resumptions.  Returns when execution would return from
64960 		 *  the entry level activation.  When the executor returns, a
64961 		 *  single return value is left on the stack top.
64962 		 *
64963 		 *  The only possible longjmp() is an error (DUK_LJ_TYPE_THROW),
64964 		 *  other types are handled internally by the executor.
64965 		 */
64966 
64967 		/* thr->ptr_curr_pc is set by bytecode executor early on entry */
64968 		DUK_ASSERT(thr->ptr_curr_pc == NULL);
64969 		DUK_DDD(DUK_DDDPRINT("entering bytecode execution"));
64970 		duk_js_execute_bytecode(thr);
64971 		DUK_DDD(DUK_DDDPRINT("returned from bytecode execution"));
64972 	} else {
64973 		/*
64974 		 *  Native call.
64975 		 */
64976 
64977 		DUK_ASSERT(func == NULL || ((duk_hnatfunc *) func)->func != NULL);
64978 		DUK_ASSERT(use_tailcall == 0);
64979 
64980 		/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
64981 
64982 		/* duk_hthread_activation_unwind_norz() will decrease this on unwind */
64983 		DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
64984 		act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;
64985 		thr->callstack_preventcount++;
64986 
64987 		/* For native calls must be NULL so we don't sync back */
64988 		DUK_ASSERT(thr->ptr_curr_pc == NULL);
64989 
64990 		/* XXX: native funcptr could come out of call setup. */
64991 		if (func) {
64992 			rc = ((duk_hnatfunc *) func)->func(thr);
64993 		} else {
64994 			duk_tval *tv_func;
64995 			duk_c_function funcptr;
64996 
64997 			tv_func = &act->tv_func;
64998 			DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func));
64999 			funcptr = DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv_func);
65000 			rc = funcptr(thr);
65001 		}
65002 
65003 		/* Automatic error throwing, retval check. */
65004 
65005 		if (rc == 0) {
65006 			DUK_ASSERT(thr->valstack < thr->valstack_end);
65007 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
65008 			thr->valstack_top++;
65009 		} else if (rc == 1) {
65010 			;
65011 		} else if (rc < 0) {
65012 			duk_error_throw_from_negative_rc(thr, rc);
65013 			DUK_WO_NORETURN(return 0;);
65014 		} else {
65015 			DUK_ERROR_TYPE(thr, DUK_STR_INVALID_CFUNC_RC);
65016 			DUK_WO_NORETURN(return 0;);
65017 		}
65018 	}
65019 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
65020 	DUK_ASSERT(use_tailcall == 0);
65021 
65022 	/*
65023 	 *  Constructor call post processing.
65024 	 */
65025 
65026 #if defined(DUK_USE_ES6_PROXY)
65027 	if (call_flags & (DUK_CALL_FLAG_CONSTRUCT | DUK_CALL_FLAG_CONSTRUCT_PROXY)) {
65028 		duk_call_construct_postprocess(thr, call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY);
65029 	}
65030 #else
65031 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
65032 		duk_call_construct_postprocess(thr, 0);
65033 	}
65034 #endif
65035 
65036 	/*
65037 	 *  Unwind, restore valstack bottom and other book-keeping.
65038 	 */
65039 
65040 	DUK_ASSERT(thr->callstack_curr != NULL);
65041 	DUK_ASSERT(thr->callstack_curr->parent == entry_act);
65042 	DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
65043 	duk_hthread_activation_unwind_norz(thr);
65044 	DUK_ASSERT(thr->callstack_curr == entry_act);
65045 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
65046 
65047 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_bottom_byteoff);
65048 	/* keep current valstack_top */
65049 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
65050 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
65051 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
65052 	DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);
65053 
65054 	/* Return value handling. */
65055 
65056 	/* [ ... func this (crud) retval ] */
65057 
65058 	{
65059 		duk_tval *tv_ret;
65060 		duk_tval *tv_funret;
65061 
65062 		tv_ret = thr->valstack_bottom + idx_func;
65063 		tv_funret = thr->valstack_top - 1;
65064 #if defined(DUK_USE_FASTINT)
65065 		/* Explicit check for fastint downgrade. */
65066 		DUK_TVAL_CHKFAST_INPLACE_FAST(tv_funret);
65067 #endif
65068 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret);  /* side effects */
65069 	}
65070 
65071 	duk_set_top_unsafe(thr, idx_func + 1);
65072 
65073 	/* [ ... retval ] */
65074 
65075 	/* Restore caller's value stack reserve (cannot fail). */
65076 	DUK_ASSERT((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff >= (duk_uint8_t *) thr->valstack_top);
65077 	DUK_ASSERT((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff <= (duk_uint8_t *) thr->valstack_alloc_end);
65078 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff);
65079 
65080 	/* XXX: Trial value stack shrink would be OK here, but we'd need
65081 	 * to prevent side effects of the potential realloc.
65082 	 */
65083 
65084 	/* Restore entry thread executor curr_pc stack frame pointer. */
65085 	thr->ptr_curr_pc = entry_ptr_curr_pc;
65086 
65087 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
65088 	thr->state = (duk_uint8_t) entry_thread_state;
65089 
65090 	/* Disabled assert: triggered with some torture tests. */
65091 #if 0
65092 	DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) ||  /* first call */
65093 	           (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) ||  /* other call */
65094 	           (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr));     /* current thread */
65095 #endif
65096 
65097 	thr->heap->call_recursion_depth = entry_call_recursion_depth;
65098 
65099 	/* If the debugger is active we need to force an interrupt so that
65100 	 * debugger breakpoints are rechecked.  This is important for function
65101 	 * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see
65102 	 * GH-303.  Only needed for success path, error path always causes a
65103 	 * breakpoint recheck in the executor.  It would be enough to set this
65104 	 * only when returning to an ECMAScript activation, but setting the flag
65105 	 * on every return should have no ill effect.
65106 	 */
65107 #if defined(DUK_USE_DEBUGGER_SUPPORT)
65108 	if (duk_debug_is_attached(thr->heap)) {
65109 		DUK_DD(DUK_DDPRINT("returning with debugger enabled, force interrupt"));
65110 		DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
65111 		thr->interrupt_init -= thr->interrupt_counter;
65112 		thr->interrupt_counter = 0;
65113 		thr->heap->dbg_force_restart = 1;
65114 	}
65115 #endif
65116 
65117 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
65118 	duk__interrupt_fixup(thr, entry_curr_thread);
65119 #endif
65120 
65121 	/* Restored by success path. */
65122 	DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
65123 	DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
65124 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
65125 
65126 	DUK_REFZERO_CHECK_FAST(thr);
65127 
65128 	return 0;  /* 0=call handled inline */
65129 }
65130 
65131 DUK_INTERNAL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr,
65132                                                          duk_idx_t nargs,
65133                                                          duk_small_uint_t call_flags) {
65134 	duk_idx_t idx_func;
65135 	DUK_ASSERT(duk_get_top(thr) >= nargs + 2);
65136 	idx_func = duk_get_top(thr) - (nargs + 2);
65137 	DUK_ASSERT(idx_func >= 0);
65138 	return duk_handle_call_unprotected(thr, idx_func, call_flags);
65139 }
65140 
65141 DUK_INTERNAL duk_int_t duk_handle_call_unprotected(duk_hthread *thr,
65142                                                    duk_idx_t idx_func,
65143                                                    duk_small_uint_t call_flags) {
65144 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
65145 	DUK_ASSERT(idx_func >= 0);
65146 	return duk__handle_call_raw(thr, idx_func, call_flags);
65147 }
65148 
65149 /*
65150  *  duk_handle_safe_call(): make a "C protected call" within the
65151  *  current activation.
65152  *
65153  *  The allowed thread states for making a call are the same as for
65154  *  duk_handle_call_protected().
65155  *
65156  *  Even though this call is protected, errors are thrown for insane arguments
65157  *  and may result in a fatal error unless there's another protected call which
65158  *  catches such errors.
65159  *
65160  *  The error handling path should be error free, even for out-of-memory
65161  *  errors, to ensure safe sandboxing.  (As of Duktape 2.2.0 this is not
65162  *  yet the case for environment closing which may run out of memory, see
65163  *  XXX notes below.)
65164  */
65165 
65166 DUK_LOCAL void duk__handle_safe_call_inner(duk_hthread *thr,
65167                                            duk_safe_call_function func,
65168                                            void *udata,
65169 #if defined(DUK_USE_ASSERTIONS)
65170                                            duk_size_t entry_valstack_bottom_byteoff,
65171                                            duk_size_t entry_callstack_top,
65172 #endif
65173                                            duk_hthread *entry_curr_thread,
65174                                            duk_uint_fast8_t entry_thread_state,
65175                                            duk_idx_t idx_retbase,
65176                                            duk_idx_t num_stack_rets) {
65177 	duk_ret_t rc;
65178 
65179 	DUK_ASSERT(thr != NULL);
65180 	DUK_CTX_ASSERT_VALID(thr);
65181 
65182 	/*
65183 	 *  Thread state check and book-keeping.
65184 	 */
65185 
65186 	duk__call_thread_state_update(thr);
65187 
65188 	/*
65189 	 *  Recursion limit check.
65190 	 */
65191 
65192 	duk__call_c_recursion_limit_check(thr);
65193 	thr->heap->call_recursion_depth++;
65194 
65195 	/*
65196 	 *  Make the C call.
65197 	 */
65198 
65199 	rc = func(thr, udata);
65200 
65201 	DUK_DDD(DUK_DDDPRINT("safe_call, func rc=%ld", (long) rc));
65202 
65203 	/*
65204 	 *  Valstack manipulation for results.
65205 	 */
65206 
65207 	/* we're running inside the caller's activation, so no change in call/catch stack or valstack bottom */
65208 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
65209 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
65210 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) == entry_valstack_bottom_byteoff);
65211 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
65212 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
65213 
65214 	if (DUK_UNLIKELY(rc < 0)) {
65215 		duk_error_throw_from_negative_rc(thr, rc);
65216 		DUK_WO_NORETURN(return;);
65217 	}
65218 	DUK_ASSERT(rc >= 0);
65219 
65220 	duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, rc);  /* throws for insane rc */
65221 
65222 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
65223 	thr->state = (duk_uint8_t) entry_thread_state;
65224 }
65225 
65226 DUK_LOCAL void duk__handle_safe_call_error(duk_hthread *thr,
65227                                            duk_activation *entry_act,
65228 #if defined(DUK_USE_ASSERTIONS)
65229                                            duk_size_t entry_callstack_top,
65230 #endif
65231                                            duk_hthread *entry_curr_thread,
65232                                            duk_uint_fast8_t entry_thread_state,
65233                                            duk_idx_t idx_retbase,
65234                                            duk_idx_t num_stack_rets,
65235                                            duk_size_t entry_valstack_bottom_byteoff,
65236                                            duk_jmpbuf *old_jmpbuf_ptr) {
65237 	DUK_ASSERT(thr != NULL);
65238 	DUK_CTX_ASSERT_VALID(thr);
65239 
65240 	/*
65241 	 *  Error during call.  The error value is at heap->lj.value1.
65242 	 *
65243 	 *  The very first thing we do is restore the previous setjmp catcher.
65244 	 *  This means that any error in error handling will propagate outwards
65245 	 *  instead of causing a setjmp() re-entry above.
65246 	 */
65247 
65248 	DUK_DDD(DUK_DDDPRINT("error caught during protected duk_handle_safe_call()"));
65249 
65250 	/* Other longjmp types are handled by executor before propagating
65251 	 * the error here.
65252 	 */
65253 	DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);
65254 	DUK_ASSERT_LJSTATE_SET(thr->heap);
65255 
65256 	/* Either pointer may be NULL (at entry), so don't assert. */
65257 	thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
65258 
65259 	/* XXX: callstack unwind may now throw an error when closing
65260 	 * scopes; this is a sandboxing issue, described in:
65261 	 * https://github.com/svaarala/duktape/issues/476
65262 	 */
65263 	/* XXX: "unwind to" primitive? */
65264 
65265 	DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
65266 	while (thr->callstack_curr != entry_act) {
65267 		DUK_ASSERT(thr->callstack_curr != NULL);
65268 		duk_hthread_activation_unwind_norz(thr);
65269 	}
65270 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
65271 
65272 	/* Switch active thread before any side effects to avoid a
65273 	 * dangling curr_thread pointer.
65274 	 */
65275 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
65276 	thr->state = (duk_uint8_t) entry_thread_state;
65277 
65278 	DUK_ASSERT(thr->heap->curr_thread == entry_curr_thread);
65279 	DUK_ASSERT(thr->state == entry_thread_state);
65280 
65281 	/* Restore valstack bottom. */
65282 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_bottom_byteoff);
65283 
65284 	/* [ ... | (crud) ] */
65285 
65286 	/* XXX: ensure space in valstack (now relies on internal reserve)? */
65287 	duk_push_tval(thr, &thr->heap->lj.value1);
65288 
65289 	/* [ ... | (crud) errobj ] */
65290 
65291 	DUK_ASSERT(duk_get_top(thr) >= 1);  /* at least errobj must be on stack */
65292 
65293 	duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, 1);  /* 1 = num actual 'return values' */
65294 
65295 	/* [ ... | ] or [ ... | errobj (M * undefined)] where M = num_stack_rets - 1 */
65296 
65297 	/* Reset longjmp state. */
65298 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
65299 	thr->heap->lj.iserror = 0;
65300 	DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, &thr->heap->lj.value1);
65301 	DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, &thr->heap->lj.value2);
65302 
65303 	/* Error handling complete, remove side effect protections.  Caller
65304 	 * will process pending finalizers.
65305 	 */
65306 #if defined(DUK_USE_ASSERTIONS)
65307 	DUK_ASSERT(thr->heap->error_not_allowed == 1);
65308 	thr->heap->error_not_allowed = 0;
65309 #endif
65310 	DUK_ASSERT(thr->heap->pf_prevent_count > 0);
65311 	thr->heap->pf_prevent_count--;
65312 	DUK_DD(DUK_DDPRINT("safe call error handled, pf_prevent_count updated to %ld", (long) thr->heap->pf_prevent_count));
65313 
65314 	/* thr->ptr_curr_pc is restored by
65315 	 * duk__handle_safe_call_shared_unwind() which is also used for
65316 	 * success path.
65317 	 */
65318 }
65319 
65320 DUK_LOCAL void duk__handle_safe_call_shared_unwind(duk_hthread *thr,
65321                                                    duk_idx_t idx_retbase,
65322                                                    duk_idx_t num_stack_rets,
65323 #if defined(DUK_USE_ASSERTIONS)
65324                                                    duk_size_t entry_callstack_top,
65325 #endif
65326                                                    duk_int_t entry_call_recursion_depth,
65327                                                    duk_hthread *entry_curr_thread,
65328                                                    duk_instr_t **entry_ptr_curr_pc) {
65329 	DUK_ASSERT(thr != NULL);
65330 	DUK_CTX_ASSERT_VALID(thr);
65331 	DUK_UNREF(idx_retbase);
65332 	DUK_UNREF(num_stack_rets);
65333 	DUK_UNREF(entry_curr_thread);
65334 
65335 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
65336 
65337 	/* Restore entry thread executor curr_pc stack frame pointer.
65338 	 * XXX: would be enough to do in error path only, should nest
65339 	 * cleanly in success path.
65340 	 */
65341 	thr->ptr_curr_pc = entry_ptr_curr_pc;
65342 
65343 	thr->heap->call_recursion_depth = entry_call_recursion_depth;
65344 
65345 	/* stack discipline consistency check */
65346 	DUK_ASSERT(duk_get_top(thr) == idx_retbase + num_stack_rets);
65347 
65348 	/* A debugger forced interrupt check is not needed here, as
65349 	 * problematic safe calls are not caused by side effects.
65350 	 */
65351 
65352 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
65353 	duk__interrupt_fixup(thr, entry_curr_thread);
65354 #endif
65355 }
65356 
65357 DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
65358                                             duk_safe_call_function func,
65359                                             void *udata,
65360                                             duk_idx_t num_stack_args,
65361                                             duk_idx_t num_stack_rets) {
65362 	duk_activation *entry_act;
65363 	duk_size_t entry_valstack_bottom_byteoff;
65364 #if defined(DUK_USE_ASSERTIONS)
65365 	duk_size_t entry_valstack_end_byteoff;
65366 	duk_size_t entry_callstack_top;
65367 	duk_size_t entry_callstack_preventcount;
65368 #endif
65369 	duk_int_t entry_call_recursion_depth;
65370 	duk_hthread *entry_curr_thread;
65371 	duk_uint_fast8_t entry_thread_state;
65372 	duk_instr_t **entry_ptr_curr_pc;
65373 	duk_jmpbuf *old_jmpbuf_ptr = NULL;
65374 	duk_jmpbuf our_jmpbuf;
65375 	duk_idx_t idx_retbase;
65376 	duk_int_t retval;
65377 
65378 	DUK_ASSERT(thr != NULL);
65379 	DUK_ASSERT(duk_get_top(thr) >= num_stack_args);  /* Caller ensures. */
65380 
65381 	DUK_STATS_INC(thr->heap, stats_safecall_all);
65382 
65383 	/* Value stack reserve handling: safe call assumes caller has reserved
65384 	 * space for nrets (assuming optimal unwind processing).  Value stack
65385 	 * reserve is not stored/restored as for normal calls because a safe
65386 	 * call conceptually happens in the same activation.
65387 	 */
65388 
65389 	/* Careful with indices like '-x'; if 'x' is zero, it refers to bottom */
65390 	entry_act = thr->callstack_curr;
65391 	entry_valstack_bottom_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
65392 #if defined(DUK_USE_ASSERTIONS)
65393 	entry_valstack_end_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
65394 	entry_callstack_top = thr->callstack_top;
65395 	entry_callstack_preventcount = thr->callstack_preventcount;
65396 #endif
65397 	entry_call_recursion_depth = thr->heap->call_recursion_depth;
65398 	entry_curr_thread = thr->heap->curr_thread;  /* may be NULL if first call */
65399 	entry_thread_state = thr->state;
65400 	entry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */
65401 	idx_retbase = duk_get_top(thr) - num_stack_args;  /* not a valid stack index if num_stack_args == 0 */
65402 	DUK_ASSERT(idx_retbase >= 0);
65403 
65404 	DUK_ASSERT((duk_idx_t) (thr->valstack_top - thr->valstack_bottom) >= num_stack_args);  /* Caller ensures. */
65405 	DUK_ASSERT((duk_idx_t) (thr->valstack_end - (thr->valstack_bottom + idx_retbase)) >= num_stack_rets);  /* Caller ensures. */
65406 
65407 	/* Cannot portably debug print a function pointer, hence 'func' not printed! */
65408 	DUK_DD(DUK_DDPRINT("duk_handle_safe_call: thr=%p, num_stack_args=%ld, num_stack_rets=%ld, "
65409 	                   "valstack_top=%ld, idx_retbase=%ld, rec_depth=%ld/%ld, "
65410 	                   "entry_act=%p, entry_valstack_bottom_byteoff=%ld, entry_call_recursion_depth=%ld, "
65411 	                   "entry_curr_thread=%p, entry_thread_state=%ld",
65412 	                   (void *) thr,
65413 	                   (long) num_stack_args,
65414 	                   (long) num_stack_rets,
65415 	                   (long) duk_get_top(thr),
65416 	                   (long) idx_retbase,
65417 	                   (long) thr->heap->call_recursion_depth,
65418 	                   (long) thr->heap->call_recursion_limit,
65419 	                   (void *) entry_act,
65420 	                   (long) entry_valstack_bottom_byteoff,
65421 	                   (long) entry_call_recursion_depth,
65422 	                   (void *) entry_curr_thread,
65423 	                   (long) entry_thread_state));
65424 
65425 	/* Setjmp catchpoint setup. */
65426 	old_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;
65427 	thr->heap->lj.jmpbuf_ptr = &our_jmpbuf;
65428 
65429 	/* Prevent yields for the duration of the safe call.  This only
65430 	 * matters if the executor makes safe calls to functions that
65431 	 * yield, this doesn't currently happen.
65432 	 */
65433 	thr->callstack_preventcount++;
65434 
65435 #if defined(DUK_USE_CPP_EXCEPTIONS)
65436 	try {
65437 #else
65438 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == &our_jmpbuf);
65439 	if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
65440 		/* Success path. */
65441 #endif
65442 		DUK_DDD(DUK_DDDPRINT("safe_call setjmp catchpoint setup complete"));
65443 
65444 		duk__handle_safe_call_inner(thr,
65445 		                            func,
65446 		                            udata,
65447 #if defined(DUK_USE_ASSERTIONS)
65448 		                            entry_valstack_bottom_byteoff,
65449 		                            entry_callstack_top,
65450 #endif
65451 		                            entry_curr_thread,
65452 		                            entry_thread_state,
65453 		                            idx_retbase,
65454 		                            num_stack_rets);
65455 
65456 		DUK_STATS_INC(thr->heap, stats_safecall_nothrow);
65457 
65458 		/* Either pointer may be NULL (at entry), so don't assert */
65459 		thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
65460 
65461 		/* If calls happen inside the safe call, these are restored by
65462 		 * whatever calls are made.  Reserve cannot decrease.
65463 		 */
65464 		DUK_ASSERT(thr->callstack_curr == entry_act);
65465 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
65466 
65467 		retval = DUK_EXEC_SUCCESS;
65468 #if defined(DUK_USE_CPP_EXCEPTIONS)
65469 	} catch (duk_internal_exception &exc) {
65470 		DUK_UNREF(exc);
65471 #else
65472 	} else {
65473 		/* Error path. */
65474 #endif
65475 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
65476 
65477 		DUK_STATS_INC(thr->heap, stats_safecall_throw);
65478 
65479 		duk__handle_safe_call_error(thr,
65480 		                            entry_act,
65481 #if defined(DUK_USE_ASSERTIONS)
65482 		                            entry_callstack_top,
65483 #endif
65484 		                            entry_curr_thread,
65485 		                            entry_thread_state,
65486 		                            idx_retbase,
65487 		                            num_stack_rets,
65488 		                            entry_valstack_bottom_byteoff,
65489 		                            old_jmpbuf_ptr);
65490 
65491 		retval = DUK_EXEC_ERROR;
65492 	}
65493 #if defined(DUK_USE_CPP_EXCEPTIONS)
65494 	catch (duk_fatal_exception &exc) {
65495 		DUK_D(DUK_DPRINT("rethrow duk_fatal_exception"));
65496 		throw;
65497 	} catch (std::exception &exc) {
65498 		const char *what = exc.what();
65499 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
65500 		DUK_STATS_INC(thr->heap, stats_safecall_throw);
65501 		if (!what) {
65502 			what = "unknown";
65503 		}
65504 		DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
65505 		try {
65506 			DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
65507 			DUK_WO_NORETURN(return 0;);
65508 		} catch (duk_internal_exception exc) {
65509 			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
65510 			DUK_UNREF(exc);
65511 			duk__handle_safe_call_error(thr,
65512 			                            entry_act,
65513 #if defined(DUK_USE_ASSERTIONS)
65514 			                            entry_callstack_top,
65515 #endif
65516 			                            entry_curr_thread,
65517 			                            entry_thread_state,
65518 			                            idx_retbase,
65519 			                            num_stack_rets,
65520 			                            entry_valstack_bottom_byteoff,
65521 			                            old_jmpbuf_ptr);
65522 			retval = DUK_EXEC_ERROR;
65523 		}
65524 	} catch (...) {
65525 		DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
65526 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
65527 		DUK_STATS_INC(thr->heap, stats_safecall_throw);
65528 		try {
65529 			DUK_ERROR_TYPE(thr, "caught invalid c++ exception (perhaps thrown by user code)");
65530 			DUK_WO_NORETURN(return 0;);
65531 		} catch (duk_internal_exception exc) {
65532 			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
65533 			DUK_UNREF(exc);
65534 			duk__handle_safe_call_error(thr,
65535 			                            entry_act,
65536 #if defined(DUK_USE_ASSERTIONS)
65537 			                            entry_callstack_top,
65538 #endif
65539 			                            entry_curr_thread,
65540 			                            entry_thread_state,
65541 			                            idx_retbase,
65542 			                            num_stack_rets,
65543 			                            entry_valstack_bottom_byteoff,
65544 			                            old_jmpbuf_ptr);
65545 			retval = DUK_EXEC_ERROR;
65546 		}
65547 	}
65548 #endif
65549 
65550 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == old_jmpbuf_ptr);  /* success/error path both do this */
65551 
65552 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
65553 
65554 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
65555 	duk__handle_safe_call_shared_unwind(thr,
65556 	                                    idx_retbase,
65557 	                                    num_stack_rets,
65558 #if defined(DUK_USE_ASSERTIONS)
65559 	                                    entry_callstack_top,
65560 #endif
65561 	                                    entry_call_recursion_depth,
65562 	                                    entry_curr_thread,
65563 	                                    entry_ptr_curr_pc);
65564 
65565 	/* Restore preventcount. */
65566 	thr->callstack_preventcount--;
65567 	DUK_ASSERT(thr->callstack_preventcount == entry_callstack_preventcount);
65568 
65569 	/* Final asserts. */
65570 	DUK_ASSERT(thr->callstack_curr == entry_act);
65571 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) == entry_valstack_bottom_byteoff);
65572 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
65573 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
65574 	DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
65575 	DUK_ASSERT(thr->heap->curr_thread == entry_curr_thread);
65576 	DUK_ASSERT(thr->state == entry_thread_state);
65577 	DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
65578 	DUK_ASSERT(duk_get_top(thr) == idx_retbase + num_stack_rets);
65579 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
65580 
65581 	/* Pending side effects. */
65582 	DUK_REFZERO_CHECK_FAST(thr);
65583 
65584 	return retval;
65585 }
65586 
65587 /*
65588  *  Property-based call (foo.noSuch()) error setup: replace target function
65589  *  on stack top with a hidden Symbol tagged non-callable wrapper object
65590  *  holding the error.  The error gets thrown in call handling at the
65591  *  proper spot to follow ECMAScript semantics.
65592  */
65593 
65594 #if defined(DUK_USE_VERBOSE_ERRORS)
65595 DUK_INTERNAL DUK_NOINLINE DUK_COLD void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_base, duk_tval *tv_key) {
65596 	const char *str_targ, *str_key, *str_base;
65597 	duk_idx_t entry_top;
65598 
65599 	entry_top = duk_get_top(thr);
65600 
65601 	/* [ <nargs> target ] */
65602 
65603 	/* Must stabilize pointers first.  tv_targ is already on stack top. */
65604 	duk_push_tval(thr, tv_base);
65605 	duk_push_tval(thr, tv_key);
65606 
65607 	DUK_GC_TORTURE(thr->heap);
65608 
65609 	duk_push_bare_object(thr);
65610 
65611 	/* [ <nargs> target base key {} ] */
65612 
65613 	/* We only push a wrapped error, replacing the call target (at
65614 	 * idx_func) with the error to ensure side effects come out
65615 	 * correctly:
65616 	 * - Property read
65617 	 * - Call argument evaluation
65618 	 * - Callability check and error thrown
65619 	 *
65620 	 * A hidden Symbol on the wrapper object pushed above is used by
65621 	 * call handling to figure out the error is to be thrown as is.
65622 	 * It is CRITICAL that the hidden Symbol can never occur on a
65623 	 * user visible object that may get thrown.
65624 	 */
65625 
65626 #if defined(DUK_USE_PARANOID_ERRORS)
65627 	str_targ = duk_get_type_name(thr, -4);
65628 	str_key = duk_get_type_name(thr, -2);
65629 	str_base = duk_get_type_name(thr, -3);
65630 	duk_push_error_object(thr,
65631 	                      DUK_ERR_TYPE_ERROR | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
65632 	                      "%s not callable (property %s of %s)", str_targ, str_key, str_base);
65633 	duk_xdef_prop_stridx(thr, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);  /* Marker property, reuse _Target. */
65634 	/* [ <nargs> target base key { _Target: error } ] */
65635 	duk_replace(thr, entry_top - 1);
65636 #else
65637 	str_targ = duk_push_string_readable(thr, -4);
65638 	str_key = duk_push_string_readable(thr, -3);
65639 	str_base = duk_push_string_readable(thr, -5);
65640 	duk_push_error_object(thr,
65641 	                      DUK_ERR_TYPE_ERROR | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
65642 	                      "%s not callable (property %s of %s)", str_targ, str_key, str_base);
65643 	/* [ <nargs> target base key {} str_targ str_key str_base error ] */
65644 	duk_xdef_prop_stridx(thr, -5, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);  /* Marker property, reuse _Target. */
65645 	/* [ <nargs> target base key { _Target: error } str_targ str_key str_base ] */
65646 	duk_swap(thr, -4, entry_top - 1);
65647 	/* [ <nargs> { _Target: error } base key target str_targ str_key str_base ] */
65648 #endif
65649 
65650 	/* [ <nregs> { _Target: error } <variable> */
65651 	duk_set_top(thr, entry_top);
65652 
65653 	/* [ <nregs> { _Target: error } */
65654 	DUK_ASSERT(!duk_is_callable(thr, -1));  /* Critical so that call handling will throw the error. */
65655 }
65656 #endif  /* DUK_USE_VERBOSE_ERRORS */
65657 
65658 /* automatic undefs */
65659 #undef DUK__AUGMENT_CALL_RELAX_COUNT
65660 #undef DUK__CALL_HANDLING_REQUIRE_STACK
65661 /*
65662  *  ECMAScript compiler.
65663  *
65664  *  Parses an input string and generates a function template result.
65665  *  Compilation may happen in multiple contexts (global code, eval
65666  *  code, function code).
65667  *
65668  *  The parser uses a traditional top-down recursive parsing for the
65669  *  statement level, and an operator precedence based top-down approach
65670  *  for the expression level.  The attempt is to minimize the C stack
65671  *  depth.  Bytecode is generated directly without an intermediate
65672  *  representation (tree), at the cost of needing two (and sometimes
65673  *  three) passes over each function.
65674  *
65675  *  The top-down recursive parser functions are named "duk__parse_XXX".
65676  *
65677  *  Recursion limits are in key functions to prevent arbitrary C recursion:
65678  *  function body parsing, statement parsing, and expression parsing.
65679  *
65680  *  See doc/compiler.rst for discussion on the design.
65681  *
65682  *  A few typing notes:
65683  *
65684  *    - duk_regconst_t: signed, highest bit set (< 0) means constant,
65685  *      some call sites use -1 for "none" (equivalent to constant 0x7fffffff)
65686  *    - PC values: duk_int_t, negative values used as markers
65687  */
65688 
65689 /* #include duk_internal.h -> already included */
65690 
65691 /* If highest bit of a register number is set, it refers to a constant instead.
65692  * When interpreted as a signed value, this means const values are always
65693  * negative (when interpreted as two's complement).  For example DUK__ISREG_TEMP()
65694  * uses this approach to avoid an explicit DUK__ISREG() check (the condition is
65695  * logically "'x' is a register AND 'x' >= temp_first").
65696  */
65697 #define DUK__CONST_MARKER                   DUK_REGCONST_CONST_MARKER
65698 #define DUK__REMOVECONST(x)                 ((x) & ~DUK__CONST_MARKER)
65699 #define DUK__ISREG(x)                       ((x) >= 0)
65700 #define DUK__ISCONST(x)                     ((x) < 0)
65701 #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. */
65702 #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. */
65703 #define DUK__GETTEMP(comp_ctx)              ((comp_ctx)->curr_func.temp_next)
65704 #define DUK__SETTEMP(comp_ctx,x)            ((comp_ctx)->curr_func.temp_next = (x))  /* dangerous: must only lower (temp_max not updated) */
65705 #define DUK__SETTEMP_CHECKMAX(comp_ctx,x)   duk__settemp_checkmax((comp_ctx),(x))
65706 #define DUK__ALLOCTEMP(comp_ctx)            duk__alloctemp((comp_ctx))
65707 #define DUK__ALLOCTEMPS(comp_ctx,count)     duk__alloctemps((comp_ctx),(count))
65708 
65709 /* Init value set size for array and object literals. */
65710 #define DUK__MAX_ARRAY_INIT_VALUES        20
65711 #define DUK__MAX_OBJECT_INIT_PAIRS        10
65712 
65713 /* XXX: hack, remove when const lookup is not O(n) */
65714 #define DUK__GETCONST_MAX_CONSTS_CHECK    256
65715 
65716 /* These limits are based on bytecode limits.  Max temps is limited
65717  * by duk_hcompfunc nargs/nregs fields being 16 bits.
65718  */
65719 #define DUK__MAX_CONSTS                   DUK_BC_BC_MAX
65720 #define DUK__MAX_FUNCS                    DUK_BC_BC_MAX
65721 #define DUK__MAX_TEMPS                    0xffffL
65722 
65723 /* Initial bytecode size allocation. */
65724 #if defined(DUK_USE_PREFER_SIZE)
65725 #define DUK__BC_INITIAL_INSTS             16
65726 #else
65727 #define DUK__BC_INITIAL_INSTS             256
65728 #endif
65729 
65730 #define DUK__RECURSION_INCREASE(comp_ctx,thr)  do { \
65731 		DUK_DDD(DUK_DDDPRINT("RECURSION INCREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
65732 		duk__comp_recursion_increase((comp_ctx)); \
65733 	} while (0)
65734 
65735 #define DUK__RECURSION_DECREASE(comp_ctx,thr)  do { \
65736 		DUK_DDD(DUK_DDDPRINT("RECURSION DECREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
65737 		duk__comp_recursion_decrease((comp_ctx)); \
65738 	} while (0)
65739 
65740 /* Value stack slot limits: these are quite approximate right now, and
65741  * because they overlap in control flow, some could be eliminated.
65742  */
65743 #define DUK__COMPILE_ENTRY_SLOTS          8
65744 #define DUK__FUNCTION_INIT_REQUIRE_SLOTS  16
65745 #define DUK__FUNCTION_BODY_REQUIRE_SLOTS  16
65746 #define DUK__PARSE_STATEMENTS_SLOTS       16
65747 #define DUK__PARSE_EXPR_SLOTS             16
65748 
65749 /* Temporary structure used to pass a stack allocated region through
65750  * duk_safe_call().
65751  */
65752 typedef struct {
65753 	duk_small_uint_t flags;
65754 	duk_compiler_ctx comp_ctx_alloc;
65755 	duk_lexer_point lex_pt_alloc;
65756 } duk__compiler_stkstate;
65757 
65758 /*
65759  *  Prototypes
65760  */
65761 
65762 /* lexing */
65763 DUK_LOCAL_DECL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
65764 DUK_LOCAL_DECL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
65765 DUK_LOCAL_DECL void duk__advance(duk_compiler_ctx *ctx);
65766 
65767 /* function helpers */
65768 DUK_LOCAL_DECL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx);
65769 DUK_LOCAL_DECL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx);
65770 DUK_LOCAL_DECL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_stmt_value_reg);
65771 DUK_LOCAL_DECL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx);
65772 DUK_LOCAL_DECL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx);
65773 
65774 /* code emission */
65775 DUK_LOCAL_DECL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx);
65776 DUK_LOCAL_DECL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc);
65777 DUK_LOCAL_DECL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins);
65778 DUK_LOCAL_DECL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op);
65779 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);
65780 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);
65781 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);
65782 #if 0  /* unused */
65783 DUK_LOCAL_DECL void duk__emit_a(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a);
65784 DUK_LOCAL_DECL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b);
65785 #endif
65786 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);
65787 DUK_LOCAL_DECL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc);
65788 DUK_LOCAL_DECL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc);
65789 DUK_LOCAL_DECL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val);
65790 DUK_LOCAL_DECL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val);
65791 DUK_LOCAL_DECL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc);
65792 DUK_LOCAL_DECL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx);
65793 DUK_LOCAL_DECL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
65794 DUK_LOCAL_DECL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc);
65795 DUK_LOCAL_DECL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
65796 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);
65797 DUK_LOCAL_DECL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
65798 DUK_LOCAL_DECL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
65799 DUK_LOCAL_DECL void duk__emit_invalid(duk_compiler_ctx *comp_ctx);
65800 
65801 /* ivalue/ispec helpers */
65802 DUK_LOCAL_DECL void duk__ivalue_regconst(duk_ivalue *x, duk_regconst_t regconst);
65803 DUK_LOCAL_DECL void duk__ivalue_plain_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65804 DUK_LOCAL_DECL void duk__ivalue_var_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65805 DUK_LOCAL_DECL void duk__ivalue_var_hstring(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_hstring *h);
65806 DUK_LOCAL_DECL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst);
65807 DUK_LOCAL_DECL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst);
65808 DUK_LOCAL_DECL duk_regconst_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num);
65809 DUK_LOCAL_DECL duk_regconst_t duk__alloctemp(duk_compiler_ctx *comp_ctx);
65810 DUK_LOCAL_DECL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_regconst_t temp_next);
65811 DUK_LOCAL_DECL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx);
65812 DUK_LOCAL_DECL
65813 duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
65814                                          duk_ispec *x,
65815                                          duk_regconst_t forced_reg,
65816                                          duk_small_uint_t flags);
65817 DUK_LOCAL_DECL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_regconst_t forced_reg);
65818 DUK_LOCAL_DECL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_regconst_t forced_reg);
65819 DUK_LOCAL_DECL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65820 DUK_LOCAL_DECL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65821 DUK_LOCAL_DECL
65822 duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
65823                                           duk_ivalue *x,
65824                                           duk_regconst_t forced_reg,
65825                                           duk_small_uint_t flags);
65826 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65827 #if 0  /* unused */
65828 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65829 #endif
65830 DUK_LOCAL_DECL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg);
65831 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65832 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65833 
65834 /* identifier handling */
65835 DUK_LOCAL_DECL duk_regconst_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx);
65836 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);
65837 
65838 /* label handling */
65839 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);
65840 DUK_LOCAL_DECL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags);
65841 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);
65842 DUK_LOCAL_DECL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_size_t len);
65843 
65844 /* top-down expression parser */
65845 DUK_LOCAL_DECL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65846 DUK_LOCAL_DECL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res);
65847 DUK_LOCAL_DECL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx);
65848 DUK_LOCAL_DECL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx);
65849 
65850 /* exprtop is the top level variant which resets nud/led counts */
65851 DUK_LOCAL_DECL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65852 DUK_LOCAL_DECL void duk__exprtop(duk_compiler_ctx *ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65853 
65854 /* convenience helpers */
65855 #if 0  /* unused */
65856 DUK_LOCAL_DECL duk_regconst_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65857 #endif
65858 #if 0  /* unused */
65859 DUK_LOCAL_DECL duk_regconst_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65860 #endif
65861 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);
65862 DUK_LOCAL_DECL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65863 #if 0  /* unused */
65864 DUK_LOCAL_DECL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65865 #endif
65866 DUK_LOCAL_DECL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65867 DUK_LOCAL_DECL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65868 DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65869 #if 0  /* unused */
65870 DUK_LOCAL_DECL duk_regconst_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65871 #endif
65872 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);
65873 DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65874 #if 0  /* unused */
65875 DUK_LOCAL_DECL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65876 #endif
65877 
65878 /* expression parsing helpers */
65879 DUK_LOCAL_DECL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65880 DUK_LOCAL_DECL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65881 DUK_LOCAL_DECL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65882 
65883 /* statement parsing */
65884 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);
65885 DUK_LOCAL_DECL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags);
65886 DUK_LOCAL_DECL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
65887 DUK_LOCAL_DECL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
65888 DUK_LOCAL_DECL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65889 DUK_LOCAL_DECL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
65890 DUK_LOCAL_DECL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
65891 DUK_LOCAL_DECL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65892 DUK_LOCAL_DECL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65893 DUK_LOCAL_DECL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65894 DUK_LOCAL_DECL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65895 DUK_LOCAL_DECL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65896 DUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem);
65897 DUK_LOCAL_DECL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id);
65898 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);
65899 
65900 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);
65901 DUK_LOCAL_DECL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx);
65902 DUK_LOCAL_DECL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);
65903 DUK_LOCAL_DECL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);
65904 
65905 #define DUK__FUNC_FLAG_DECL            (1 << 0)   /* Parsing a function declaration. */
65906 #define DUK__FUNC_FLAG_GETSET          (1 << 1)   /* Parsing an object literal getter/setter. */
65907 #define DUK__FUNC_FLAG_METDEF          (1 << 2)   /* Parsing an object literal method definition shorthand. */
65908 #define DUK__FUNC_FLAG_PUSHNAME_PASS1  (1 << 3)   /* Push function name when creating template (first pass only). */
65909 #define DUK__FUNC_FLAG_USE_PREVTOKEN   (1 << 4)   /* Use prev_token to start function parsing (workaround for object literal). */
65910 
65911 /*
65912  *  Parser control values for tokens.  The token table is ordered by the
65913  *  DUK_TOK_XXX defines.
65914  *
65915  *  The binding powers are for lbp() use (i.e. for use in led() context).
65916  *  Binding powers are positive for typing convenience, and bits at the
65917  *  top should be reserved for flags.  Binding power step must be higher
65918  *  than 1 so that binding power "lbp - 1" can be used for right associative
65919  *  operators.  Currently a step of 2 is used (which frees one more bit for
65920  *  flags).
65921  */
65922 
65923 /* XXX: actually single step levels would work just fine, clean up */
65924 
65925 /* binding power "levels" (see doc/compiler.rst) */
65926 #define DUK__BP_INVALID                0             /* always terminates led() */
65927 #define DUK__BP_EOF                    2
65928 #define DUK__BP_CLOSING                4             /* token closes expression, e.g. ')', ']' */
65929 #define DUK__BP_FOR_EXPR               DUK__BP_CLOSING    /* bp to use when parsing a top level Expression */
65930 #define DUK__BP_COMMA                  6
65931 #define DUK__BP_ASSIGNMENT             8
65932 #define DUK__BP_CONDITIONAL            10
65933 #define DUK__BP_LOR                    12
65934 #define DUK__BP_LAND                   14
65935 #define DUK__BP_BOR                    16
65936 #define DUK__BP_BXOR                   18
65937 #define DUK__BP_BAND                   20
65938 #define DUK__BP_EQUALITY               22
65939 #define DUK__BP_RELATIONAL             24
65940 #define DUK__BP_SHIFT                  26
65941 #define DUK__BP_ADDITIVE               28
65942 #define DUK__BP_MULTIPLICATIVE         30
65943 #define DUK__BP_EXPONENTIATION         32
65944 #define DUK__BP_POSTFIX                34
65945 #define DUK__BP_CALL                   36
65946 #define DUK__BP_MEMBER                 38
65947 
65948 #define DUK__TOKEN_LBP_BP_MASK         0x1f
65949 #define DUK__TOKEN_LBP_FLAG_NO_REGEXP  (1 << 5)   /* regexp literal must not follow this token */
65950 #define DUK__TOKEN_LBP_FLAG_TERMINATES (1 << 6)   /* terminates expression; e.g. post-increment/-decrement */
65951 #define DUK__TOKEN_LBP_FLAG_UNUSED     (1 << 7)   /* unused */
65952 
65953 #define DUK__TOKEN_LBP_GET_BP(x)       ((duk_small_uint_t) (((x) & DUK__TOKEN_LBP_BP_MASK) * 2))
65954 
65955 #define DUK__MK_LBP(bp)                ((bp) >> 1)    /* bp is assumed to be even */
65956 #define DUK__MK_LBP_FLAGS(bp,flags)    (((bp) >> 1) | (flags))
65957 
65958 DUK_LOCAL const duk_uint8_t duk__token_lbp[] = {
65959 	DUK__MK_LBP(DUK__BP_EOF),                                 /* DUK_TOK_EOF */
65960 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_IDENTIFIER */
65961 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_BREAK */
65962 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CASE */
65963 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CATCH */
65964 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CONTINUE */
65965 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DEBUGGER */
65966 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DEFAULT */
65967 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DELETE */
65968 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DO */
65969 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_ELSE */
65970 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FINALLY */
65971 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FOR */
65972 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FUNCTION */
65973 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IF */
65974 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_IN */
65975 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_INSTANCEOF */
65976 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_NEW */
65977 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_RETURN */
65978 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SWITCH */
65979 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_THIS */
65980 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_THROW */
65981 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_TRY */
65982 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_TYPEOF */
65983 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_VAR */
65984 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CONST */
65985 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_VOID */
65986 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_WHILE */
65987 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_WITH */
65988 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CLASS */
65989 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_ENUM */
65990 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_EXPORT */
65991 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_EXTENDS */
65992 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IMPORT */
65993 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SUPER */
65994 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_NULL */
65995 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_TRUE */
65996 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_FALSE */
65997 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_GET */
65998 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SET */
65999 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IMPLEMENTS */
66000 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_INTERFACE */
66001 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LET */
66002 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PACKAGE */
66003 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PRIVATE */
66004 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PROTECTED */
66005 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PUBLIC */
66006 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_STATIC */
66007 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_YIELD */
66008 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LCURLY */
66009 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RCURLY */
66010 	DUK__MK_LBP(DUK__BP_MEMBER),                              /* DUK_TOK_LBRACKET */
66011 	DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RBRACKET */
66012 	DUK__MK_LBP(DUK__BP_CALL),                                /* DUK_TOK_LPAREN */
66013 	DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RPAREN */
66014 	DUK__MK_LBP(DUK__BP_MEMBER),                              /* DUK_TOK_PERIOD */
66015 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SEMICOLON */
66016 	DUK__MK_LBP(DUK__BP_COMMA),                               /* DUK_TOK_COMMA */
66017 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_LT */
66018 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_GT */
66019 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_LE */
66020 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_GE */
66021 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_EQ */
66022 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_NEQ */
66023 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_SEQ */
66024 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_SNEQ */
66025 	DUK__MK_LBP(DUK__BP_ADDITIVE),                            /* DUK_TOK_ADD */
66026 	DUK__MK_LBP(DUK__BP_ADDITIVE),                            /* DUK_TOK_SUB */
66027 	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_MUL */
66028 	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_DIV */
66029 	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_MOD */
66030 	DUK__MK_LBP(DUK__BP_EXPONENTIATION),                      /* DUK_TOK_EXP */
66031 	DUK__MK_LBP_FLAGS(DUK__BP_POSTFIX, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_INCREMENT */
66032 	DUK__MK_LBP_FLAGS(DUK__BP_POSTFIX, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_DECREMENT */
66033 	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_ALSHIFT */
66034 	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_ARSHIFT */
66035 	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_RSHIFT */
66036 	DUK__MK_LBP(DUK__BP_BAND),                                /* DUK_TOK_BAND */
66037 	DUK__MK_LBP(DUK__BP_BOR),                                 /* DUK_TOK_BOR */
66038 	DUK__MK_LBP(DUK__BP_BXOR),                                /* DUK_TOK_BXOR */
66039 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LNOT */
66040 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_BNOT */
66041 	DUK__MK_LBP(DUK__BP_LAND),                                /* DUK_TOK_LAND */
66042 	DUK__MK_LBP(DUK__BP_LOR),                                 /* DUK_TOK_LOR */
66043 	DUK__MK_LBP(DUK__BP_CONDITIONAL),                         /* DUK_TOK_QUESTION */
66044 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_COLON */
66045 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_EQUALSIGN */
66046 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ADD_EQ */
66047 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_SUB_EQ */
66048 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_MUL_EQ */
66049 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_DIV_EQ */
66050 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_MOD_EQ */
66051 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_EXP_EQ */
66052 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ALSHIFT_EQ */
66053 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ARSHIFT_EQ */
66054 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_RSHIFT_EQ */
66055 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BAND_EQ */
66056 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BOR_EQ */
66057 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BXOR_EQ */
66058 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_NUMBER */
66059 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_STRING */
66060 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_REGEXP */
66061 };
66062 
66063 /*
66064  *  Misc helpers
66065  */
66066 
66067 DUK_LOCAL void duk__comp_recursion_increase(duk_compiler_ctx *comp_ctx) {
66068 	DUK_ASSERT(comp_ctx != NULL);
66069 	DUK_ASSERT(comp_ctx->recursion_depth >= 0);
66070 	if (comp_ctx->recursion_depth >= comp_ctx->recursion_limit) {
66071 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_COMPILER_RECURSION_LIMIT);
66072 		DUK_WO_NORETURN(return;);
66073 	}
66074 	comp_ctx->recursion_depth++;
66075 }
66076 
66077 DUK_LOCAL void duk__comp_recursion_decrease(duk_compiler_ctx *comp_ctx) {
66078 	DUK_ASSERT(comp_ctx != NULL);
66079 	DUK_ASSERT(comp_ctx->recursion_depth > 0);
66080 	comp_ctx->recursion_depth--;
66081 }
66082 
66083 DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
66084 	DUK_UNREF(comp_ctx);
66085 	DUK_ASSERT(h != NULL);
66086 	return DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h);
66087 }
66088 
66089 DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments_in_strict_mode(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
66090 	DUK_ASSERT(h != NULL);
66091 	return (comp_ctx->curr_func.is_strict &&
66092 	        DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h));
66093 }
66094 
66095 /*
66096  *  Parser duk__advance() token eating functions
66097  */
66098 
66099 /* XXX: valstack handling is awkward.  Add a valstack helper which
66100  * avoids dup():ing; valstack_copy(src, dst)?
66101  */
66102 
66103 DUK_LOCAL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
66104 	duk_hthread *thr = comp_ctx->thr;
66105 	duk_bool_t regexp;
66106 
66107 	DUK_ASSERT_DISABLE(comp_ctx->curr_token.t >= 0);  /* unsigned */
66108 	DUK_ASSERT(comp_ctx->curr_token.t <= DUK_TOK_MAXVAL);  /* MAXVAL is inclusive */
66109 
66110 	/*
66111 	 *  Use current token to decide whether a RegExp can follow.
66112 	 *
66113 	 *  We can use either 't' or 't_nores'; the latter would not
66114 	 *  recognize keywords.  Some keywords can be followed by a
66115 	 *  RegExp (e.g. "return"), so using 't' is better.  This is
66116 	 *  not trivial, see doc/compiler.rst.
66117 	 */
66118 
66119 	regexp = 1;
66120 	if (duk__token_lbp[comp_ctx->curr_token.t] & DUK__TOKEN_LBP_FLAG_NO_REGEXP) {
66121 		regexp = 0;
66122 	}
66123 	if (comp_ctx->curr_func.reject_regexp_in_adv) {
66124 		comp_ctx->curr_func.reject_regexp_in_adv = 0;
66125 		regexp = 0;
66126 	}
66127 	if (comp_ctx->curr_func.allow_regexp_in_adv) {
66128 		comp_ctx->curr_func.allow_regexp_in_adv = 0;
66129 		regexp = 1;
66130 	}
66131 
66132 	if (expect >= 0 && comp_ctx->curr_token.t != (duk_small_uint_t) expect) {
66133 		DUK_D(DUK_DPRINT("parse error: expect=%ld, got=%ld",
66134 		                 (long) expect, (long) comp_ctx->curr_token.t));
66135 		DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
66136 		DUK_WO_NORETURN(return;);
66137 	}
66138 
66139 	/* make current token the previous; need to fiddle with valstack "backing store" */
66140 	duk_memcpy(&comp_ctx->prev_token, &comp_ctx->curr_token, sizeof(duk_token));
66141 	duk_copy(thr, comp_ctx->tok11_idx, comp_ctx->tok21_idx);
66142 	duk_copy(thr, comp_ctx->tok12_idx, comp_ctx->tok22_idx);
66143 
66144 	/* parse new token */
66145 	duk_lexer_parse_js_input_element(&comp_ctx->lex,
66146 	                                 &comp_ctx->curr_token,
66147 	                                 comp_ctx->curr_func.is_strict,
66148 	                                 regexp);
66149 
66150 	DUK_DDD(DUK_DDDPRINT("advance: curr: tok=%ld/%ld,%ld,term=%ld,%!T,%!T "
66151 	                     "prev: tok=%ld/%ld,%ld,term=%ld,%!T,%!T",
66152 	                     (long) comp_ctx->curr_token.t,
66153 	                     (long) comp_ctx->curr_token.t_nores,
66154 	                     (long) comp_ctx->curr_token.start_line,
66155 	                     (long) comp_ctx->curr_token.lineterm,
66156 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok11_idx),
66157 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok12_idx),
66158 	                     (long) comp_ctx->prev_token.t,
66159 	                     (long) comp_ctx->prev_token.t_nores,
66160 	                     (long) comp_ctx->prev_token.start_line,
66161 	                     (long) comp_ctx->prev_token.lineterm,
66162 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok21_idx),
66163 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok22_idx)));
66164 }
66165 
66166 /* advance, expecting current token to be a specific token; parse next token in regexp context */
66167 DUK_LOCAL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
66168 	duk__advance_helper(comp_ctx, expect);
66169 }
66170 
66171 /* advance, whatever the current token is; parse next token in regexp context */
66172 DUK_LOCAL void duk__advance(duk_compiler_ctx *comp_ctx) {
66173 	duk__advance_helper(comp_ctx, -1);
66174 }
66175 
66176 /*
66177  *  Helpers for duk_compiler_func.
66178  */
66179 
66180 /* init function state: inits valstack allocations */
66181 DUK_LOCAL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) {
66182 	duk_compiler_func *func = &comp_ctx->curr_func;
66183 	duk_hthread *thr = comp_ctx->thr;
66184 	duk_idx_t entry_top;
66185 
66186 	entry_top = duk_get_top(thr);
66187 
66188 	duk_memzero(func, sizeof(*func));  /* intentional overlap with earlier memzero */
66189 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
66190 	func->h_name = NULL;
66191 	func->h_consts = NULL;
66192 	func->h_funcs = NULL;
66193 	func->h_decls = NULL;
66194 	func->h_labelnames = NULL;
66195 	func->h_labelinfos = NULL;
66196 	func->h_argnames = NULL;
66197 	func->h_varmap = NULL;
66198 #endif
66199 
66200 	duk_require_stack(thr, DUK__FUNCTION_INIT_REQUIRE_SLOTS);
66201 
66202 	DUK_BW_INIT_PUSHBUF(thr, &func->bw_code, DUK__BC_INITIAL_INSTS * sizeof(duk_compiler_instr));
66203 	/* code_idx = entry_top + 0 */
66204 
66205 	duk_push_bare_array(thr);
66206 	func->consts_idx = entry_top + 1;
66207 	func->h_consts = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 1);
66208 	DUK_ASSERT(func->h_consts != NULL);
66209 
66210 	duk_push_bare_array(thr);
66211 	func->funcs_idx = entry_top + 2;
66212 	func->h_funcs = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 2);
66213 	DUK_ASSERT(func->h_funcs != NULL);
66214 	DUK_ASSERT(func->fnum_next == 0);
66215 
66216 	duk_push_bare_array(thr);
66217 	func->decls_idx = entry_top + 3;
66218 	func->h_decls = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 3);
66219 	DUK_ASSERT(func->h_decls != NULL);
66220 
66221 	duk_push_bare_array(thr);
66222 	func->labelnames_idx = entry_top + 4;
66223 	func->h_labelnames = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 4);
66224 	DUK_ASSERT(func->h_labelnames != NULL);
66225 
66226 	duk_push_dynamic_buffer(thr, 0);
66227 	func->labelinfos_idx = entry_top + 5;
66228 	func->h_labelinfos = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, entry_top + 5);
66229 	DUK_ASSERT(func->h_labelinfos != NULL);
66230 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(func->h_labelinfos) && !DUK_HBUFFER_HAS_EXTERNAL(func->h_labelinfos));
66231 
66232 	duk_push_bare_array(thr);
66233 	func->argnames_idx = entry_top + 6;
66234 	func->h_argnames = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 6);
66235 	DUK_ASSERT(func->h_argnames != NULL);
66236 
66237 	duk_push_bare_object(thr);
66238 	func->varmap_idx = entry_top + 7;
66239 	func->h_varmap = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 7);
66240 	DUK_ASSERT(func->h_varmap != NULL);
66241 }
66242 
66243 /* reset function state (prepare for pass 2) */
66244 DUK_LOCAL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx) {
66245 	duk_compiler_func *func = &comp_ctx->curr_func;
66246 	duk_hthread *thr = comp_ctx->thr;
66247 
66248 	/* reset bytecode buffer but keep current size; pass 2 will
66249 	 * require same amount or more.
66250 	 */
66251 	DUK_BW_RESET_SIZE(thr, &func->bw_code);
66252 
66253 	duk_set_length(thr, func->consts_idx, 0);
66254 	/* keep func->h_funcs; inner functions are not reparsed to avoid O(depth^2) parsing */
66255 	func->fnum_next = 0;
66256 	/* duk_set_length(thr, func->funcs_idx, 0); */
66257 	duk_set_length(thr, func->labelnames_idx, 0);
66258 	duk_hbuffer_reset(thr, func->h_labelinfos);
66259 	/* keep func->h_argnames; it is fixed for all passes */
66260 
66261 	/* truncated in case pass 3 needed */
66262 	duk_push_bare_object(thr);
66263 	duk_replace(thr, func->varmap_idx);
66264 	func->h_varmap = DUK_GET_HOBJECT_POSIDX(thr, func->varmap_idx);
66265 	DUK_ASSERT(func->h_varmap != NULL);
66266 }
66267 
66268 /* cleanup varmap from any null entries, compact it, etc; returns number
66269  * of final entries after cleanup.
66270  */
66271 DUK_LOCAL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx) {
66272 	duk_hthread *thr = comp_ctx->thr;
66273 	duk_hobject *h_varmap;
66274 	duk_hstring *h_key;
66275 	duk_tval *tv;
66276 	duk_uint32_t i, e_next;
66277 	duk_int_t ret;
66278 
66279 	/* [ ... varmap ] */
66280 
66281 	h_varmap = DUK_GET_HOBJECT_NEGIDX(thr, -1);
66282 	DUK_ASSERT(h_varmap != NULL);
66283 
66284 	ret = 0;
66285 	e_next = DUK_HOBJECT_GET_ENEXT(h_varmap);
66286 	for (i = 0; i < e_next; i++) {
66287 		h_key = DUK_HOBJECT_E_GET_KEY(thr->heap, h_varmap, i);
66288 		if (!h_key) {
66289 			continue;
66290 		}
66291 
66292 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h_varmap, i));
66293 
66294 		/* The entries can either be register numbers or 'null' values.
66295 		 * Thus, no need to DECREF them and get side effects.  DECREF'ing
66296 		 * the keys (strings) can cause memory to be freed but no side
66297 		 * effects as strings don't have finalizers.  This is why we can
66298 		 * rely on the object properties not changing from underneath us.
66299 		 */
66300 
66301 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h_varmap, i);
66302 		if (!DUK_TVAL_IS_NUMBER(tv)) {
66303 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv));
66304 			DUK_HOBJECT_E_SET_KEY(thr->heap, h_varmap, i, NULL);
66305 			DUK_HSTRING_DECREF(thr, h_key);
66306 			/* when key is NULL, value is garbage so no need to set */
66307 		} else {
66308 			ret++;
66309 		}
66310 	}
66311 
66312 	duk_compact_m1(thr);
66313 
66314 	return ret;
66315 }
66316 
66317 /* Convert duk_compiler_func into a function template, leaving the result
66318  * on top of stack.
66319  */
66320 /* XXX: awkward and bloated asm -- use faster internal accesses */
66321 DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
66322 	duk_compiler_func *func = &comp_ctx->curr_func;
66323 	duk_hthread *thr = comp_ctx->thr;
66324 	duk_hcompfunc *h_res;
66325 	duk_hbuffer_fixed *h_data;
66326 	duk_size_t consts_count;
66327 	duk_size_t funcs_count;
66328 	duk_size_t code_count;
66329 	duk_size_t code_size;
66330 	duk_size_t data_size;
66331 	duk_size_t i;
66332 	duk_tval *p_const;
66333 	duk_hobject **p_func;
66334 	duk_instr_t *p_instr;
66335 	duk_compiler_instr *q_instr;
66336 	duk_tval *tv;
66337 	duk_bool_t keep_varmap;
66338 	duk_bool_t keep_formals;
66339 #if !defined(DUK_USE_DEBUGGER_SUPPORT)
66340 	duk_size_t formals_length;
66341 #endif
66342 
66343 	DUK_DDD(DUK_DDDPRINT("converting duk_compiler_func to function/template"));
66344 
66345 	/*
66346 	 *  Push result object and init its flags
66347 	 */
66348 
66349 	/* Valstack should suffice here, required on function valstack init */
66350 
66351 	h_res = duk_push_hcompfunc(thr);
66352 	DUK_ASSERT(h_res != NULL);
66353 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_res) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
66354 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) h_res, NULL);  /* Function templates are "bare objects". */
66355 
66356 	if (func->is_function) {
66357 		DUK_DDD(DUK_DDDPRINT("function -> set NEWENV"));
66358 		DUK_HOBJECT_SET_NEWENV((duk_hobject *) h_res);
66359 
66360 		if (!func->is_arguments_shadowed) {
66361 			/* arguments object would be accessible; note that shadowing
66362 			 * bindings are arguments or function declarations, neither
66363 			 * of which are deletable, so this is safe.
66364 			 */
66365 
66366 			if (func->id_access_arguments || func->may_direct_eval) {
66367 				DUK_DDD(DUK_DDDPRINT("function may access 'arguments' object directly or "
66368 				                     "indirectly -> set CREATEARGS"));
66369 				DUK_HOBJECT_SET_CREATEARGS((duk_hobject *) h_res);
66370 			}
66371 		}
66372 	} else if (func->is_eval && func->is_strict) {
66373 		DUK_DDD(DUK_DDDPRINT("strict eval code -> set NEWENV"));
66374 		DUK_HOBJECT_SET_NEWENV((duk_hobject *) h_res);
66375 	} else {
66376 		/* non-strict eval: env is caller's env or global env (direct vs. indirect call)
66377 		 * global code: env is is global env
66378 		 */
66379 		DUK_DDD(DUK_DDDPRINT("non-strict eval code or global code -> no NEWENV"));
66380 		DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) h_res));
66381 	}
66382 
66383 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
66384 	if (func->is_function && func->is_namebinding && func->h_name != NULL) {
66385 		/* Object literal set/get functions have a name (property
66386 		 * name) but must not have a lexical name binding, see
66387 		 * test-bug-getset-func-name.js.
66388 		 */
66389 		DUK_DDD(DUK_DDDPRINT("function expression with a name -> set NAMEBINDING"));
66390 		DUK_HOBJECT_SET_NAMEBINDING((duk_hobject *) h_res);
66391 	}
66392 #endif
66393 
66394 	if (func->is_strict) {
66395 		DUK_DDD(DUK_DDDPRINT("function is strict -> set STRICT"));
66396 		DUK_HOBJECT_SET_STRICT((duk_hobject *) h_res);
66397 	}
66398 
66399 	if (func->is_notail) {
66400 		DUK_DDD(DUK_DDDPRINT("function is notail -> set NOTAIL"));
66401 		DUK_HOBJECT_SET_NOTAIL((duk_hobject *) h_res);
66402 	}
66403 
66404 	if (func->is_constructable) {
66405 		DUK_DDD(DUK_DDDPRINT("function is constructable -> set CONSTRUCTABLE"));
66406 		DUK_HOBJECT_SET_CONSTRUCTABLE((duk_hobject *) h_res);
66407 	}
66408 
66409 	/*
66410 	 *  Build function fixed size 'data' buffer, which contains bytecode,
66411 	 *  constants, and inner function references.
66412 	 *
66413 	 *  During the building phase 'data' is reachable but incomplete.
66414 	 *  Only incref's occur during building (no refzero or GC happens),
66415 	 *  so the building process is atomic.
66416 	 */
66417 
66418 	consts_count = duk_hobject_get_length(thr, func->h_consts);
66419 	funcs_count = duk_hobject_get_length(thr, func->h_funcs) / 3;
66420 	code_count = DUK_BW_GET_SIZE(thr, &func->bw_code) / sizeof(duk_compiler_instr);
66421 	code_size = code_count * sizeof(duk_instr_t);
66422 
66423 	data_size = consts_count * sizeof(duk_tval) +
66424 	            funcs_count * sizeof(duk_hobject *) +
66425 	            code_size;
66426 
66427 	DUK_DDD(DUK_DDDPRINT("consts_count=%ld, funcs_count=%ld, code_size=%ld -> "
66428 	                     "data_size=%ld*%ld + %ld*%ld + %ld = %ld",
66429 	                     (long) consts_count, (long) funcs_count, (long) code_size,
66430 	                     (long) consts_count, (long) sizeof(duk_tval),
66431 	                     (long) funcs_count, (long) sizeof(duk_hobject *),
66432 	                     (long) code_size, (long) data_size));
66433 
66434 	duk_push_fixed_buffer_nozero(thr, data_size);
66435 	h_data = (duk_hbuffer_fixed *) (void *) duk_known_hbuffer(thr, -1);
66436 
66437 	DUK_HCOMPFUNC_SET_DATA(thr->heap, h_res, (duk_hbuffer *) h_data);
66438 	DUK_HEAPHDR_INCREF(thr, h_data);
66439 
66440 	p_const = (duk_tval *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data);
66441 	for (i = 0; i < consts_count; i++) {
66442 		DUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* const limits */
66443 		tv = duk_hobject_find_array_entry_tval_ptr(thr->heap, func->h_consts, (duk_uarridx_t) i);
66444 		DUK_ASSERT(tv != NULL);
66445 		DUK_TVAL_SET_TVAL(p_const, tv);
66446 		p_const++;
66447 		DUK_TVAL_INCREF(thr, tv);  /* may be a string constant */
66448 
66449 		DUK_DDD(DUK_DDDPRINT("constant: %!T", (duk_tval *) tv));
66450 	}
66451 
66452 	p_func = (duk_hobject **) p_const;
66453 	DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_res, p_func);
66454 	for (i = 0; i < funcs_count; i++) {
66455 		duk_hobject *h;
66456 		DUK_ASSERT(i * 3 <= DUK_UARRIDX_MAX);  /* func limits */
66457 		tv = duk_hobject_find_array_entry_tval_ptr(thr->heap, func->h_funcs, (duk_uarridx_t) (i * 3));
66458 		DUK_ASSERT(tv != NULL);
66459 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
66460 		h = DUK_TVAL_GET_OBJECT(tv);
66461 		DUK_ASSERT(h != NULL);
66462 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(h));
66463 		*p_func++ = h;
66464 		DUK_HOBJECT_INCREF(thr, h);
66465 
66466 		DUK_DDD(DUK_DDDPRINT("inner function: %p -> %!iO",
66467 		                     (void *) h, (duk_heaphdr *) h));
66468 	}
66469 
66470 	p_instr = (duk_instr_t *) p_func;
66471 	DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, h_res, p_instr);
66472 
66473 	/* copy bytecode instructions one at a time */
66474 	q_instr = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(thr, &func->bw_code);
66475 	for (i = 0; i < code_count; i++) {
66476 		p_instr[i] = q_instr[i].ins;
66477 	}
66478 	/* Note: 'q_instr' is still used below */
66479 
66480 	DUK_ASSERT((duk_uint8_t *) (p_instr + code_count) == DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data) + data_size);
66481 
66482 	duk_pop(thr);  /* 'data' (and everything in it) is reachable through h_res now */
66483 
66484 	/*
66485 	 *  Init non-property result fields
66486 	 *
66487 	 *  'nregs' controls how large a register frame is allocated.
66488 	 *
66489 	 *  'nargs' controls how many formal arguments are written to registers:
66490 	 *  r0, ... r(nargs-1).  The remaining registers are initialized to
66491 	 *  undefined.
66492 	 */
66493 
66494 	DUK_ASSERT(func->temp_max >= 0);
66495 	h_res->nregs = (duk_uint16_t) func->temp_max;
66496 	h_res->nargs = (duk_uint16_t) duk_hobject_get_length(thr, func->h_argnames);
66497 	DUK_ASSERT(h_res->nregs >= h_res->nargs);  /* pass2 allocation handles this */
66498 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66499 	h_res->start_line = (duk_uint32_t) func->min_line;
66500 	h_res->end_line = (duk_uint32_t) func->max_line;
66501 #endif
66502 
66503 	/*
66504 	 *  Init object properties
66505 	 *
66506 	 *  Properties should be added in decreasing order of access frequency.
66507 	 *  (Not very critical for function templates.)
66508 	 */
66509 
66510 	DUK_DDD(DUK_DDDPRINT("init function properties"));
66511 
66512 	/* [ ... res ] */
66513 
66514 	/* _Varmap: omitted if function is guaranteed not to do a slow path
66515 	 * identifier access that might be caught by locally declared variables.
66516 	 * The varmap can also be omitted if it turns out empty of actual
66517 	 * register mappings after a cleanup.  When debugging is enabled, we
66518 	 * always need the varmap to be able to lookup variables at any point.
66519 	 */
66520 
66521 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66522 	DUK_DD(DUK_DDPRINT("keeping _Varmap because debugger support is enabled"));
66523 	keep_varmap = 1;
66524 #else
66525 	if (func->id_access_slow_own ||   /* directly uses slow accesses that may match own variables */
66526 	    func->id_access_arguments ||  /* accesses 'arguments' directly */
66527 	    func->may_direct_eval ||      /* may indirectly slow access through a direct eval */
66528 	    funcs_count > 0) {            /* has inner functions which may slow access (XXX: this can be optimized by looking at the inner functions) */
66529 		DUK_DD(DUK_DDPRINT("keeping _Varmap because of direct eval, slow path access that may match local variables, or presence of inner functions"));
66530 		keep_varmap = 1;
66531 	} else {
66532 		DUK_DD(DUK_DDPRINT("dropping _Varmap"));
66533 		keep_varmap = 0;
66534 	}
66535 #endif
66536 
66537 	if (keep_varmap) {
66538 		duk_int_t num_used;
66539 		duk_dup(thr, func->varmap_idx);
66540 		num_used = duk__cleanup_varmap(comp_ctx);
66541 		DUK_DDD(DUK_DDDPRINT("cleaned up varmap: %!T (num_used=%ld)",
66542 		                     (duk_tval *) duk_get_tval(thr, -1), (long) num_used));
66543 
66544 		if (num_used > 0) {
66545 			duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
66546 		} else {
66547 			DUK_DD(DUK_DDPRINT("varmap is empty after cleanup -> no need to add"));
66548 			duk_pop(thr);
66549 		}
66550 	}
66551 
66552 	/* _Formals: omitted if function is guaranteed not to need a (non-strict)
66553 	 * arguments object, and _Formals.length matches nargs exactly.
66554 	 *
66555 	 * Non-arrow functions can't see an outer function's 'argument' binding
66556 	 * (because they have their own), but arrow functions can.  When arrow
66557 	 * functions are added, this condition would need to be added:
66558 	 *     inner_arrow_funcs_count > 0   inner arrow functions may access 'arguments'
66559 	 */
66560 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66561 	DUK_DD(DUK_DDPRINT("keeping _Formals because debugger support is enabled"));
66562 	keep_formals = 1;
66563 #else
66564 	formals_length = duk_get_length(thr, func->argnames_idx);
66565 	if (formals_length != (duk_size_t) h_res->nargs) {
66566 		/* Nargs not enough for closure .length: keep _Formals regardless
66567 		 * of its length.  Shouldn't happen in practice at the moment.
66568 		 */
66569 		DUK_DD(DUK_DDPRINT("keeping _Formals because _Formals.length != nargs"));
66570 		keep_formals = 1;
66571 	} else if ((func->id_access_arguments || func->may_direct_eval) &&
66572 	           (formals_length > 0)) {
66573 		/* Direct eval (may access 'arguments') or accesses 'arguments'
66574 		 * explicitly: keep _Formals unless it is zero length.
66575 		 */
66576 		DUK_DD(DUK_DDPRINT("keeping _Formals because of direct eval or explicit access to 'arguments', and _Formals.length != 0"));
66577 		keep_formals = 1;
66578 	} else {
66579 		DUK_DD(DUK_DDPRINT("omitting _Formals, nargs matches _Formals.length, so no properties added"));
66580 		keep_formals = 0;
66581 	}
66582 #endif
66583 
66584 	if (keep_formals) {
66585 		duk_dup(thr, func->argnames_idx);
66586 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
66587 	}
66588 
66589 	/* name */
66590 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
66591 	if (func->h_name) {
66592 		duk_push_hstring(thr, func->h_name);
66593 		DUK_DD(DUK_DDPRINT("setting function template .name to %!T", duk_get_tval(thr, -1)));
66594 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
66595 	}
66596 #endif  /* DUK_USE_FUNC_NAME_PROPERTY */
66597 
66598 	/* _Source */
66599 #if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
66600 	if (0) {
66601 		/* XXX: Currently function source code is not stored, as it is not
66602 		 * required by the standard.  Source code should not be stored by
66603 		 * default (user should enable it explicitly), and the source should
66604 		 * probably be compressed with a trivial text compressor; average
66605 		 * compression of 20-30% is quite easy to achieve even with a trivial
66606 		 * compressor (RLE + backwards lookup).
66607 		 *
66608 		 * Debugging needs source code to be useful: sometimes input code is
66609 		 * not found in files as it may be generated and then eval()'d, given
66610 		 * by dynamic C code, etc.
66611 		 *
66612 		 * Other issues:
66613 		 *
66614 		 *   - Need tokenizer indices for start and end to substring
66615 		 *   - Always normalize function declaration part?
66616 		 *   - If we keep _Formals, only need to store body
66617 		 */
66618 
66619 		/*
66620 		 *  For global or eval code this is straightforward.  For functions
66621 		 *  created with the Function constructor we only get the source for
66622 		 *  the body and must manufacture the "function ..." part.
66623 		 *
66624 		 *  For instance, for constructed functions (v8):
66625 		 *
66626 		 *    > a = new Function("foo", "bar", "print(foo)");
66627 		 *    [Function]
66628 		 *    > a.toString()
66629 		 *    'function anonymous(foo,bar) {\nprint(foo)\n}'
66630 		 *
66631 		 *  Similarly for e.g. getters (v8):
66632 		 *
66633 		 *    > x = { get a(foo,bar) { print(foo); } }
66634 		 *    { a: [Getter] }
66635 		 *    > Object.getOwnPropertyDescriptor(x, 'a').get.toString()
66636 		 *    'function a(foo,bar) { print(foo); }'
66637 		 */
66638 
66639 #if 0
66640 		duk_push_literal(thr, "XXX");
66641 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);
66642 #endif
66643 	}
66644 #endif  /* DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY */
66645 
66646 	/* _Pc2line */
66647 #if defined(DUK_USE_PC2LINE)
66648 	if (1) {
66649 		/*
66650 		 *  Size-optimized pc->line mapping.
66651 		 */
66652 
66653 		DUK_ASSERT(code_count <= DUK_COMPILER_MAX_BYTECODE_LENGTH);
66654 		duk_hobject_pc2line_pack(thr, q_instr, (duk_uint_fast32_t) code_count);  /* -> pushes fixed buffer */
66655 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_NONE);
66656 
66657 		/* XXX: if assertions enabled, walk through all valid PCs
66658 		 * and check line mapping.
66659 		 */
66660 	}
66661 #endif  /* DUK_USE_PC2LINE */
66662 
66663 	/* fileName */
66664 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
66665 	if (comp_ctx->h_filename) {
66666 		/*
66667 		 *  Source filename (or equivalent), for identifying thrown errors.
66668 		 */
66669 
66670 		duk_push_hstring(thr, comp_ctx->h_filename);
66671 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_NONE);
66672 	}
66673 #endif
66674 
66675 	DUK_DD(DUK_DDPRINT("converted function: %!ixT",
66676 	                   (duk_tval *) duk_get_tval(thr, -1)));
66677 
66678 	/*
66679 	 *  Compact the function template.
66680 	 */
66681 
66682 	duk_compact_m1(thr);
66683 
66684 	/*
66685 	 *  Debug dumping
66686 	 */
66687 
66688 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
66689 	{
66690 		duk_hcompfunc *h;
66691 		duk_instr_t *p, *p_start, *p_end;
66692 
66693 		h = (duk_hcompfunc *) duk_get_hobject(thr, -1);
66694 		p_start = (duk_instr_t *) DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, h);
66695 		p_end = (duk_instr_t *) DUK_HCOMPFUNC_GET_CODE_END(thr->heap, h);
66696 
66697 		p = p_start;
66698 		while (p < p_end) {
66699 			DUK_DDD(DUK_DDDPRINT("BC %04ld: %!I        ; 0x%08lx op=%ld (%!X) a=%ld b=%ld c=%ld",
66700 			                     (long) (p - p_start),
66701 			                     (duk_instr_t) (*p),
66702 			                     (unsigned long) (*p),
66703 			                     (long) DUK_DEC_OP(*p),
66704 			                     (long) DUK_DEC_OP(*p),
66705 			                     (long) DUK_DEC_A(*p),
66706 			                     (long) DUK_DEC_B(*p),
66707 			                     (long) DUK_DEC_C(*p)));
66708 			p++;
66709 		}
66710 	}
66711 #endif
66712 }
66713 
66714 /*
66715  *  Code emission helpers
66716  *
66717  *  Some emission helpers understand the range of target and source reg/const
66718  *  values and automatically emit shuffling code if necessary.  This is the
66719  *  case when the slot in question (A, B, C) is used in the standard way and
66720  *  for opcodes the emission helpers explicitly understand (like DUK_OP_MPUTOBJ).
66721  *
66722  *  The standard way is that:
66723  *    - slot A is a target register
66724  *    - slot B is a source register/constant
66725  *    - slot C is a source register/constant
66726  *
66727  *  If a slot is used in a non-standard way the caller must indicate this
66728  *  somehow.  If a slot is used as a target instead of a source (or vice
66729  *  versa), this can be indicated with a flag to trigger proper shuffling
66730  *  (e.g. DUK__EMIT_FLAG_B_IS_TARGET).  If the value in the slot is not
66731  *  register/const related at all, the caller must ensure that the raw value
66732  *  fits into the corresponding slot so as to not trigger shuffling.  The
66733  *  caller must set a "no shuffle" flag to ensure compilation fails if
66734  *  shuffling were to be triggered because of an internal error.
66735  *
66736  *  For slots B and C the raw slot size is 9 bits but one bit is reserved for
66737  *  the reg/const indicator.  To use the full 9-bit range for a raw value,
66738  *  shuffling must be disabled with the DUK__EMIT_FLAG_NO_SHUFFLE_{B,C} flag.
66739  *  Shuffling is only done for A, B, and C slots, not the larger BC or ABC slots.
66740  *
66741  *  There is call handling specific understanding in the A-B-C emitter to
66742  *  convert call setup and call instructions into indirect ones if necessary.
66743  */
66744 
66745 /* Code emission flags, passed in the 'opcode' field.  Opcode + flags
66746  * fit into 16 bits for now, so use duk_small_uint_t.
66747  */
66748 #define DUK__EMIT_FLAG_NO_SHUFFLE_A      (1 << 8)
66749 #define DUK__EMIT_FLAG_NO_SHUFFLE_B      (1 << 9)
66750 #define DUK__EMIT_FLAG_NO_SHUFFLE_C      (1 << 10)
66751 #define DUK__EMIT_FLAG_A_IS_SOURCE       (1 << 11)  /* slot A is a source (default: target) */
66752 #define DUK__EMIT_FLAG_B_IS_TARGET       (1 << 12)  /* slot B is a target (default: source) */
66753 #define DUK__EMIT_FLAG_C_IS_TARGET       (1 << 13)  /* slot C is a target (default: source) */
66754 #define DUK__EMIT_FLAG_BC_REGCONST       (1 << 14)  /* slots B and C are reg/const */
66755 #define DUK__EMIT_FLAG_RESERVE_JUMPSLOT  (1 << 15)  /* reserve a jumpslot after instr before target spilling, used for NEXTENUM */
66756 
66757 /* XXX: macro smaller than call? */
66758 DUK_LOCAL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx) {
66759 	duk_compiler_func *func;
66760 	func = &comp_ctx->curr_func;
66761 	return (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &func->bw_code) / sizeof(duk_compiler_instr));
66762 }
66763 
66764 DUK_LOCAL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc) {
66765 	DUK_ASSERT(pc >= 0);
66766 	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)));
66767 	return ((duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code)) + pc;
66768 }
66769 
66770 /* emit instruction; could return PC but that's not needed in the majority
66771  * of cases.
66772  */
66773 DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) {
66774 #if defined(DUK_USE_PC2LINE)
66775 	duk_int_t line;
66776 #endif
66777 	duk_compiler_instr *instr;
66778 
66779 	DUK_DDD(DUK_DDDPRINT("duk__emit: 0x%08lx curr_token.start_line=%ld prev_token.start_line=%ld pc=%ld --> %!I",
66780 	                     (unsigned long) ins,
66781 	                     (long) comp_ctx->curr_token.start_line,
66782 	                     (long) comp_ctx->prev_token.start_line,
66783 	                     (long) duk__get_current_pc(comp_ctx),
66784 	                     (duk_instr_t) ins));
66785 
66786 	instr = (duk_compiler_instr *) (void *) DUK_BW_ENSURE_GETPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
66787 	DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
66788 
66789 #if defined(DUK_USE_PC2LINE)
66790 	/* The line number tracking is a bit inconsistent right now, which
66791 	 * affects debugger accuracy.  Mostly call sites emit opcodes when
66792 	 * they have parsed a token (say a terminating semicolon) and called
66793 	 * duk__advance().  In this case the line number of the previous
66794 	 * token is the most accurate one (except in prologue where
66795 	 * prev_token.start_line is 0).  This is probably not 100% correct
66796 	 * right now.
66797 	 */
66798 	/* approximation, close enough */
66799 	line = comp_ctx->prev_token.start_line;
66800 	if (line == 0) {
66801 		line = comp_ctx->curr_token.start_line;
66802 	}
66803 #endif
66804 
66805 	instr->ins = ins;
66806 #if defined(DUK_USE_PC2LINE)
66807 	instr->line = (duk_uint32_t) line;
66808 #endif
66809 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66810 	if (line < comp_ctx->curr_func.min_line) {
66811 		comp_ctx->curr_func.min_line = line;
66812 	}
66813 	if (line > comp_ctx->curr_func.max_line) {
66814 		comp_ctx->curr_func.max_line = line;
66815 	}
66816 #endif
66817 
66818 	/* Limit checks for bytecode byte size and line number. */
66819 	if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {
66820 		goto fail_bc_limit;
66821 	}
66822 #if defined(DUK_USE_PC2LINE) && defined(DUK_USE_ESBC_LIMITS)
66823 #if defined(DUK_USE_BUFLEN16)
66824 	/* Buffer length is bounded to 0xffff automatically, avoid compile warning. */
66825 	if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {
66826 		goto fail_bc_limit;
66827 	}
66828 #else
66829 	if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {
66830 		goto fail_bc_limit;
66831 	}
66832 #endif
66833 #endif
66834 
66835 	return;
66836 
66837   fail_bc_limit:
66838 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);
66839 	DUK_WO_NORETURN(return;);
66840 }
66841 
66842 /* Update function min/max line from current token.  Needed to improve
66843  * function line range information for debugging, so that e.g. opening
66844  * curly brace is covered by line range even when no opcodes are emitted
66845  * for the line containing the brace.
66846  */
66847 DUK_LOCAL void duk__update_lineinfo_currtoken(duk_compiler_ctx *comp_ctx) {
66848 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66849 	duk_int_t line;
66850 
66851 	line = comp_ctx->curr_token.start_line;
66852 	if (line == 0) {
66853 		return;
66854 	}
66855 	if (line < comp_ctx->curr_func.min_line) {
66856 		comp_ctx->curr_func.min_line = line;
66857 	}
66858 	if (line > comp_ctx->curr_func.max_line) {
66859 		comp_ctx->curr_func.max_line = line;
66860 	}
66861 #else
66862 	DUK_UNREF(comp_ctx);
66863 #endif
66864 }
66865 
66866 DUK_LOCAL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op) {
66867 	duk__emit(comp_ctx, DUK_ENC_OP_ABC(op, 0));
66868 }
66869 
66870 /* Important main primitive. */
66871 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) {
66872 	duk_instr_t ins = 0;
66873 	duk_int_t a_out = -1;
66874 	duk_int_t b_out = -1;
66875 	duk_int_t c_out = -1;
66876 	duk_int_t tmp;
66877 	duk_small_uint_t op = op_flags & 0xffU;
66878 
66879 	DUK_DDD(DUK_DDDPRINT("emit: op_flags=%04lx, a=%ld, b=%ld, c=%ld",
66880 	                     (unsigned long) op_flags, (long) a, (long) b, (long) c));
66881 
66882 	/* We could rely on max temp/const checks: if they don't exceed BC
66883 	 * limit, nothing here can either (just asserts would be enough).
66884 	 * Currently we check for the limits, which provides additional
66885 	 * protection against creating invalid bytecode due to compiler
66886 	 * bugs.
66887 	 */
66888 
66889 	DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN);  /* unsigned */
66890 	DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
66891 	DUK_ASSERT(DUK__ISREG(a));
66892 	DUK_ASSERT(b != -1);  /* Not 'none'. */
66893 	DUK_ASSERT(c != -1);  /* Not 'none'. */
66894 
66895 	/* Input shuffling happens before the actual operation, while output
66896 	 * shuffling happens afterwards.  Output shuffling decisions are still
66897 	 * made at the same time to reduce branch clutter; output shuffle decisions
66898 	 * are recorded into X_out variables.
66899 	 */
66900 
66901 	/* Slot A: currently no support for reg/const. */
66902 
66903 #if defined(DUK_USE_SHUFFLE_TORTURE)
66904 	if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
66905 #else
66906 	if (a <= DUK_BC_A_MAX) {
66907 #endif
66908 		;
66909 	} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
66910 		DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but shuffle prohibited, a: %ld", (long) a));
66911 		goto error_outofregs;
66912 	} else if (a <= DUK_BC_BC_MAX) {
66913 		comp_ctx->curr_func.needs_shuffle = 1;
66914 		tmp = comp_ctx->curr_func.shuffle1;
66915 		if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
66916 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
66917 		} else {
66918 			/* Output shuffle needed after main operation */
66919 			a_out = a;
66920 
66921 			/* The DUK_OP_CSVAR output shuffle assumes shuffle registers are
66922 			 * consecutive.
66923 			 */
66924 			DUK_ASSERT((comp_ctx->curr_func.shuffle1 == 0 && comp_ctx->curr_func.shuffle2 == 0) ||
66925 			           (comp_ctx->curr_func.shuffle2 == comp_ctx->curr_func.shuffle1 + 1));
66926 			if (op == DUK_OP_CSVAR) {
66927 				/* For CSVAR the limit is one smaller because output shuffle
66928 				 * must be able to express 'a + 1' in BC.
66929 				 */
66930 				if (a + 1 > DUK_BC_BC_MAX) {
66931 					goto error_outofregs;
66932 				}
66933 			}
66934 		}
66935 		a = tmp;
66936 	} else {
66937 		DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but does not fit into BC, a: %ld", (long) a));
66938 		goto error_outofregs;
66939 	}
66940 
66941 	/* Slot B: reg/const support, mapped to bit 0 of opcode. */
66942 
66943 	if ((b & DUK__CONST_MARKER) != 0) {
66944 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) == 0);
66945 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
66946 		b = b & ~DUK__CONST_MARKER;
66947 #if defined(DUK_USE_SHUFFLE_TORTURE)
66948 		if (0) {
66949 #else
66950 		if (b <= 0xff) {
66951 #endif
66952 			if (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {
66953 				/* Opcode follows B/C reg/const convention. */
66954 				DUK_ASSERT((op & 0x01) == 0);
66955 				ins |= DUK_ENC_OP_A_B_C(0x01, 0, 0, 0);  /* const flag for B */
66956 			} else {
66957 				DUK_D(DUK_DPRINT("B is const, opcode is not B/C reg/const: %x", op_flags));
66958 			}
66959 		} else if (b <= DUK_BC_BC_MAX) {
66960 			comp_ctx->curr_func.needs_shuffle = 1;
66961 			tmp = comp_ctx->curr_func.shuffle2;
66962 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, b));
66963 			b = tmp;
66964 		} else {
66965 			DUK_D(DUK_DPRINT("out of regs: 'b' (const) needs shuffling but does not fit into BC, b: %ld", (long) b));
66966 			goto error_outofregs;
66967 		}
66968 	} else {
66969 #if defined(DUK_USE_SHUFFLE_TORTURE)
66970 		if (b <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B)) {
66971 #else
66972 		if (b <= 0xff) {
66973 #endif
66974 			;
66975 		} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) {
66976 			if (b > DUK_BC_B_MAX) {
66977 				/* Note: 0xff != DUK_BC_B_MAX */
66978 				DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but shuffle prohibited, b: %ld", (long) b));
66979 				goto error_outofregs;
66980 			}
66981 		} else if (b <= DUK_BC_BC_MAX) {
66982 			comp_ctx->curr_func.needs_shuffle = 1;
66983 			tmp = comp_ctx->curr_func.shuffle2;
66984 			if (op_flags & DUK__EMIT_FLAG_B_IS_TARGET) {
66985 				/* Output shuffle needed after main operation */
66986 				b_out = b;
66987 			}
66988 			if (!(op_flags & DUK__EMIT_FLAG_B_IS_TARGET)) {
66989 				if (op == DUK_OP_MPUTOBJ || op == DUK_OP_MPUTARR) {
66990 					/* Special handling for MPUTOBJ/MPUTARR shuffling.
66991 					 * For each, slot B identifies the first register of a range
66992 					 * of registers, so normal shuffling won't work.  Instead,
66993 					 * an indirect version of the opcode is used.
66994 					 */
66995 					DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
66996 					duk__emit_load_int32_noshuffle(comp_ctx, tmp, b);
66997 					DUK_ASSERT(DUK_OP_MPUTOBJI == DUK_OP_MPUTOBJ + 1);
66998 					DUK_ASSERT(DUK_OP_MPUTARRI == DUK_OP_MPUTARR + 1);
66999 					op_flags++;  /* indirect opcode follows direct */
67000 				} else {
67001 					duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, b));
67002 				}
67003 			}
67004 			b = tmp;
67005 		} else {
67006 			DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but does not fit into BC, b: %ld", (long) b));
67007 			goto error_outofregs;
67008 		}
67009 	}
67010 
67011 	/* Slot C: reg/const support, mapped to bit 1 of opcode. */
67012 
67013 	if ((c & DUK__CONST_MARKER) != 0) {
67014 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) == 0);
67015 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_C_IS_TARGET) == 0);
67016 		c = c & ~DUK__CONST_MARKER;
67017 #if defined(DUK_USE_SHUFFLE_TORTURE)
67018 		if (0) {
67019 #else
67020 		if (c <= 0xff) {
67021 #endif
67022 			if (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {
67023 				/* Opcode follows B/C reg/const convention. */
67024 				DUK_ASSERT((op & 0x02) == 0);
67025 				ins |= DUK_ENC_OP_A_B_C(0x02, 0, 0, 0);  /* const flag for C */
67026 			} else {
67027 				DUK_D(DUK_DPRINT("C is const, opcode is not B/C reg/const: %x", op_flags));
67028 			}
67029 		} else if (c <= DUK_BC_BC_MAX) {
67030 			comp_ctx->curr_func.needs_shuffle = 1;
67031 			tmp = comp_ctx->curr_func.shuffle3;
67032 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, c));
67033 			c = tmp;
67034 		} else {
67035 			DUK_D(DUK_DPRINT("out of regs: 'c' (const) needs shuffling but does not fit into BC, c: %ld", (long) c));
67036 			goto error_outofregs;
67037 		}
67038 	} else {
67039 #if defined(DUK_USE_SHUFFLE_TORTURE)
67040 		if (c <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C)) {
67041 #else
67042 		if (c <= 0xff) {
67043 #endif
67044 			;
67045 		} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) {
67046 			if (c > DUK_BC_C_MAX) {
67047 				/* Note: 0xff != DUK_BC_C_MAX */
67048 				DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but shuffle prohibited, c: %ld", (long) c));
67049 				goto error_outofregs;
67050 			}
67051 		} else if (c <= DUK_BC_BC_MAX) {
67052 			comp_ctx->curr_func.needs_shuffle = 1;
67053 			tmp = comp_ctx->curr_func.shuffle3;
67054 			if (op_flags & DUK__EMIT_FLAG_C_IS_TARGET) {
67055 				/* Output shuffle needed after main operation */
67056 				c_out = c;
67057 			} else {
67058 				duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, c));
67059 			}
67060 			c = tmp;
67061 		} else {
67062 			DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but does not fit into BC, c: %ld", (long) c));
67063 			goto error_outofregs;
67064 		}
67065 	}
67066 
67067 	/* Main operation */
67068 
67069 	DUK_ASSERT(a >= DUK_BC_A_MIN);
67070 	DUK_ASSERT(a <= DUK_BC_A_MAX);
67071 	DUK_ASSERT(b >= DUK_BC_B_MIN);
67072 	DUK_ASSERT(b <= DUK_BC_B_MAX);
67073 	DUK_ASSERT(c >= DUK_BC_C_MIN);
67074 	DUK_ASSERT(c <= DUK_BC_C_MAX);
67075 
67076 	ins |= DUK_ENC_OP_A_B_C(op_flags & 0xff, a, b, c);
67077 	duk__emit(comp_ctx, ins);
67078 
67079 	/* NEXTENUM needs a jump slot right after the main instruction.
67080 	 * When the JUMP is taken, output spilling is not needed so this
67081 	 * workaround is possible.  The jump slot PC is exceptionally
67082 	 * plumbed through comp_ctx to minimize call sites.
67083 	 */
67084 	if (op_flags & DUK__EMIT_FLAG_RESERVE_JUMPSLOT) {
67085 		comp_ctx->emit_jumpslot_pc = duk__get_current_pc(comp_ctx);
67086 		duk__emit_abc(comp_ctx, DUK_OP_JUMP, 0);
67087 	}
67088 
67089 	/* Output shuffling: only one output register is realistically possible.
67090 	 *
67091 	 * (Zero would normally be an OK marker value: if the target register
67092 	 * was zero, it would never be shuffled.  But with DUK_USE_SHUFFLE_TORTURE
67093 	 * this is no longer true, so use -1 as a marker instead.)
67094 	 */
67095 
67096 	if (a_out >= 0) {
67097 		DUK_ASSERT(b_out < 0);
67098 		DUK_ASSERT(c_out < 0);
67099 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a, a_out));
67100 
67101 		if (op == DUK_OP_CSVAR) {
67102 			/* Special handling for CSVAR shuffling.  The variable lookup
67103 			 * results in a <value, this binding> pair in successive
67104 			 * registers so use two shuffle registers and two output
67105 			 * loads.  (In practice this is dead code because temp/const
67106 			 * limit is reached first.)
67107 			 */
67108 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a + 1, a_out + 1));
67109 		}
67110 	} else if (b_out >= 0) {
67111 		DUK_ASSERT(a_out < 0);
67112 		DUK_ASSERT(c_out < 0);
67113 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, b, b_out));
67114 	} else if (c_out >= 0) {
67115 		DUK_ASSERT(b_out < 0);
67116 		DUK_ASSERT(c_out < 0);
67117 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, c, c_out));
67118 	}
67119 
67120 	return;
67121 
67122  error_outofregs:
67123 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
67124 	DUK_WO_NORETURN(return;);
67125 }
67126 
67127 /* For many of the helpers below it'd be technically correct to add
67128  * "no shuffle" flags for parameters passed in as zero.  For example,
67129  * duk__emit_a_b() should call duk__emit_a_b_c() with C set to 0, and
67130  * DUK__EMIT_FLAG_NO_SHUFFLE_C added to op_flags.  However, since the
67131  * C value is 0, it'll never get shuffled so adding the flag is just
67132  * unnecessary additional code.  This is unfortunately not true for
67133  * "shuffle torture" mode which needs special handling.
67134  */
67135 
67136 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) {
67137 #if defined(DUK_USE_SHUFFLE_TORTURE)
67138 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_C;
67139 #endif
67140 	duk__emit_a_b_c(comp_ctx, op_flags, a, b, 0);
67141 }
67142 
67143 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) {
67144 #if defined(DUK_USE_SHUFFLE_TORTURE)
67145 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_A;
67146 #endif
67147 	duk__emit_a_b_c(comp_ctx, op_flags, 0, b, c);
67148 }
67149 
67150 #if 0  /* unused */
67151 DUK_LOCAL void duk__emit_a(duk_compiler_ctx *comp_ctx, int op_flags, int a) {
67152 #if defined(DUK_USE_SHUFFLE_TORTURE)
67153 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_B | DUK__EMIT_FLAG_NO_SHUFFLE_C;
67154 #endif
67155 	duk__emit_a_b_c(comp_ctx, op_flags, a, 0, 0);
67156 }
67157 #endif
67158 
67159 #if 0  /* unused */
67160 DUK_LOCAL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b) {
67161 #if defined(DUK_USE_SHUFFLE_TORTURE)
67162 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_NO_SHUFFLE_C;
67163 #endif
67164 	duk__emit_a_b_c(comp_ctx, op_flags, 0, b, 0);
67165 }
67166 #endif
67167 
67168 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) {
67169 	duk_instr_t ins;
67170 	duk_int_t tmp;
67171 
67172 	/* allow caller to give a const number with the DUK__CONST_MARKER */
67173 	DUK_ASSERT(bc != -1);  /* Not 'none'. */
67174 	bc = bc & (~DUK__CONST_MARKER);
67175 
67176 	DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN);  /* unsigned */
67177 	DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
67178 	DUK_ASSERT(bc >= DUK_BC_BC_MIN);
67179 	DUK_ASSERT(bc <= DUK_BC_BC_MAX);
67180 	DUK_ASSERT((bc & DUK__CONST_MARKER) == 0);
67181 
67182 	if (bc <= DUK_BC_BC_MAX) {
67183 		;
67184 	} else {
67185 		/* No BC shuffling now. */
67186 		goto error_outofregs;
67187 	}
67188 
67189 #if defined(DUK_USE_SHUFFLE_TORTURE)
67190 	if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
67191 #else
67192 	if (a <= DUK_BC_A_MAX) {
67193 #endif
67194 		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, a, bc);
67195 		duk__emit(comp_ctx, ins);
67196 	} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
67197 		goto error_outofregs;
67198 	} else if ((op_flags & 0xf0U) == DUK_OP_CALL0) {
67199 		comp_ctx->curr_func.needs_shuffle = 1;
67200 		tmp = comp_ctx->curr_func.shuffle1;
67201 		duk__emit_load_int32_noshuffle(comp_ctx, tmp, a);
67202 		op_flags |= DUK_BC_CALL_FLAG_INDIRECT;
67203 		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);
67204 		duk__emit(comp_ctx, ins);
67205 	} else if (a <= DUK_BC_BC_MAX) {
67206 		comp_ctx->curr_func.needs_shuffle = 1;
67207 		tmp = comp_ctx->curr_func.shuffle1;
67208 		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);
67209 		if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
67210 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
67211 			duk__emit(comp_ctx, ins);
67212 		} else {
67213 			duk__emit(comp_ctx, ins);
67214 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, tmp, a));
67215 		}
67216 	} else {
67217 		goto error_outofregs;
67218 	}
67219 	return;
67220 
67221  error_outofregs:
67222 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
67223 	DUK_WO_NORETURN(return;);
67224 }
67225 
67226 DUK_LOCAL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc) {
67227 #if defined(DUK_USE_SHUFFLE_TORTURE)
67228 	op |= DUK__EMIT_FLAG_NO_SHUFFLE_A;
67229 #endif
67230 	duk__emit_a_bc(comp_ctx, op, 0, bc);
67231 }
67232 
67233 DUK_LOCAL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc) {
67234 	duk_instr_t ins;
67235 
67236 	DUK_ASSERT_DISABLE(op >= DUK_BC_OP_MIN);  /* unsigned */
67237 	DUK_ASSERT(op <= DUK_BC_OP_MAX);
67238 	DUK_ASSERT_DISABLE(abc >= DUK_BC_ABC_MIN);  /* unsigned */
67239 	DUK_ASSERT(abc <= DUK_BC_ABC_MAX);
67240 	DUK_ASSERT((abc & DUK__CONST_MARKER) == 0);
67241 	DUK_ASSERT(abc != -1);  /* Not 'none'. */
67242 
67243 	if (abc <= DUK_BC_ABC_MAX) {
67244 		;
67245 	} else {
67246 		goto error_outofregs;
67247 	}
67248 	ins = DUK_ENC_OP_ABC(op, abc);
67249 	DUK_DDD(DUK_DDDPRINT("duk__emit_abc: 0x%08lx line=%ld pc=%ld op=%ld (%!X) abc=%ld (%!I)",
67250 	                     (unsigned long) ins, (long) comp_ctx->curr_token.start_line,
67251 	                     (long) duk__get_current_pc(comp_ctx), (long) op, (long) op,
67252 	                     (long) abc, (duk_instr_t) ins));
67253 	duk__emit(comp_ctx, ins);
67254 	return;
67255 
67256  error_outofregs:
67257 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
67258 	DUK_WO_NORETURN(return;);
67259 }
67260 
67261 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) {
67262 	/* XXX: Shuffling support could be implemented here so that LDINT+LDINTX
67263 	 * would only shuffle once (instead of twice).  The current code works
67264 	 * though, and has a smaller compiler footprint.
67265 	 */
67266 
67267 	if ((val >= (duk_int32_t) DUK_BC_BC_MIN - (duk_int32_t) DUK_BC_LDINT_BIAS) &&
67268 	    (val <= (duk_int32_t) DUK_BC_BC_MAX - (duk_int32_t) DUK_BC_LDINT_BIAS)) {
67269 		DUK_DDD(DUK_DDDPRINT("emit LDINT to reg %ld for %ld", (long) reg, (long) val));
67270 		duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (val + (duk_int32_t) DUK_BC_LDINT_BIAS));
67271 	} else {
67272 		duk_int32_t hi = val >> DUK_BC_LDINTX_SHIFT;
67273 		duk_int32_t lo = val & ((((duk_int32_t) 1) << DUK_BC_LDINTX_SHIFT) - 1);
67274 		DUK_ASSERT(lo >= 0);
67275 		DUK_DDD(DUK_DDDPRINT("emit LDINT+LDINTX to reg %ld for %ld -> hi %ld, lo %ld",
67276 		                     (long) reg, (long) val, (long) hi, (long) lo));
67277 		duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (hi + (duk_int32_t) DUK_BC_LDINT_BIAS));
67278 		duk__emit_a_bc(comp_ctx, DUK_OP_LDINTX | op_flags, reg, (duk_regconst_t) lo);
67279 	}
67280 }
67281 
67282 DUK_LOCAL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
67283 	duk__emit_load_int32_raw(comp_ctx, reg, val, 0 /*op_flags*/);
67284 }
67285 
67286 #if defined(DUK_USE_SHUFFLE_TORTURE)
67287 /* Used by duk__emit*() calls so that we don't shuffle the loadints that
67288  * are needed to handle indirect opcodes.
67289  */
67290 DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
67291 	duk__emit_load_int32_raw(comp_ctx, reg, val, DUK__EMIT_FLAG_NO_SHUFFLE_A /*op_flags*/);
67292 }
67293 #else
67294 DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
67295 	/* When torture not enabled, can just use the same helper because
67296 	 * 'reg' won't get spilled.
67297 	 */
67298 	DUK_ASSERT(reg <= DUK_BC_A_MAX);
67299 	duk__emit_load_int32(comp_ctx, reg, val);
67300 }
67301 #endif
67302 
67303 DUK_LOCAL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc) {
67304 	duk_int_t curr_pc;
67305 	duk_int_t offset;
67306 
67307 	curr_pc = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
67308 	offset = (duk_int_t) target_pc - (duk_int_t) curr_pc - 1;
67309 	DUK_ASSERT(offset + DUK_BC_JUMP_BIAS >= DUK_BC_ABC_MIN);
67310 	DUK_ASSERT(offset + DUK_BC_JUMP_BIAS <= DUK_BC_ABC_MAX);
67311 	duk__emit_abc(comp_ctx, DUK_OP_JUMP, (duk_regconst_t) (offset + DUK_BC_JUMP_BIAS));
67312 }
67313 
67314 DUK_LOCAL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx) {
67315 	duk_int_t ret;
67316 
67317 	ret = duk__get_current_pc(comp_ctx);  /* useful for patching jumps later */
67318 	duk__emit_op_only(comp_ctx, DUK_OP_JUMP);
67319 	return ret;
67320 }
67321 
67322 /* Insert an empty jump in the middle of code emitted earlier.  This is
67323  * currently needed for compiling for-in.
67324  */
67325 DUK_LOCAL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
67326 #if defined(DUK_USE_PC2LINE)
67327 	duk_int_t line;
67328 #endif
67329 	duk_compiler_instr *instr;
67330 	duk_size_t offset;
67331 
67332 	DUK_ASSERT(jump_pc >= 0);
67333 	offset = (duk_size_t) jump_pc * sizeof(duk_compiler_instr);
67334 	instr = (duk_compiler_instr *) (void *)
67335 	        DUK_BW_INSERT_ENSURE_AREA(comp_ctx->thr,
67336 	                                  &comp_ctx->curr_func.bw_code,
67337 	                                  offset,
67338 	                                  sizeof(duk_compiler_instr));
67339 
67340 #if defined(DUK_USE_PC2LINE)
67341 	line = comp_ctx->curr_token.start_line;  /* approximation, close enough */
67342 #endif
67343 	instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, 0);
67344 #if defined(DUK_USE_PC2LINE)
67345 	instr->line = (duk_uint32_t) line;
67346 #endif
67347 
67348 	DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
67349 	if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {
67350 		goto fail_bc_limit;
67351 	}
67352 	return;
67353 
67354   fail_bc_limit:
67355 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);
67356 	DUK_WO_NORETURN(return;);
67357 }
67358 
67359 /* Does not assume that jump_pc contains a DUK_OP_JUMP previously; this is intentional
67360  * to allow e.g. an INVALID opcode be overwritten with a JUMP (label management uses this).
67361  */
67362 DUK_LOCAL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc) {
67363 	duk_compiler_instr *instr;
67364 	duk_int_t offset;
67365 
67366 	/* allow negative PCs, behave as a no-op */
67367 	if (jump_pc < 0) {
67368 		DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): nop call, jump_pc=%ld (<0), target_pc=%ld",
67369 		                     (long) jump_pc, (long) target_pc));
67370 		return;
67371 	}
67372 	DUK_ASSERT(jump_pc >= 0);
67373 
67374 	/* XXX: range assert */
67375 	instr = duk__get_instr_ptr(comp_ctx, jump_pc);
67376 	DUK_ASSERT(instr != NULL);
67377 
67378 	/* XXX: range assert */
67379 	offset = target_pc - jump_pc - 1;
67380 
67381 	instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, offset + DUK_BC_JUMP_BIAS);
67382 	DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): jump_pc=%ld, target_pc=%ld, offset=%ld",
67383 	                     (long) jump_pc, (long) target_pc, (long) offset));
67384 }
67385 
67386 DUK_LOCAL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
67387 	duk__patch_jump(comp_ctx, jump_pc, duk__get_current_pc(comp_ctx));
67388 }
67389 
67390 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) {
67391 	duk_compiler_instr *instr;
67392 
67393 	DUK_ASSERT(DUK__ISREG(reg_catch));
67394 
67395 	instr = duk__get_instr_ptr(comp_ctx, ldconst_pc);
67396 	DUK_ASSERT(DUK_DEC_OP(instr->ins) == DUK_OP_LDCONST);
67397 	DUK_ASSERT(instr != NULL);
67398 	if (const_varname & DUK__CONST_MARKER) {
67399 		/* Have a catch variable. */
67400 		const_varname = const_varname & (~DUK__CONST_MARKER);
67401 		if (reg_catch > DUK_BC_BC_MAX || const_varname > DUK_BC_BC_MAX) {
67402 			/* Catch attempts to use out-of-range reg/const.  Without this
67403 			 * check Duktape 0.12.0 could generate invalid code which caused
67404 			 * an assert failure on execution.  This error is triggered e.g.
67405 			 * for functions with a lot of constants and a try-catch statement.
67406 			 * Shuffling or opcode semantics change is needed to fix the issue.
67407 			 * See: test-bug-trycatch-many-constants.js.
67408 			 */
67409 			DUK_D(DUK_DPRINT("failed to patch trycatch: flags=%ld, reg_catch=%ld, const_varname=%ld (0x%08lx)",
67410 			                 (long) flags, (long) reg_catch, (long) const_varname, (long) const_varname));
67411 			DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
67412 			DUK_WO_NORETURN(return;);
67413 		}
67414 		instr->ins |= DUK_ENC_OP_A_BC(0, 0, const_varname);
67415 	} else {
67416 		/* No catch variable, e.g. a try-finally; replace LDCONST with
67417 		 * NOP to avoid a bogus LDCONST.
67418 		 */
67419 		instr->ins = DUK_ENC_OP(DUK_OP_NOP);
67420 	}
67421 
67422 	instr = duk__get_instr_ptr(comp_ctx, trycatch_pc);
67423 	DUK_ASSERT(instr != NULL);
67424 	DUK_ASSERT_DISABLE(flags >= DUK_BC_A_MIN);
67425 	DUK_ASSERT(flags <= DUK_BC_A_MAX);
67426 	instr->ins = DUK_ENC_OP_A_BC(DUK_OP_TRYCATCH, flags, reg_catch);
67427 }
67428 
67429 DUK_LOCAL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
67430 	duk_small_uint_t op;
67431 
67432 	op = DUK__ISREG(regconst) ? DUK_OP_IFFALSE_R : DUK_OP_IFFALSE_C;
67433 	duk__emit_bc(comp_ctx, op, regconst);  /* helper will remove const flag */
67434 }
67435 
67436 DUK_LOCAL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
67437 	duk_small_uint_t op;
67438 
67439 	op = DUK__ISREG(regconst) ? DUK_OP_IFTRUE_R : DUK_OP_IFTRUE_C;
67440 	duk__emit_bc(comp_ctx, op, regconst);  /* helper will remove const flag */
67441 }
67442 
67443 DUK_LOCAL void duk__emit_invalid(duk_compiler_ctx *comp_ctx) {
67444 	duk__emit_op_only(comp_ctx, DUK_OP_INVALID);
67445 }
67446 
67447 /*
67448  *  Peephole optimizer for finished bytecode.
67449  *
67450  *  Does not remove opcodes; currently only straightens out unconditional
67451  *  jump chains which are generated by several control structures.
67452  */
67453 
67454 DUK_LOCAL void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx) {
67455 	duk_compiler_instr *bc;
67456 	duk_small_uint_t iter;
67457 	duk_int_t i, n;
67458 	duk_int_t count_opt;
67459 
67460 	bc = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code);
67461 #if defined(DUK_USE_BUFLEN16)
67462 	/* No need to assert, buffer size maximum is 0xffff. */
67463 #else
67464 	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 */
67465 #endif
67466 	n = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
67467 
67468 	for (iter = 0; iter < DUK_COMPILER_PEEPHOLE_MAXITER; iter++) {
67469 		count_opt = 0;
67470 
67471 		for (i = 0; i < n; i++) {
67472 			duk_instr_t ins;
67473 			duk_int_t target_pc1;
67474 			duk_int_t target_pc2;
67475 
67476 			ins = bc[i].ins;
67477 			if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
67478 				continue;
67479 			}
67480 
67481 			target_pc1 = i + 1 + (duk_int_t) DUK_DEC_ABC(ins) - (duk_int_t) DUK_BC_JUMP_BIAS;
67482 			DUK_DDD(DUK_DDDPRINT("consider jump at pc %ld; target_pc=%ld", (long) i, (long) target_pc1));
67483 			DUK_ASSERT(target_pc1 >= 0);
67484 			DUK_ASSERT(target_pc1 < n);
67485 
67486 			/* Note: if target_pc1 == i, we'll optimize a jump to itself.
67487 			 * This does not need to be checked for explicitly; the case
67488 			 * is rare and max iter breaks us out.
67489 			 */
67490 
67491 			ins = bc[target_pc1].ins;
67492 			if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
67493 				continue;
67494 			}
67495 
67496 			target_pc2 = target_pc1 + 1 + (duk_int_t) DUK_DEC_ABC(ins) - (duk_int_t) DUK_BC_JUMP_BIAS;
67497 
67498 			DUK_DDD(DUK_DDDPRINT("optimizing jump at pc %ld; old target is %ld -> new target is %ld",
67499 			                     (long) i, (long) target_pc1, (long) target_pc2));
67500 
67501 			bc[i].ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, target_pc2 - (i + 1) + DUK_BC_JUMP_BIAS);
67502 
67503 			count_opt++;
67504 		}
67505 
67506 		DUK_DD(DUK_DDPRINT("optimized %ld jumps on peephole round %ld", (long) count_opt, (long) (iter + 1)));
67507 
67508 		if (count_opt == 0) {
67509 			break;
67510 		}
67511 	}
67512 }
67513 
67514 /*
67515  *  Intermediate value helpers
67516  */
67517 
67518 /* Flags for intermediate value coercions.  A flag for using a forced reg
67519  * is not needed, the forced_reg argument suffices and generates better
67520  * code (it is checked as it is used).
67521  */
67522 /* XXX: DUK__IVAL_FLAG_REQUIRE_SHORT is passed but not currently implemented
67523  * by ispec/ivalue operations.
67524  */
67525 #define DUK__IVAL_FLAG_ALLOW_CONST          (1 << 0)  /* allow a constant to be returned */
67526 #define DUK__IVAL_FLAG_REQUIRE_TEMP         (1 << 1)  /* require a (mutable) temporary as a result (or a const if allowed) */
67527 #define DUK__IVAL_FLAG_REQUIRE_SHORT        (1 << 2)  /* require a short (8-bit) reg/const which fits into bytecode B/C slot */
67528 
67529 /* XXX: some code might benefit from DUK__SETTEMP_IFTEMP(thr,x) */
67530 
67531 #if 0  /* enable manually for dumping */
67532 #define DUK__DUMP_ISPEC(compctx,ispec) do { duk__dump_ispec((compctx), (ispec)); } while (0)
67533 #define DUK__DUMP_IVALUE(compctx,ivalue) do { duk__dump_ivalue((compctx), (ivalue)); } while (0)
67534 
67535 DUK_LOCAL void duk__dump_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *x) {
67536 	DUK_D(DUK_DPRINT("ispec dump: t=%ld regconst=0x%08lx, valstack_idx=%ld, value=%!T",
67537 	                 (long) x->t, (unsigned long) x->regconst, (long) x->valstack_idx,
67538 	                 duk_get_tval(comp_ctx->thr, x->valstack_idx)));
67539 }
67540 DUK_LOCAL void duk__dump_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
67541 	DUK_D(DUK_DPRINT("ivalue dump: t=%ld op=%ld "
67542 	                 "x1={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T} "
67543 	                 "x2={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T}",
67544 		         (long) x->t, (long) x->op,
67545 	                 (long) x->x1.t, (unsigned long) x->x1.regconst, (long) x->x1.valstack_idx,
67546 	                 duk_get_tval(comp_ctx->thr, x->x1.valstack_idx),
67547 	                 (long) x->x2.t, (unsigned long) x->x2.regconst, (long) x->x2.valstack_idx,
67548 	                 duk_get_tval(comp_ctx->thr, x->x2.valstack_idx)));
67549 }
67550 #else
67551 #define DUK__DUMP_ISPEC(comp_ctx,x) do {} while (0)
67552 #define DUK__DUMP_IVALUE(comp_ctx,x) do {} while (0)
67553 #endif
67554 
67555 DUK_LOCAL void duk__ivalue_regconst(duk_ivalue *x, duk_regconst_t regconst) {
67556 	x->t = DUK_IVAL_PLAIN;
67557 	x->x1.t = DUK_ISPEC_REGCONST;
67558 	x->x1.regconst = regconst;
67559 }
67560 
67561 DUK_LOCAL void duk__ivalue_plain_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
67562 	x->t = DUK_IVAL_PLAIN;
67563 	x->x1.t = DUK_ISPEC_VALUE;
67564 	duk_replace(comp_ctx->thr, x->x1.valstack_idx);
67565 }
67566 
67567 DUK_LOCAL void duk__ivalue_var_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
67568 	x->t = DUK_IVAL_VAR;
67569 	x->x1.t = DUK_ISPEC_VALUE;
67570 	duk_replace(comp_ctx->thr, x->x1.valstack_idx);
67571 }
67572 
67573 DUK_LOCAL_DECL void duk__ivalue_var_hstring(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_hstring *h) {
67574 	DUK_ASSERT(h != NULL);
67575 	duk_push_hstring(comp_ctx->thr, h);
67576 	duk__ivalue_var_fromstack(comp_ctx, x);
67577 }
67578 
67579 DUK_LOCAL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst) {
67580 	dst->t = src->t;
67581 	dst->regconst = src->regconst;
67582 	duk_copy(comp_ctx->thr, src->valstack_idx, dst->valstack_idx);
67583 }
67584 
67585 DUK_LOCAL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst) {
67586 	dst->t = src->t;
67587 	dst->op = src->op;
67588 	dst->x1.t = src->x1.t;
67589 	dst->x1.regconst = src->x1.regconst;
67590 	dst->x2.t = src->x2.t;
67591 	dst->x2.regconst = src->x2.regconst;
67592 	duk_copy(comp_ctx->thr, src->x1.valstack_idx, dst->x1.valstack_idx);
67593 	duk_copy(comp_ctx->thr, src->x2.valstack_idx, dst->x2.valstack_idx);
67594 }
67595 
67596 DUK_LOCAL duk_regconst_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num) {
67597 	duk_regconst_t res;
67598 
67599 	res = comp_ctx->curr_func.temp_next;
67600 	comp_ctx->curr_func.temp_next += num;
67601 
67602 	if (comp_ctx->curr_func.temp_next > DUK__MAX_TEMPS) {  /* == DUK__MAX_TEMPS is OK */
67603 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_TEMP_LIMIT);
67604 		DUK_WO_NORETURN(return 0;);
67605 	}
67606 
67607 	/* maintain highest 'used' temporary, needed to figure out nregs of function */
67608 	if (comp_ctx->curr_func.temp_next > comp_ctx->curr_func.temp_max) {
67609 		comp_ctx->curr_func.temp_max = comp_ctx->curr_func.temp_next;
67610 	}
67611 
67612 	return res;
67613 }
67614 
67615 DUK_LOCAL duk_regconst_t duk__alloctemp(duk_compiler_ctx *comp_ctx) {
67616 	return duk__alloctemps(comp_ctx, 1);
67617 }
67618 
67619 DUK_LOCAL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_regconst_t temp_next) {
67620 	comp_ctx->curr_func.temp_next = temp_next;
67621 	if (temp_next > comp_ctx->curr_func.temp_max) {
67622 		comp_ctx->curr_func.temp_max = temp_next;
67623 	}
67624 }
67625 
67626 /* get const for value at valstack top */
67627 DUK_LOCAL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx) {
67628 	duk_hthread *thr = comp_ctx->thr;
67629 	duk_compiler_func *f = &comp_ctx->curr_func;
67630 	duk_tval *tv1;
67631 	duk_int_t i, n, n_check;
67632 
67633 	n = (duk_int_t) duk_get_length(thr, f->consts_idx);
67634 
67635 	tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
67636 	DUK_ASSERT(tv1 != NULL);
67637 
67638 #if defined(DUK_USE_FASTINT)
67639 	/* Explicit check for fastint downgrade. */
67640 	DUK_TVAL_CHKFAST_INPLACE_SLOW(tv1);
67641 #endif
67642 
67643 	/* Sanity workaround for handling functions with a large number of
67644 	 * constants at least somewhat reasonably.  Otherwise checking whether
67645 	 * we already have the constant would grow very slow (as it is O(N^2)).
67646 	 */
67647 	n_check = (n > DUK__GETCONST_MAX_CONSTS_CHECK ? DUK__GETCONST_MAX_CONSTS_CHECK : n);
67648 	for (i = 0; i < n_check; i++) {
67649 		duk_tval *tv2 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, f->h_consts, i);
67650 
67651 		/* Strict equality is NOT enough, because we cannot use the same
67652 		 * constant for e.g. +0 and -0.
67653 		 */
67654 		if (duk_js_samevalue(tv1, tv2)) {
67655 			DUK_DDD(DUK_DDDPRINT("reused existing constant for %!T -> const index %ld",
67656 			                     (duk_tval *) tv1, (long) i));
67657 			duk_pop(thr);
67658 			return (duk_regconst_t) i | (duk_regconst_t) DUK__CONST_MARKER;
67659 		}
67660 	}
67661 
67662 	if (n > DUK__MAX_CONSTS) {
67663 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_CONST_LIMIT);
67664 		DUK_WO_NORETURN(return 0;);
67665 	}
67666 
67667 	DUK_DDD(DUK_DDDPRINT("allocating new constant for %!T -> const index %ld",
67668 	                     (duk_tval *) tv1, (long) n));
67669 	(void) duk_put_prop_index(thr, f->consts_idx, (duk_uarridx_t) n);  /* invalidates tv1, tv2 */
67670 	return (duk_regconst_t) n | (duk_regconst_t) DUK__CONST_MARKER;
67671 }
67672 
67673 DUK_LOCAL duk_bool_t duk__const_needs_refcount(duk_compiler_ctx *comp_ctx, duk_regconst_t rc) {
67674 #if defined(DUK_USE_REFERENCE_COUNTING)
67675 	duk_compiler_func *f = &comp_ctx->curr_func;
67676 	duk_bool_t ret;
67677 
67678 	DUK_ASSERT((rc & DUK__CONST_MARKER) == 0);  /* caller removes const marker */
67679 	(void) duk_get_prop_index(comp_ctx->thr, f->consts_idx, (duk_uarridx_t) rc);
67680 	ret = !duk_is_number(comp_ctx->thr, -1);  /* now only number/string, so conservative check */
67681 	duk_pop(comp_ctx->thr);
67682 	return ret;
67683 #else
67684 	DUK_UNREF(comp_ctx);
67685 	DUK_UNREF(rc);
67686 	DUK_ASSERT((rc & DUK__CONST_MARKER) == 0);  /* caller removes const marker */
67687 	return 0;
67688 #endif
67689 }
67690 
67691 /* Get the value represented by an duk_ispec to a register or constant.
67692  * The caller can control the result by indicating whether or not:
67693  *
67694  *   (1) a constant is allowed (sometimes the caller needs the result to
67695  *       be in a register)
67696  *
67697  *   (2) a temporary register is required (usually when caller requires
67698  *       the register to be safely mutable; normally either a bound
67699  *       register or a temporary register are both OK)
67700  *
67701  *   (3) a forced register target needs to be used
67702  *
67703  * Bytecode may be emitted to generate the necessary value.  The return
67704  * value is either a register or a constant.
67705  */
67706 
67707 DUK_LOCAL
67708 duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
67709                                          duk_ispec *x,
67710                                          duk_regconst_t forced_reg,
67711                                          duk_small_uint_t flags) {
67712 	duk_hthread *thr = comp_ctx->thr;
67713 
67714 	DUK_DDD(DUK_DDDPRINT("duk__ispec_toregconst_raw(): x={%ld:%ld:%!T}, "
67715 	                     "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
67716 	                     (long) x->t,
67717 	                     (long) x->regconst,
67718 	                     (duk_tval *) duk_get_tval(thr, x->valstack_idx),
67719 	                     (long) forced_reg,
67720 	                     (unsigned long) flags,
67721 	                     (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
67722 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
67723 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
67724 
67725 	switch (x->t) {
67726 	case DUK_ISPEC_VALUE: {
67727 		duk_tval *tv;
67728 
67729 		tv = DUK_GET_TVAL_POSIDX(thr, x->valstack_idx);
67730 		DUK_ASSERT(tv != NULL);
67731 
67732 		switch (DUK_TVAL_GET_TAG(tv)) {
67733 		case DUK_TAG_UNDEFINED: {
67734 			/* Note: although there is no 'undefined' literal, undefined
67735 			 * values can occur during compilation as a result of e.g.
67736 			 * the 'void' operator.
67737 			 */
67738 			duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67739 			duk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, dest);
67740 			return dest;
67741 		}
67742 		case DUK_TAG_NULL: {
67743 			duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67744 			duk__emit_bc(comp_ctx, DUK_OP_LDNULL, dest);
67745 			return dest;
67746 		}
67747 		case DUK_TAG_BOOLEAN: {
67748 			duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67749 			duk__emit_bc(comp_ctx,
67750 			             (DUK_TVAL_GET_BOOLEAN(tv) ? DUK_OP_LDTRUE : DUK_OP_LDFALSE),
67751 			             dest);
67752 			return dest;
67753 		}
67754 		case DUK_TAG_POINTER: {
67755 			DUK_UNREACHABLE();
67756 			break;
67757 		}
67758 		case DUK_TAG_STRING: {
67759 			duk_hstring *h;
67760 			duk_regconst_t dest;
67761 			duk_regconst_t constidx;
67762 
67763 			h = DUK_TVAL_GET_STRING(tv);
67764 			DUK_UNREF(h);
67765 			DUK_ASSERT(h != NULL);
67766 
67767 #if 0  /* XXX: to be implemented? */
67768 			/* Use special opcodes to load short strings */
67769 			if (DUK_HSTRING_GET_BYTELEN(h) <= 2) {
67770 				/* Encode into a single opcode (18 bits can encode 1-2 bytes + length indicator) */
67771 			} else if (DUK_HSTRING_GET_BYTELEN(h) <= 6) {
67772 				/* Encode into a double constant (53 bits can encode 6*8 = 48 bits + 3-bit length */
67773 			}
67774 #endif
67775 			duk_dup(thr, x->valstack_idx);
67776 			constidx = duk__getconst(comp_ctx);
67777 
67778 			if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
67779 				return constidx;
67780 			}
67781 
67782 			dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67783 			duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, constidx);
67784 			return dest;
67785 		}
67786 		case DUK_TAG_OBJECT: {
67787 			DUK_UNREACHABLE();
67788 			break;
67789 		}
67790 		case DUK_TAG_BUFFER: {
67791 			DUK_UNREACHABLE();
67792 			break;
67793 		}
67794 		case DUK_TAG_LIGHTFUNC: {
67795 			DUK_UNREACHABLE();
67796 			break;
67797 		}
67798 #if defined(DUK_USE_FASTINT)
67799 		case DUK_TAG_FASTINT:
67800 #endif
67801 		default: {
67802 			/* number */
67803 			duk_regconst_t dest;
67804 			duk_regconst_t constidx;
67805 			duk_double_t dval;
67806 			duk_int32_t ival;
67807 
67808 			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
67809 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
67810 			dval = DUK_TVAL_GET_NUMBER(tv);
67811 
67812 			if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
67813 				/* A number can be loaded either through a constant, using
67814 				 * LDINT, or using LDINT+LDINTX.  LDINT is always a size win,
67815 				 * LDINT+LDINTX is not if the constant is used multiple times.
67816 				 * Currently always prefer LDINT+LDINTX over a double constant.
67817 				 */
67818 
67819 				if (duk_is_whole_get_int32_nonegzero(dval, &ival)) {
67820 					dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67821 					duk__emit_load_int32(comp_ctx, dest, ival);
67822 					return dest;
67823 				}
67824 			}
67825 
67826 			duk_dup(thr, x->valstack_idx);
67827 			constidx = duk__getconst(comp_ctx);
67828 
67829 			if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
67830 				return constidx;
67831 			} else {
67832 				dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67833 				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, constidx);
67834 				return dest;
67835 			}
67836 		}
67837 		}  /* end switch */
67838 		goto fail_internal;  /* never here */
67839 	}
67840 	case DUK_ISPEC_REGCONST: {
67841 		if (forced_reg >= 0) {
67842 			if (DUK__ISCONST(x->regconst)) {
67843 				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, forced_reg, x->regconst);
67844 			} else if (x->regconst != forced_reg) {
67845 				duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, forced_reg, x->regconst);
67846 			} else {
67847 				; /* already in correct reg */
67848 			}
67849 			return forced_reg;
67850 		}
67851 
67852 		DUK_ASSERT(forced_reg < 0);
67853 		if (DUK__ISCONST(x->regconst)) {
67854 			if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
67855 				duk_regconst_t dest = DUK__ALLOCTEMP(comp_ctx);
67856 				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, x->regconst);
67857 				return dest;
67858 			}
67859 			return x->regconst;
67860 		}
67861 
67862 		DUK_ASSERT(forced_reg < 0 && !DUK__ISCONST(x->regconst));
67863 		if ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) && !DUK__ISREG_TEMP(comp_ctx, x->regconst)) {
67864 			duk_regconst_t dest = DUK__ALLOCTEMP(comp_ctx);
67865 			duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, dest, x->regconst);
67866 			return dest;
67867 		}
67868 		return x->regconst;
67869 	}
67870 	default: {
67871 		break;  /* never here */
67872 	}
67873 	}
67874 
67875  fail_internal:
67876 	DUK_ERROR_INTERNAL(thr);
67877 	DUK_WO_NORETURN(return 0;);
67878 }
67879 
67880 DUK_LOCAL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_regconst_t forced_reg) {
67881 	DUK_ASSERT(forced_reg >= 0);
67882 	(void) duk__ispec_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
67883 }
67884 
67885 /* Coerce an duk_ivalue to a 'plain' value by generating the necessary
67886  * arithmetic operations, property access, or variable access bytecode.
67887  * The duk_ivalue argument ('x') is converted into a plain value as a
67888  * side effect.
67889  */
67890 DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_regconst_t forced_reg) {
67891 	duk_hthread *thr = comp_ctx->thr;
67892 
67893 	DUK_DDD(DUK_DDDPRINT("duk__ivalue_toplain_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
67894 	                     "forced_reg=%ld",
67895 	                     (long) x->t, (long) x->op,
67896 	                     (long) x->x1.t, (long) x->x1.regconst,
67897 	                     (duk_tval *) duk_get_tval(thr, x->x1.valstack_idx),
67898 	                     (long) x->x2.t, (long) x->x2.regconst,
67899 	                     (duk_tval *) duk_get_tval(thr, x->x2.valstack_idx),
67900 	                     (long) forced_reg));
67901 
67902 	switch (x->t) {
67903 	case DUK_IVAL_PLAIN: {
67904 		return;
67905 	}
67906 	/* XXX: support unary arithmetic ivalues (useful?) */
67907 	case DUK_IVAL_ARITH: {
67908 		duk_regconst_t arg1;
67909 		duk_regconst_t arg2;
67910 		duk_regconst_t dest;
67911 		duk_tval *tv1;
67912 		duk_tval *tv2;
67913 
67914 		DUK_DDD(DUK_DDDPRINT("arith to plain conversion"));
67915 
67916 		/* inline arithmetic check for constant values */
67917 		/* XXX: use the exactly same arithmetic function here as in executor */
67918 		if (x->x1.t == DUK_ISPEC_VALUE && x->x2.t == DUK_ISPEC_VALUE && x->t == DUK_IVAL_ARITH) {
67919 			tv1 = DUK_GET_TVAL_POSIDX(thr, x->x1.valstack_idx);
67920 			tv2 = DUK_GET_TVAL_POSIDX(thr, x->x2.valstack_idx);
67921 			DUK_ASSERT(tv1 != NULL);
67922 			DUK_ASSERT(tv2 != NULL);
67923 
67924 			DUK_DDD(DUK_DDDPRINT("arith: tv1=%!T, tv2=%!T",
67925 			                     (duk_tval *) tv1,
67926 			                     (duk_tval *) tv2));
67927 
67928 			if (DUK_TVAL_IS_NUMBER(tv1) && DUK_TVAL_IS_NUMBER(tv2)) {
67929 				duk_double_t d1 = DUK_TVAL_GET_NUMBER(tv1);
67930 				duk_double_t d2 = DUK_TVAL_GET_NUMBER(tv2);
67931 				duk_double_t d3;
67932 				duk_bool_t accept_fold = 1;
67933 
67934 				DUK_DDD(DUK_DDDPRINT("arith inline check: d1=%lf, d2=%lf, op=%ld",
67935 				                     (double) d1, (double) d2, (long) x->op));
67936 				switch (x->op) {
67937 				case DUK_OP_ADD: {
67938 					d3 = d1 + d2;
67939 					break;
67940 				}
67941 				case DUK_OP_SUB: {
67942 					d3 = d1 - d2;
67943 					break;
67944 				}
67945 				case DUK_OP_MUL: {
67946 					d3 = d1 * d2;
67947 					break;
67948 				}
67949 				case DUK_OP_DIV: {
67950 					/* Division-by-zero is undefined
67951 					 * behavior, so rely on a helper.
67952 					 */
67953 					d3 = duk_double_div(d1, d2);
67954 					break;
67955 				}
67956 				case DUK_OP_EXP: {
67957 					d3 = (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);
67958 					break;
67959 				}
67960 				default: {
67961 					d3 = 0.0;  /* Won't be used, but silence MSVC /W4 warning. */
67962 					accept_fold = 0;
67963 					break;
67964 				}
67965 				}
67966 
67967 				if (accept_fold) {
67968 					duk_double_union du;
67969 					du.d = d3;
67970 					DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
67971 					d3 = du.d;
67972 
67973 					x->t = DUK_IVAL_PLAIN;
67974 					DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
67975 					DUK_TVAL_SET_NUMBER(tv1, d3);  /* old value is number: no refcount */
67976 					return;
67977 				}
67978 			} else if (x->op == DUK_OP_ADD && DUK_TVAL_IS_STRING(tv1) && DUK_TVAL_IS_STRING(tv2)) {
67979 				/* Inline string concatenation.  No need to check for
67980 				 * symbols, as all inputs are valid ECMAScript strings.
67981 				 */
67982 				duk_dup(thr, x->x1.valstack_idx);
67983 				duk_dup(thr, x->x2.valstack_idx);
67984 				duk_concat(thr, 2);
67985 				duk_replace(thr, x->x1.valstack_idx);
67986 				x->t = DUK_IVAL_PLAIN;
67987 				DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
67988 				return;
67989 			}
67990 		}
67991 
67992 		arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
67993 		arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
67994 
67995 		/* If forced reg, use it as destination.  Otherwise try to
67996 		 * use either coerced ispec if it is a temporary.
67997 		 */
67998 		if (forced_reg >= 0) {
67999 			dest = forced_reg;
68000 		} else if (DUK__ISREG_TEMP(comp_ctx, arg1)) {
68001 			dest = arg1;
68002 		} else if (DUK__ISREG_TEMP(comp_ctx, arg2)) {
68003 			dest = arg2;
68004 		} else {
68005 			dest = DUK__ALLOCTEMP(comp_ctx);
68006 		}
68007 
68008 		DUK_ASSERT(DUK__ISREG(dest));
68009 		duk__emit_a_b_c(comp_ctx, x->op | DUK__EMIT_FLAG_BC_REGCONST, dest, arg1, arg2);
68010 
68011 		duk__ivalue_regconst(x, dest);
68012 		return;
68013 	}
68014 	case DUK_IVAL_PROP: {
68015 		/* XXX: very similar to DUK_IVAL_ARITH - merge? */
68016 		duk_regconst_t arg1;
68017 		duk_regconst_t arg2;
68018 		duk_regconst_t dest;
68019 
68020 		/* Need a short reg/const, does not have to be a mutable temp. */
68021 		arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
68022 		arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
68023 
68024 		/* Pick a destination register.  If either base value or key
68025 		 * happens to be a temp value, reuse it as the destination.
68026 		 *
68027 		 * XXX: The temp must be a "mutable" one, i.e. such that no
68028 		 * other expression is using it anymore.  Here this should be
68029 		 * the case because the value of a property access expression
68030 		 * is neither the base nor the key, but the lookup result.
68031 		 */
68032 
68033 		if (forced_reg >= 0) {
68034 			dest = forced_reg;
68035 		} else if (DUK__ISREG_TEMP(comp_ctx, arg1)) {
68036 			dest = arg1;
68037 		} else if (DUK__ISREG_TEMP(comp_ctx, arg2)) {
68038 			dest = arg2;
68039 		} else {
68040 			dest = DUK__ALLOCTEMP(comp_ctx);
68041 		}
68042 
68043 		duk__emit_a_b_c(comp_ctx,
68044 		                DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST,
68045 		                dest,
68046 		                arg1,
68047 		                arg2);
68048 
68049 		duk__ivalue_regconst(x, dest);
68050 		return;
68051 	}
68052 	case DUK_IVAL_VAR: {
68053 		/* x1 must be a string */
68054 		duk_regconst_t dest;
68055 		duk_regconst_t reg_varbind;
68056 		duk_regconst_t rc_varname;
68057 
68058 		DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
68059 
68060 		duk_dup(thr, x->x1.valstack_idx);
68061 		if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
68062 			duk__ivalue_regconst(x, reg_varbind);
68063 		} else {
68064 			dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
68065 			duk__emit_a_bc(comp_ctx, DUK_OP_GETVAR, dest, rc_varname);
68066 			duk__ivalue_regconst(x, dest);
68067 		}
68068 		return;
68069 	}
68070 	case DUK_IVAL_NONE:
68071 	default: {
68072 		DUK_D(DUK_DPRINT("invalid ivalue type: %ld", (long) x->t));
68073 		break;
68074 	}
68075 	}
68076 
68077 	DUK_ERROR_INTERNAL(thr);
68078 	DUK_WO_NORETURN(return;);
68079 }
68080 
68081 /* evaluate to plain value, no forced register (temp/bound reg both ok) */
68082 DUK_LOCAL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
68083 	duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
68084 }
68085 
68086 /* evaluate to final form (e.g. coerce GETPROP to code), throw away temp */
68087 DUK_LOCAL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
68088 	duk_regconst_t temp;
68089 
68090 	/* If duk__ivalue_toplain_raw() allocates a temp, forget it and
68091 	 * restore next temp state.
68092 	 */
68093 	temp = DUK__GETTEMP(comp_ctx);
68094 	duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
68095 	DUK__SETTEMP(comp_ctx, temp);
68096 }
68097 
68098 /* Coerce an duk_ivalue to a register or constant; result register may
68099  * be a temp or a bound register.
68100  *
68101  * The duk_ivalue argument ('x') is converted into a regconst as a
68102  * side effect.
68103  */
68104 DUK_LOCAL
68105 duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
68106                                           duk_ivalue *x,
68107                                           duk_regconst_t forced_reg,
68108                                           duk_small_uint_t flags) {
68109 	duk_hthread *thr = comp_ctx->thr;
68110 	duk_regconst_t reg;
68111 	DUK_UNREF(thr);
68112 
68113 	DUK_DDD(DUK_DDDPRINT("duk__ivalue_toregconst_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
68114 	                     "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
68115 	                     (long) x->t, (long) x->op,
68116 	                     (long) x->x1.t, (long) x->x1.regconst,
68117 	                     (duk_tval *) duk_get_tval(thr, x->x1.valstack_idx),
68118 	                     (long) x->x2.t, (long) x->x2.regconst,
68119 	                     (duk_tval *) duk_get_tval(thr, x->x2.valstack_idx),
68120 	                     (long) forced_reg,
68121 	                     (unsigned long) flags,
68122 	                     (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
68123 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
68124 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
68125 
68126 	/* first coerce to a plain value */
68127 	duk__ivalue_toplain_raw(comp_ctx, x, forced_reg);
68128 	DUK_ASSERT(x->t == DUK_IVAL_PLAIN);
68129 
68130 	/* then to a register */
68131 	reg = duk__ispec_toregconst_raw(comp_ctx, &x->x1, forced_reg, flags);
68132 	duk__ivalue_regconst(x, reg);
68133 
68134 	return reg;
68135 }
68136 
68137 DUK_LOCAL duk_regconst_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
68138 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, 0 /*flags*/);
68139 }
68140 
68141 #if 0  /* unused */
68142 DUK_LOCAL duk_regconst_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
68143 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
68144 }
68145 #endif
68146 
68147 DUK_LOCAL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg) {
68148 	DUK_ASSERT(forced_reg >= 0);
68149 	(void) duk__ivalue_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
68150 }
68151 
68152 DUK_LOCAL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
68153 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
68154 }
68155 
68156 DUK_LOCAL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
68157 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
68158 }
68159 
68160 /* The issues below can be solved with better flags */
68161 
68162 /* XXX: many operations actually want toforcedtemp() -- brand new temp? */
68163 /* XXX: need a toplain_ignore() which will only coerce a value to a temp
68164  * register if it might have a side effect.  Side-effect free values do not
68165  * need to be coerced.
68166  */
68167 
68168 /*
68169  *  Identifier handling
68170  */
68171 
68172 DUK_LOCAL duk_regconst_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx) {
68173 	duk_hthread *thr = comp_ctx->thr;
68174 	duk_hstring *h_varname;
68175 	duk_regconst_t ret;
68176 
68177 	DUK_DDD(DUK_DDDPRINT("resolving identifier reference to '%!T'",
68178 	                     (duk_tval *) duk_get_tval(thr, -1)));
68179 
68180 	/*
68181 	 *  Special name handling
68182 	 */
68183 
68184 	h_varname = duk_known_hstring(thr, -1);
68185 
68186 	if (h_varname == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)) {
68187 		DUK_DDD(DUK_DDDPRINT("flagging function as accessing 'arguments'"));
68188 		comp_ctx->curr_func.id_access_arguments = 1;
68189 	}
68190 
68191 	/*
68192 	 *  Inside one or more 'with' statements fall back to slow path always.
68193 	 *  (See e.g. test-stmt-with.js.)
68194 	 */
68195 
68196 	if (comp_ctx->curr_func.with_depth > 0) {
68197 		DUK_DDD(DUK_DDDPRINT("identifier lookup inside a 'with' -> fall back to slow path"));
68198 		goto slow_path_own;
68199 	}
68200 
68201 	/*
68202 	 *  Any catch bindings ("catch (e)") also affect identifier binding.
68203 	 *
68204 	 *  Currently, the varmap is modified for the duration of the catch
68205 	 *  clause to ensure any identifier accesses with the catch variable
68206 	 *  name will use slow path.
68207 	 */
68208 
68209 	duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
68210 	if (duk_is_number(thr, -1)) {
68211 		ret = duk_to_int(thr, -1);
68212 		duk_pop(thr);
68213 	} else {
68214 		duk_pop(thr);
68215 		if (comp_ctx->curr_func.catch_depth > 0 || comp_ctx->curr_func.with_depth > 0) {
68216 			DUK_DDD(DUK_DDDPRINT("slow path access from inside a try-catch or with needs _Varmap"));
68217 			goto slow_path_own;
68218 		} else {
68219 			/* In this case we're doing a variable lookup that doesn't
68220 			 * match our own variables, so _Varmap won't be needed at
68221 			 * run time.
68222 			 */
68223 			DUK_DDD(DUK_DDDPRINT("slow path access outside of try-catch and with, no need for _Varmap"));
68224 			goto slow_path_notown;
68225 		}
68226 	}
68227 
68228 	DUK_DDD(DUK_DDDPRINT("identifier lookup -> reg %ld", (long) ret));
68229 	return ret;
68230 
68231  slow_path_notown:
68232 	DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path, not own variable"));
68233 
68234 	comp_ctx->curr_func.id_access_slow = 1;
68235 	return (duk_regconst_t) -1;
68236 
68237  slow_path_own:
68238 	DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path, may be own variable"));
68239 
68240 	comp_ctx->curr_func.id_access_slow = 1;
68241 	comp_ctx->curr_func.id_access_slow_own = 1;
68242 	return (duk_regconst_t) -1;
68243 }
68244 
68245 /* Lookup an identifier name in the current varmap, indicating whether the
68246  * identifier is register-bound and if not, allocating a constant for the
68247  * identifier name.  Returns 1 if register-bound, 0 otherwise.  Caller can
68248  * also check (out_reg_varbind >= 0) to check whether or not identifier is
68249  * register bound.  The caller must NOT use out_rc_varname at all unless
68250  * return code is 0 or out_reg_varbind is < 0; this is becuase out_rc_varname
68251  * is unsigned and doesn't have a "unused" / none value.
68252  */
68253 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) {
68254 	duk_hthread *thr = comp_ctx->thr;
68255 	duk_regconst_t reg_varbind;
68256 	duk_regconst_t rc_varname;
68257 
68258 	/* [ ... varname ] */
68259 
68260 	duk_dup_top(thr);
68261 	reg_varbind = duk__lookup_active_register_binding(comp_ctx);
68262 
68263 	if (reg_varbind >= 0) {
68264 		*out_reg_varbind = reg_varbind;
68265 		*out_rc_varname = 0;  /* duk_regconst_t is unsigned, so use 0 as dummy value (ignored by caller) */
68266 		duk_pop(thr);
68267 		return 1;
68268 	} else {
68269 		rc_varname = duk__getconst(comp_ctx);
68270 		*out_reg_varbind = -1;
68271 		*out_rc_varname = rc_varname;
68272 		return 0;
68273 	}
68274 }
68275 
68276 /*
68277  *  Label handling
68278  *
68279  *  Labels are initially added with flags prohibiting both break and continue.
68280  *  When the statement type is finally uncovered (after potentially multiple
68281  *  labels), all the labels are updated to allow/prohibit break and continue.
68282  */
68283 
68284 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) {
68285 	duk_hthread *thr = comp_ctx->thr;
68286 	duk_size_t n;
68287 	duk_size_t new_size;
68288 	duk_uint8_t *p;
68289 	duk_labelinfo *li_start, *li;
68290 
68291 	/* Duplicate (shadowing) labels are not allowed, except for the empty
68292 	 * labels (which are used as default labels for switch and iteration
68293 	 * statements).
68294 	 *
68295 	 * We could also allow shadowing of non-empty pending labels without any
68296 	 * other issues than breaking the required label shadowing requirements
68297 	 * of the E5 specification, see Section 12.12.
68298 	 */
68299 
68300 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
68301 	li_start = (duk_labelinfo *) (void *) p;
68302 	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
68303 	n = (duk_size_t) (li - li_start);
68304 
68305 	while (li > li_start) {
68306 		li--;
68307 
68308 		if (li->h_label == h_label && h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
68309 			DUK_ERROR_SYNTAX(thr, DUK_STR_DUPLICATE_LABEL);
68310 			DUK_WO_NORETURN(return;);
68311 		}
68312 	}
68313 
68314 	duk_push_hstring(thr, h_label);
68315 	DUK_ASSERT(n <= DUK_UARRIDX_MAX);  /* label limits */
68316 	(void) duk_put_prop_index(thr, comp_ctx->curr_func.labelnames_idx, (duk_uarridx_t) n);
68317 
68318 	new_size = (n + 1) * sizeof(duk_labelinfo);
68319 	duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size);
68320 	/* XXX: slack handling, slow now */
68321 
68322 	/* relookup after possible realloc */
68323 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
68324 	li_start = (duk_labelinfo *) (void *) p;
68325 	DUK_UNREF(li_start);  /* silence scan-build warning */
68326 	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
68327 	li--;
68328 
68329 	/* Labels can be used for iteration statements but also for other statements,
68330 	 * in particular a label can be used for a block statement.  All cases of a
68331 	 * named label accept a 'break' so that flag is set here.  Iteration statements
68332 	 * also allow 'continue', so that flag is updated when we figure out the
68333 	 * statement type.
68334 	 */
68335 
68336 	li->flags = DUK_LABEL_FLAG_ALLOW_BREAK;
68337 	li->label_id = label_id;
68338 	li->h_label = h_label;
68339 	li->catch_depth = comp_ctx->curr_func.catch_depth;   /* catch depth from current func */
68340 	li->pc_label = pc_label;
68341 
68342 	DUK_DDD(DUK_DDDPRINT("registered label: flags=0x%08lx, id=%ld, name=%!O, catch_depth=%ld, pc_label=%ld",
68343 	                     (unsigned long) li->flags, (long) li->label_id, (duk_heaphdr *) li->h_label,
68344 	                     (long) li->catch_depth, (long) li->pc_label));
68345 }
68346 
68347 /* Update all labels with matching label_id. */
68348 DUK_LOCAL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags) {
68349 	duk_uint8_t *p;
68350 	duk_labelinfo *li_start, *li;
68351 
68352 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(comp_ctx->thr->heap, comp_ctx->curr_func.h_labelinfos);
68353 	li_start = (duk_labelinfo *) (void *) p;
68354 	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
68355 
68356 	/* Match labels starting from latest; once label_id no longer matches, we can
68357 	 * safely exit without checking the rest of the labels (only the topmost labels
68358 	 * are ever updated).
68359 	 */
68360 	while (li > li_start) {
68361 		li--;
68362 
68363 		if (li->label_id != label_id) {
68364 			break;
68365 		}
68366 
68367 		DUK_DDD(DUK_DDDPRINT("updating (overwriting) label flags for li=%p, label_id=%ld, flags=%ld",
68368 		                     (void *) li, (long) label_id, (long) flags));
68369 
68370 		li->flags = flags;
68371 	}
68372 }
68373 
68374 /* Lookup active label information.  Break/continue distinction is necessary to handle switch
68375  * statement related labels correctly: a switch will only catch a 'break', not a 'continue'.
68376  *
68377  * An explicit label cannot appear multiple times in the active set, but empty labels (unlabelled
68378  * iteration and switch statements) can.  A break will match the closest unlabelled or labelled
68379  * statement.  A continue will match the closest unlabelled or labelled iteration statement.  It is
68380  * a syntax error if a continue matches a labelled switch statement; because an explicit label cannot
68381  * be duplicated, the continue cannot match any valid label outside the switch.
68382  *
68383  * A side effect of these rules is that a LABEL statement related to a switch should never actually
68384  * catch a continue abrupt completion at run-time.  Hence an INVALID opcode can be placed in the
68385  * continue slot of the switch's LABEL statement.
68386  */
68387 
68388 /* XXX: awkward, especially the bunch of separate output values -> output struct? */
68389 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) {
68390 	duk_hthread *thr = comp_ctx->thr;
68391 	duk_uint8_t *p;
68392 	duk_labelinfo *li_start, *li_end, *li;
68393 	duk_bool_t match = 0;
68394 
68395 	DUK_DDD(DUK_DDDPRINT("looking up active label: label='%!O', is_break=%ld",
68396 	                     (duk_heaphdr *) h_label, (long) is_break));
68397 
68398 	DUK_UNREF(thr);
68399 
68400 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
68401 	li_start = (duk_labelinfo *) (void *) p;
68402 	li_end = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
68403 	li = li_end;
68404 
68405 	/* Match labels starting from latest label because there can be duplicate empty
68406 	 * labels in the label set.
68407 	 */
68408 	while (li > li_start) {
68409 		li--;
68410 
68411 		if (li->h_label != h_label) {
68412 			DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] ->'%!O' != %!O",
68413 			                     (long) (li - li_start),
68414 			                     (duk_heaphdr *) li->h_label,
68415 			                     (duk_heaphdr *) h_label));
68416 			continue;
68417 		}
68418 
68419 		DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] -> '%!O' label name matches (still need to check type)",
68420 		                     (long) (li - li_start), (duk_heaphdr *) h_label));
68421 
68422 		/* currently all labels accept a break, so no explicit check for it now */
68423 		DUK_ASSERT(li->flags & DUK_LABEL_FLAG_ALLOW_BREAK);
68424 
68425 		if (is_break) {
68426 			/* break matches always */
68427 			match = 1;
68428 			break;
68429 		} else if (li->flags & DUK_LABEL_FLAG_ALLOW_CONTINUE) {
68430 			/* iteration statements allow continue */
68431 			match = 1;
68432 			break;
68433 		} else {
68434 			/* continue matched this label -- we can only continue if this is the empty
68435 			 * label, for which duplication is allowed, and thus there is hope of
68436 			 * finding a match deeper in the label stack.
68437 			 */
68438 			if (h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
68439 				DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);
68440 				DUK_WO_NORETURN(return;);
68441 			} else {
68442 				DUK_DDD(DUK_DDDPRINT("continue matched an empty label which does not "
68443 				                     "allow a continue -> continue lookup deeper in label stack"));
68444 			}
68445 		}
68446 	}
68447 	/* XXX: match flag is awkward, rework */
68448 	if (!match) {
68449 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);
68450 		DUK_WO_NORETURN(return;);
68451 	}
68452 
68453 	DUK_DDD(DUK_DDDPRINT("label match: %!O -> label_id %ld, catch_depth=%ld, pc_label=%ld",
68454 	                     (duk_heaphdr *) h_label, (long) li->label_id,
68455 	                     (long) li->catch_depth, (long) li->pc_label));
68456 
68457 	*out_label_id = li->label_id;
68458 	*out_label_catch_depth = li->catch_depth;
68459 	*out_label_pc = li->pc_label;
68460 	*out_is_closest = (li == li_end - 1);
68461 }
68462 
68463 DUK_LOCAL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_size_t len) {
68464 	duk_hthread *thr = comp_ctx->thr;
68465 
68466 	duk_set_length(thr, comp_ctx->curr_func.labelnames_idx, len);
68467 	duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, sizeof(duk_labelinfo) * len);
68468 }
68469 
68470 /*
68471  *  Expression parsing: duk__expr_nud(), duk__expr_led(), duk__expr_lbp(), and helpers.
68472  *
68473  *  - duk__expr_nud(): ("null denotation"): process prev_token as a "start" of an expression (e.g. literal)
68474  *  - duk__expr_led(): ("left denotation"): process prev_token in the "middle" of an expression (e.g. operator)
68475  *  - duk__expr_lbp(): ("left-binding power"): return left-binding power of curr_token
68476  */
68477 
68478 /* object literal key tracking flags */
68479 #define DUK__OBJ_LIT_KEY_PLAIN  (1 << 0)  /* key encountered as a plain property */
68480 #define DUK__OBJ_LIT_KEY_GET    (1 << 1)  /* key encountered as a getter */
68481 #define DUK__OBJ_LIT_KEY_SET    (1 << 2)  /* key encountered as a setter */
68482 
68483 DUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
68484 	duk_hthread *thr = comp_ctx->thr;
68485 	duk_regconst_t reg_obj;                 /* result reg */
68486 	duk_regconst_t reg_temp;                /* temp reg */
68487 	duk_regconst_t temp_start;              /* temp reg value for start of loop */
68488 	duk_small_uint_t max_init_values;  /* max # of values initialized in one MPUTARR set */
68489 	duk_small_uint_t num_values;       /* number of values in current MPUTARR set */
68490 	duk_uarridx_t curr_idx;            /* current (next) array index */
68491 	duk_uarridx_t start_idx;           /* start array index of current MPUTARR set */
68492 	duk_uarridx_t init_idx;            /* last array index explicitly initialized, +1 */
68493 	duk_bool_t require_comma;          /* next loop requires a comma */
68494 #if !defined(DUK_USE_PREFER_SIZE)
68495 	duk_int_t pc_newarr;
68496 	duk_compiler_instr *instr;
68497 #endif
68498 
68499 	/* DUK_TOK_LBRACKET already eaten, current token is right after that */
68500 	DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LBRACKET);
68501 
68502 	max_init_values = DUK__MAX_ARRAY_INIT_VALUES;  /* XXX: depend on available temps? */
68503 
68504 	reg_obj = DUK__ALLOCTEMP(comp_ctx);
68505 #if !defined(DUK_USE_PREFER_SIZE)
68506 	pc_newarr = duk__get_current_pc(comp_ctx);
68507 #endif
68508 	duk__emit_bc(comp_ctx, DUK_OP_NEWARR, reg_obj);  /* XXX: patch initial size hint afterwards? */
68509 	temp_start = DUK__GETTEMP(comp_ctx);
68510 
68511 	/*
68512 	 *  Emit initializers in sets of maximum max_init_values.
68513 	 *  Corner cases such as single value initializers do not have
68514 	 *  special handling now.
68515 	 *
68516 	 *  Elided elements must not be emitted as 'undefined' values,
68517 	 *  because such values would be enumerable (which is incorrect).
68518 	 *  Also note that trailing elisions must be reflected in the
68519 	 *  length of the final array but cause no elements to be actually
68520 	 *  inserted.
68521 	 */
68522 
68523 	curr_idx = 0;
68524 	init_idx = 0;         /* tracks maximum initialized index + 1 */
68525 	start_idx = 0;
68526 	require_comma = 0;
68527 
68528 	for (;;) {
68529 		num_values = 0;
68530 		DUK__SETTEMP(comp_ctx, temp_start);
68531 
68532 		if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
68533 			break;
68534 		}
68535 
68536 		for (;;) {
68537 			if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
68538 				/* the outer loop will recheck and exit */
68539 				break;
68540 			}
68541 
68542 			/* comma check */
68543 			if (require_comma) {
68544 				if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
68545 					/* comma after a value, expected */
68546 					duk__advance(comp_ctx);
68547 					require_comma = 0;
68548 					continue;
68549 				} else {
68550 					goto syntax_error;
68551 				}
68552 			} else {
68553 				if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
68554 					/* elision - flush */
68555 					curr_idx++;
68556 					duk__advance(comp_ctx);
68557 					/* if num_values > 0, MPUTARR emitted by outer loop after break */
68558 					break;
68559 				}
68560 			}
68561 			/* else an array initializer element */
68562 
68563 			/* initial index */
68564 			if (num_values == 0) {
68565 				start_idx = curr_idx;
68566 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
68567 				duk__emit_load_int32(comp_ctx, reg_temp, (duk_int32_t) start_idx);
68568 			}
68569 
68570 			reg_temp = DUK__ALLOCTEMP(comp_ctx);   /* alloc temp just in case, to update max temp */
68571 			DUK__SETTEMP(comp_ctx, reg_temp);
68572 			duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);
68573 			DUK__SETTEMP(comp_ctx, reg_temp + 1);
68574 
68575 			num_values++;
68576 			curr_idx++;
68577 			require_comma = 1;
68578 
68579 			if (num_values >= max_init_values) {
68580 				/* MPUTARR emitted by outer loop */
68581 				break;
68582 			}
68583 		}
68584 
68585 		if (num_values > 0) {
68586 			/* - A is a source register (it's not a write target, but used
68587 			 *   to identify the target object) but can be shuffled.
68588 			 * - B cannot be shuffled normally because it identifies a range
68589 			 *   of registers, the emitter has special handling for this
68590 			 *   (the "no shuffle" flag must not be set).
68591 			 * - C is a non-register number and cannot be shuffled, but
68592 			 *   never needs to be.
68593 			 */
68594 			duk__emit_a_b_c(comp_ctx,
68595 			                DUK_OP_MPUTARR |
68596 			                    DUK__EMIT_FLAG_NO_SHUFFLE_C |
68597 			                    DUK__EMIT_FLAG_A_IS_SOURCE,
68598 			                reg_obj,
68599 			                temp_start,
68600 			                (duk_regconst_t) (num_values + 1));
68601 			init_idx = start_idx + num_values;
68602 
68603 			/* num_values and temp_start reset at top of outer loop */
68604 		}
68605 	}
68606 
68607 	/* Update initil size for NEWARR, doesn't need to be exact and is
68608 	 * capped at A field limit.
68609 	 */
68610 #if !defined(DUK_USE_PREFER_SIZE)
68611 	instr = duk__get_instr_ptr(comp_ctx, pc_newarr);
68612 	instr->ins |= DUK_ENC_OP_A(0, curr_idx > DUK_BC_A_MAX ? DUK_BC_A_MAX : curr_idx);
68613 #endif
68614 
68615 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RBRACKET);
68616 	duk__advance(comp_ctx);
68617 
68618 	DUK_DDD(DUK_DDDPRINT("array literal done, curridx=%ld, initidx=%ld",
68619 	                     (long) curr_idx, (long) init_idx));
68620 
68621 	/* trailing elisions? */
68622 	if (curr_idx > init_idx) {
68623 		/* yes, must set array length explicitly */
68624 		DUK_DDD(DUK_DDDPRINT("array literal has trailing elisions which affect its length"));
68625 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
68626 		duk__emit_load_int32(comp_ctx, reg_temp, (duk_int_t) curr_idx);
68627 		duk__emit_a_bc(comp_ctx,
68628 		               DUK_OP_SETALEN | DUK__EMIT_FLAG_A_IS_SOURCE,
68629 		               reg_obj,
68630 		               reg_temp);
68631 	}
68632 
68633 	DUK__SETTEMP(comp_ctx, temp_start);
68634 
68635 	duk__ivalue_regconst(res, reg_obj);
68636 	return;
68637 
68638  syntax_error:
68639 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARRAY_LITERAL);
68640 	DUK_WO_NORETURN(return;);
68641 }
68642 
68643 typedef struct {
68644 	duk_regconst_t reg_obj;
68645 	duk_regconst_t temp_start;
68646 	duk_small_uint_t num_pairs;
68647 	duk_small_uint_t num_total_pairs;
68648 } duk__objlit_state;
68649 
68650 DUK_LOCAL void duk__objlit_flush_keys(duk_compiler_ctx *comp_ctx, duk__objlit_state *st) {
68651 	if (st->num_pairs > 0) {
68652 		/* - A is a source register (it's not a write target, but used
68653 		 *   to identify the target object) but can be shuffled.
68654 		 * - B cannot be shuffled normally because it identifies a range
68655 		 *   of registers, the emitter has special handling for this
68656 		 *   (the "no shuffle" flag must not be set).
68657 		 * - C is a non-register number and cannot be shuffled, but
68658 		 *   never needs to be.
68659 		 */
68660 		DUK_ASSERT(st->num_pairs > 0);
68661 		duk__emit_a_b_c(comp_ctx,
68662 		                DUK_OP_MPUTOBJ |
68663 		                    DUK__EMIT_FLAG_NO_SHUFFLE_C |
68664 		                    DUK__EMIT_FLAG_A_IS_SOURCE,
68665 		                st->reg_obj,
68666 		                st->temp_start,
68667 		                (duk_regconst_t) (st->num_pairs * 2));
68668 		st->num_total_pairs += st->num_pairs;
68669 		st->num_pairs = 0;
68670 	}
68671 	DUK__SETTEMP(comp_ctx, st->temp_start);
68672 }
68673 
68674 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) {
68675 	if (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t_nores == DUK_TOK_STRING) {
68676 		/* same handling for identifiers and strings */
68677 		DUK_ASSERT(tok->str1 != NULL);
68678 		duk_push_hstring(comp_ctx->thr, tok->str1);
68679 	} else if (tok->t == DUK_TOK_NUMBER) {
68680 		/* numbers can be loaded as numbers and coerced on the fly */
68681 		duk_push_number(comp_ctx->thr, tok->num);
68682 	} else {
68683 		return 1;  /* error */
68684 	}
68685 
68686 	duk__ivalue_plain_fromstack(comp_ctx, res);
68687 	DUK__SETTEMP(comp_ctx, reg_temp + 1);
68688 	duk__ivalue_toforcedreg(comp_ctx, res, reg_temp);
68689 	DUK__SETTEMP(comp_ctx, reg_temp + 1);
68690 	return 0;
68691 }
68692 
68693 DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
68694 	duk_hthread *thr = comp_ctx->thr;
68695 	duk__objlit_state st;
68696 	duk_regconst_t reg_temp;          /* temp reg */
68697 	duk_small_uint_t max_init_pairs;  /* max # of key-value pairs initialized in one MPUTOBJ set */
68698 	duk_bool_t first;                 /* first value: comma must not precede the value */
68699 	duk_bool_t is_set, is_get;        /* temps */
68700 #if !defined(DUK_USE_PREFER_SIZE)
68701 	duk_int_t pc_newobj;
68702 	duk_compiler_instr *instr;
68703 #endif
68704 
68705 	DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LCURLY);
68706 
68707 	max_init_pairs = DUK__MAX_OBJECT_INIT_PAIRS;  /* XXX: depend on available temps? */
68708 
68709 	st.reg_obj = DUK__ALLOCTEMP(comp_ctx);    /* target object */
68710 	st.temp_start = DUK__GETTEMP(comp_ctx);   /* start of MPUTOBJ argument list */
68711 	st.num_pairs = 0;                         /* number of key/value pairs emitted for current MPUTOBJ set */
68712 	st.num_total_pairs = 0;                   /* number of key/value pairs emitted overall */
68713 
68714 #if !defined(DUK_USE_PREFER_SIZE)
68715 	pc_newobj = duk__get_current_pc(comp_ctx);
68716 #endif
68717 	duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, st.reg_obj);
68718 
68719 	/*
68720 	 *  Emit initializers in sets of maximum max_init_pairs keys.
68721 	 *  Setter/getter is handled separately and terminates the
68722 	 *  current set of initializer values.  Corner cases such as
68723 	 *  single value initializers do not have special handling now.
68724 	 */
68725 
68726 	first = 1;
68727 	for (;;) {
68728 		/*
68729 		 *  ES5 and ES2015+ provide a lot of different PropertyDefinition
68730 		 *  formats, see http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer.
68731 		 *
68732 		 *  PropertyName can be IdentifierName (includes reserved words), a string
68733 		 *  literal, or a number literal.  Note that IdentifierName allows 'get' and
68734 		 *  'set' too, so we need to look ahead to the next token to distinguish:
68735 		 *
68736 		 *     { get : 1 }
68737 		 *
68738 		 *  and
68739 		 *
68740 		 *     { get foo() { return 1 } }
68741 		 *     { get get() { return 1 } }    // 'get' as getter propertyname
68742 		 *
68743 		 *  Finally, a trailing comma is allowed.
68744 		 *
68745 		 *  Key name is coerced to string at compile time (and ends up as a
68746 		 *  a string constant) even for numeric keys (e.g. "{1:'foo'}").
68747 		 *  These could be emitted using e.g. LDINT, but that seems hardly
68748 		 *  worth the effort and would increase code size.
68749 		 */
68750 
68751 		DUK_DDD(DUK_DDDPRINT("object literal loop, curr_token->t = %ld",
68752 		                     (long) comp_ctx->curr_token.t));
68753 
68754 		if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
68755 			break;
68756 		}
68757 
68758 		if (first) {
68759 			first = 0;
68760 		} else {
68761 			if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
68762 				goto syntax_error;
68763 			}
68764 			duk__advance(comp_ctx);
68765 			if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
68766 				/* trailing comma followed by rcurly */
68767 				break;
68768 			}
68769 		}
68770 
68771 		/* Advance to get one step of lookup. */
68772 		duk__advance(comp_ctx);
68773 
68774 		/* Flush current MPUTOBJ if enough many pairs gathered. */
68775 		if (st.num_pairs >= max_init_pairs) {
68776 			duk__objlit_flush_keys(comp_ctx, &st);
68777 			DUK_ASSERT(st.num_pairs == 0);
68778 		}
68779 
68780 		/* Reset temp register state and reserve reg_temp and
68781 		 * reg_temp + 1 for handling the current property.
68782 		 */
68783 		DUK__SETTEMP(comp_ctx, st.temp_start + 2 * (duk_regconst_t) st.num_pairs);
68784 		reg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);
68785 
68786 		/* NOTE: "get" and "set" are not officially ReservedWords and the lexer
68787 		 * currently treats them always like ordinary identifiers (DUK_TOK_GET
68788 		 * and DUK_TOK_SET are unused).  They need to be detected based on the
68789 		 * identifier string content.
68790 		 */
68791 
68792 		is_get = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
68793 		          comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_GET(thr));
68794 		is_set = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
68795 		          comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_SET(thr));
68796 		if ((is_get || is_set) && comp_ctx->curr_token.t != DUK_TOK_COLON) {
68797 			/* getter/setter */
68798 			duk_int_t fnum;
68799 
68800 			duk__objlit_flush_keys(comp_ctx, &st);
68801 			DUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start);  /* 2 regs are guaranteed to be allocated w.r.t. temp_max */
68802 			reg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);
68803 
68804 			if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->curr_token, reg_temp) != 0) {
68805 				goto syntax_error;
68806 			}
68807 
68808 			/* curr_token = get/set name */
68809 			fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_GETSET);
68810 
68811 			duk__emit_a_bc(comp_ctx,
68812 			               DUK_OP_CLOSURE,
68813 			               st.temp_start + 1,
68814 			               (duk_regconst_t) fnum);
68815 
68816 			/* Slot C is used in a non-standard fashion (range of regs),
68817 			 * emitter code has special handling for it (must not set the
68818 			 * "no shuffle" flag).
68819 			 */
68820 			duk__emit_a_bc(comp_ctx,
68821 			              (is_get ? DUK_OP_INITGET : DUK_OP_INITSET) | DUK__EMIT_FLAG_A_IS_SOURCE,
68822 			              st.reg_obj,
68823 			              st.temp_start);   /* temp_start+0 = key, temp_start+1 = closure */
68824 
68825 			DUK_ASSERT(st.num_pairs == 0);  /* temp state is reset on next loop */
68826 #if defined(DUK_USE_ES6)
68827 		} else if (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
68828 		           (comp_ctx->curr_token.t == DUK_TOK_COMMA || comp_ctx->curr_token.t == DUK_TOK_RCURLY)) {
68829 			duk_bool_t load_rc;
68830 
68831 			load_rc = duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp);
68832 			DUK_UNREF(load_rc);
68833 			DUK_ASSERT(load_rc == 0);  /* always succeeds because token is identifier */
68834 
68835 			duk__ivalue_var_hstring(comp_ctx, res, comp_ctx->prev_token.str1);
68836 			DUK_ASSERT(DUK__GETTEMP(comp_ctx) == reg_temp + 1);
68837 			duk__ivalue_toforcedreg(comp_ctx, res, reg_temp + 1);
68838 
68839 			st.num_pairs++;
68840 		} else if ((comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER ||
68841 		            comp_ctx->prev_token.t == DUK_TOK_STRING ||
68842 		            comp_ctx->prev_token.t == DUK_TOK_NUMBER) &&
68843 		           comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
68844 			duk_int_t fnum;
68845 
68846 			/* Parsing-wise there's a small hickup here: the token parsing
68847 			 * state is one step too advanced for the function parse helper
68848 			 * compared to other cases.  The current solution is an extra
68849 			 * flag to indicate whether function parsing should use the
68850 			 * current or the previous token to starting parsing from.
68851 			 */
68852 
68853 			if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {
68854 				goto syntax_error;
68855 			}
68856 
68857 			fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_USE_PREVTOKEN | DUK__FUNC_FLAG_METDEF);
68858 
68859 			duk__emit_a_bc(comp_ctx,
68860 			               DUK_OP_CLOSURE,
68861 			               reg_temp + 1,
68862 			               (duk_regconst_t) fnum);
68863 
68864 			st.num_pairs++;
68865 #endif  /* DUK_USE_ES6 */
68866 		} else {
68867 #if defined(DUK_USE_ES6)
68868 			if (comp_ctx->prev_token.t == DUK_TOK_LBRACKET) {
68869 				/* ES2015 computed property name.  Executor ToPropertyKey()
68870 				 * coerces the key at runtime.
68871 				 */
68872 				DUK__SETTEMP(comp_ctx, reg_temp);
68873 				duk__expr_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR, reg_temp);
68874 				duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);
68875 
68876 				/* XXX: If next token is '(' we're dealing with
68877 				 * the method shorthand with a computed name,
68878 				 * e.g. { [Symbol.for('foo')](a,b) {} }.  This
68879 				 * form is not yet supported and causes a
68880 				 * SyntaxError on the DUK_TOK_COLON check below.
68881 				 */
68882 			}
68883 			else
68884 #endif  /* DUK_USE_ES6 */
68885 			{
68886 				if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {
68887 					goto syntax_error;
68888 				}
68889 			}
68890 
68891 			duk__advance_expect(comp_ctx, DUK_TOK_COLON);
68892 
68893 			DUK__SETTEMP(comp_ctx, reg_temp + 1);
68894 			duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp + 1 /*forced_reg*/);
68895 
68896 			st.num_pairs++;
68897 		}
68898 	}  /* property loop */
68899 
68900 	/* Flush remaining properties. */
68901 	duk__objlit_flush_keys(comp_ctx, &st);
68902 	DUK_ASSERT(st.num_pairs == 0);
68903 	DUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start);
68904 
68905 	/* Update initial size for NEWOBJ.  The init size doesn't need to be
68906 	 * exact as the purpose is just to avoid object resizes in common
68907 	 * cases.  The size is capped to field A limit, and will be too high
68908 	 * if the object literal contains duplicate keys (this is harmless but
68909 	 * increases memory traffic if the object is compacted later on).
68910 	 */
68911 #if !defined(DUK_USE_PREFER_SIZE)
68912 	instr = duk__get_instr_ptr(comp_ctx, pc_newobj);
68913 	instr->ins |= DUK_ENC_OP_A(0, st.num_total_pairs > DUK_BC_A_MAX ? DUK_BC_A_MAX : st.num_total_pairs);
68914 #endif
68915 
68916 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
68917 	duk__advance(comp_ctx);  /* No RegExp after object literal. */
68918 
68919 	duk__ivalue_regconst(res, st.reg_obj);
68920 	return;
68921 
68922  syntax_error:
68923 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_OBJECT_LITERAL);
68924 	DUK_WO_NORETURN(return;);
68925 }
68926 
68927 /* Parse argument list.  Arguments are written to temps starting from
68928  * "next temp".  Returns number of arguments parsed.  Expects left paren
68929  * to be already eaten, and eats the right paren before returning.
68930  */
68931 DUK_LOCAL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
68932 	duk_int_t nargs = 0;
68933 	duk_regconst_t reg_temp;
68934 
68935 	/* Note: expect that caller has already eaten the left paren */
68936 
68937 	DUK_DDD(DUK_DDDPRINT("start parsing arguments, prev_token.t=%ld, curr_token.t=%ld",
68938 	                     (long) comp_ctx->prev_token.t, (long) comp_ctx->curr_token.t));
68939 
68940 	for (;;) {
68941 		if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
68942 			break;
68943 		}
68944 		if (nargs > 0) {
68945 			duk__advance_expect(comp_ctx, DUK_TOK_COMMA);
68946 		}
68947 
68948 		/* We want the argument expression value to go to "next temp"
68949 		 * without additional moves.  That should almost always be the
68950 		 * case, but we double check after expression parsing.
68951 		 *
68952 		 * This is not the cleanest possible approach.
68953 		 */
68954 
68955 		reg_temp = DUK__ALLOCTEMP(comp_ctx);  /* bump up "allocated" reg count, just in case */
68956 		DUK__SETTEMP(comp_ctx, reg_temp);
68957 
68958 		/* binding power must be high enough to NOT allow comma expressions directly */
68959 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp);  /* always allow 'in', coerce to 'tr' just in case */
68960 
68961 		DUK__SETTEMP(comp_ctx, reg_temp + 1);
68962 		nargs++;
68963 
68964 		DUK_DDD(DUK_DDDPRINT("argument #%ld written into reg %ld", (long) nargs, (long) reg_temp));
68965 	}
68966 
68967 	/* eat the right paren */
68968 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* RegExp mode does not matter. */
68969 
68970 	DUK_DDD(DUK_DDDPRINT("end parsing arguments"));
68971 
68972 	return nargs;
68973 }
68974 
68975 DUK_LOCAL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx) {
68976 	/* empty expressions can be detected conveniently with nud/led counts */
68977 	return (comp_ctx->curr_func.nud_count == 0) &&
68978 	       (comp_ctx->curr_func.led_count == 0);
68979 }
68980 
68981 DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
68982 	duk_hthread *thr = comp_ctx->thr;
68983 	duk_token *tk;
68984 	duk_regconst_t temp_at_entry;
68985 	duk_small_uint_t tok;
68986 	duk_uint32_t args;  /* temp variable to pass constants and flags to shared code */
68987 
68988 	/*
68989 	 *  ctx->prev_token     token to process with duk__expr_nud()
68990 	 *  ctx->curr_token     updated by caller
68991 	 *
68992 	 *  Note: the token in the switch below has already been eaten.
68993 	 */
68994 
68995 	temp_at_entry = DUK__GETTEMP(comp_ctx);
68996 
68997 	comp_ctx->curr_func.nud_count++;
68998 
68999 	tk = &comp_ctx->prev_token;
69000 	tok = tk->t;
69001 	res->t = DUK_IVAL_NONE;
69002 
69003 	DUK_DDD(DUK_DDDPRINT("duk__expr_nud(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
69004 	                     (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
69005 
69006 	switch (tok) {
69007 
69008 	/* PRIMARY EXPRESSIONS */
69009 
69010 	case DUK_TOK_THIS: {
69011 		duk_regconst_t reg_temp;
69012 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
69013 		duk__emit_bc(comp_ctx,
69014 		             DUK_OP_LDTHIS,
69015 		             reg_temp);
69016 		duk__ivalue_regconst(res, reg_temp);
69017 		return;
69018 	}
69019 	case DUK_TOK_IDENTIFIER: {
69020 		duk__ivalue_var_hstring(comp_ctx, res, tk->str1);
69021 		return;
69022 	}
69023 	case DUK_TOK_NULL: {
69024 		duk_push_null(thr);
69025 		goto plain_value;
69026 	}
69027 	case DUK_TOK_TRUE: {
69028 		duk_push_true(thr);
69029 		goto plain_value;
69030 	}
69031 	case DUK_TOK_FALSE: {
69032 		duk_push_false(thr);
69033 		goto plain_value;
69034 	}
69035 	case DUK_TOK_NUMBER: {
69036 		duk_push_number(thr, tk->num);
69037 		goto plain_value;
69038 	}
69039 	case DUK_TOK_STRING: {
69040 		DUK_ASSERT(tk->str1 != NULL);
69041 		duk_push_hstring(thr, tk->str1);
69042 		goto plain_value;
69043 	}
69044 	case DUK_TOK_REGEXP: {
69045 #if defined(DUK_USE_REGEXP_SUPPORT)
69046 		duk_regconst_t reg_temp;
69047 		duk_regconst_t rc_re_bytecode;  /* const */
69048 		duk_regconst_t rc_re_source;    /* const */
69049 
69050 		DUK_ASSERT(tk->str1 != NULL);
69051 		DUK_ASSERT(tk->str2 != NULL);
69052 
69053 		DUK_DDD(DUK_DDDPRINT("emitting regexp op, str1=%!O, str2=%!O",
69054 		                     (duk_heaphdr *) tk->str1,
69055 		                     (duk_heaphdr *) tk->str2));
69056 
69057 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
69058 		duk_push_hstring(thr, tk->str1);
69059 		duk_push_hstring(thr, tk->str2);
69060 
69061 		/* [ ... pattern flags ] */
69062 
69063 		duk_regexp_compile(thr);
69064 
69065 		/* [ ... escaped_source bytecode ] */
69066 
69067 		rc_re_bytecode = duk__getconst(comp_ctx);
69068 		rc_re_source = duk__getconst(comp_ctx);
69069 
69070 		duk__emit_a_b_c(comp_ctx,
69071 		                DUK_OP_REGEXP | DUK__EMIT_FLAG_BC_REGCONST,
69072 		                reg_temp /*a*/,
69073 		                rc_re_bytecode /*b*/,
69074 		                rc_re_source /*c*/);
69075 
69076 		duk__ivalue_regconst(res, reg_temp);
69077 		return;
69078 #else  /* DUK_USE_REGEXP_SUPPORT */
69079 		goto syntax_error;
69080 #endif  /* DUK_USE_REGEXP_SUPPORT */
69081 	}
69082 	case DUK_TOK_LBRACKET: {
69083 		DUK_DDD(DUK_DDDPRINT("parsing array literal"));
69084 		duk__nud_array_literal(comp_ctx, res);
69085 		return;
69086 	}
69087 	case DUK_TOK_LCURLY: {
69088 		DUK_DDD(DUK_DDDPRINT("parsing object literal"));
69089 		duk__nud_object_literal(comp_ctx, res);
69090 		return;
69091 	}
69092 	case DUK_TOK_LPAREN: {
69093 		duk_bool_t prev_allow_in;
69094 
69095 		comp_ctx->curr_func.paren_level++;
69096 		prev_allow_in = comp_ctx->curr_func.allow_in;
69097 		comp_ctx->curr_func.allow_in = 1; /* reset 'allow_in' for parenthesized expression */
69098 
69099 		duk__expr(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression, terminates at a ')' */
69100 
69101 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* No RegExp after parenthesized expression. */
69102 		comp_ctx->curr_func.allow_in = prev_allow_in;
69103 		comp_ctx->curr_func.paren_level--;
69104 		return;
69105 	}
69106 
69107 	/* MEMBER/NEW/CALL EXPRESSIONS */
69108 
69109 	case DUK_TOK_NEW: {
69110 		/*
69111 		 *  Parsing an expression starting with 'new' is tricky because
69112 		 *  there are multiple possible productions deriving from
69113 		 *  LeftHandSideExpression which begin with 'new'.
69114 		 *
69115 		 *  We currently resort to one-token lookahead to distinguish the
69116 		 *  cases.  Hopefully this is correct.  The binding power must be
69117 		 *  such that parsing ends at an LPAREN (CallExpression) but not at
69118 		 *  a PERIOD or LBRACKET (MemberExpression).
69119 		 *
69120 		 *  See doc/compiler.rst for discussion on the parsing approach,
69121 		 *  and testcases/test-dev-new.js for a bunch of documented tests.
69122 		 */
69123 
69124 		duk_regconst_t reg_target;
69125 		duk_int_t nargs;
69126 
69127 		DUK_DDD(DUK_DDDPRINT("begin parsing new expression"));
69128 
69129 		reg_target = DUK__ALLOCTEMPS(comp_ctx, 2);
69130 
69131 #if defined(DUK_USE_ES6)
69132 		if (comp_ctx->curr_token.t == DUK_TOK_PERIOD) {
69133 			/* new.target */
69134 			DUK_DDD(DUK_DDDPRINT("new.target"));
69135 			duk__advance(comp_ctx);
69136 			if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER ||
69137 			    !duk_hstring_equals_ascii_cstring(comp_ctx->curr_token.str1, "target")) {
69138 				goto syntax_error_newtarget;
69139 			}
69140 			if (comp_ctx->curr_func.is_global) {
69141 				goto syntax_error_newtarget;
69142 			}
69143 			duk__advance(comp_ctx);
69144 			duk__emit_bc(comp_ctx,
69145 			             DUK_OP_NEWTARGET,
69146 			             reg_target);
69147 			duk__ivalue_regconst(res, reg_target);
69148 			return;
69149 		}
69150 #endif  /* DUK_USE_ES6 */
69151 
69152 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_CALL /*rbp_flags*/, reg_target /*forced_reg*/);
69153 		duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, reg_target + 1);  /* default instance */
69154 		DUK__SETTEMP(comp_ctx, reg_target + 2);
69155 
69156 		/* XXX: 'new obj.noSuch()' doesn't use GETPROPC now which
69157 		 * makes the error message worse than for obj.noSuch().
69158 		 */
69159 
69160 		if (comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
69161 			/* 'new' MemberExpression Arguments */
69162 			DUK_DDD(DUK_DDDPRINT("new expression has argument list"));
69163 			duk__advance(comp_ctx);
69164 			nargs = duk__parse_arguments(comp_ctx, res);  /* parse args starting from "next temp", reg_target + 1 */
69165 			/* right paren eaten */
69166 		} else {
69167 			/* 'new' MemberExpression */
69168 			DUK_DDD(DUK_DDDPRINT("new expression has no argument list"));
69169 			nargs = 0;
69170 		}
69171 
69172 		duk__emit_a_bc(comp_ctx,
69173 		              DUK_OP_CALL0 | DUK_BC_CALL_FLAG_CONSTRUCT,
69174 		              nargs /*num_args*/,
69175 		              reg_target /*target*/);
69176 
69177 		DUK_DDD(DUK_DDDPRINT("end parsing new expression"));
69178 
69179 		duk__ivalue_regconst(res, reg_target);
69180 		return;
69181 	}
69182 
69183 	/* FUNCTION EXPRESSIONS */
69184 
69185 	case DUK_TOK_FUNCTION: {
69186 		/* Function expression.  Note that any statement beginning with 'function'
69187 		 * is handled by the statement parser as a function declaration, or a
69188 		 * non-standard function expression/statement (or a SyntaxError).  We only
69189 		 * handle actual function expressions (occurring inside an expression) here.
69190 		 *
69191 		 * O(depth^2) parse count for inner functions is handled by recording a
69192 		 * lexer offset on the first compilation pass, so that the function can
69193 		 * be efficiently skipped on the second pass.  This is encapsulated into
69194 		 * duk__parse_func_like_fnum().
69195 		 */
69196 
69197 		duk_regconst_t reg_temp;
69198 		duk_int_t fnum;
69199 
69200 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
69201 
69202 		/* curr_token follows 'function' */
69203 		fnum = duk__parse_func_like_fnum(comp_ctx, 0 /*flags*/);
69204 		DUK_DDD(DUK_DDDPRINT("parsed inner function -> fnum %ld", (long) fnum));
69205 
69206 		duk__emit_a_bc(comp_ctx,
69207 		               DUK_OP_CLOSURE,
69208 		               reg_temp /*a*/,
69209 		               (duk_regconst_t) fnum /*bc*/);
69210 
69211 		duk__ivalue_regconst(res, reg_temp);
69212 		return;
69213 	}
69214 
69215 	/* UNARY EXPRESSIONS */
69216 
69217 	case DUK_TOK_DELETE: {
69218 		/* Delete semantics are a bit tricky.  The description in E5 specification
69219 		 * is kind of confusing, because it distinguishes between resolvability of
69220 		 * a reference (which is only known at runtime) seemingly at compile time
69221 		 * (= SyntaxError throwing).
69222 		 */
69223 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
69224 		if (res->t == DUK_IVAL_VAR) {
69225 			/* not allowed in strict mode, regardless of whether resolves;
69226 			 * in non-strict mode DELVAR handles both non-resolving and
69227 			 * resolving cases (the specification description is a bit confusing).
69228 			 */
69229 
69230 			duk_regconst_t reg_temp;
69231 			duk_regconst_t reg_varbind;
69232 			duk_regconst_t rc_varname;
69233 
69234 			if (comp_ctx->curr_func.is_strict) {
69235 				DUK_ERROR_SYNTAX(thr, DUK_STR_CANNOT_DELETE_IDENTIFIER);
69236 				DUK_WO_NORETURN(return;);
69237 			}
69238 
69239 			DUK__SETTEMP(comp_ctx, temp_at_entry);
69240 			reg_temp = DUK__ALLOCTEMP(comp_ctx);
69241 
69242 			duk_dup(thr, res->x1.valstack_idx);
69243 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
69244 				/* register bound variables are non-configurable -> always false */
69245 				duk__emit_bc(comp_ctx,
69246 				             DUK_OP_LDFALSE,
69247 				             reg_temp);
69248 			} else {
69249 				duk_dup(thr, res->x1.valstack_idx);
69250 				rc_varname = duk__getconst(comp_ctx);
69251 				duk__emit_a_bc(comp_ctx,
69252 				               DUK_OP_DELVAR,
69253 				               reg_temp,
69254 				               rc_varname);
69255 			}
69256 			duk__ivalue_regconst(res, reg_temp);
69257 		} else if (res->t == DUK_IVAL_PROP) {
69258 			duk_regconst_t reg_temp;
69259 			duk_regconst_t reg_obj;
69260 			duk_regconst_t rc_key;
69261 
69262 			DUK__SETTEMP(comp_ctx, temp_at_entry);
69263 			reg_temp = DUK__ALLOCTEMP(comp_ctx);
69264 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
69265 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
69266 			duk__emit_a_b_c(comp_ctx,
69267 			                DUK_OP_DELPROP | DUK__EMIT_FLAG_BC_REGCONST,
69268 			                reg_temp,
69269 			                reg_obj,
69270 			                rc_key);
69271 
69272 			duk__ivalue_regconst(res, reg_temp);
69273 		} else {
69274 			/* non-Reference deletion is always 'true', even in strict mode */
69275 			duk_push_true(thr);
69276 			goto plain_value;
69277 		}
69278 		return;
69279 	}
69280 	case DUK_TOK_VOID: {
69281 		duk__expr_toplain_ignore(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
69282 		duk_push_undefined(thr);
69283 		goto plain_value;
69284 	}
69285 	case DUK_TOK_TYPEOF: {
69286 		/* 'typeof' must handle unresolvable references without throwing
69287 		 * a ReferenceError (E5 Section 11.4.3).  Register mapped values
69288 		 * will never be unresolvable so special handling is only required
69289 		 * when an identifier is a "slow path" one.
69290 		 */
69291 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
69292 
69293 		if (res->t == DUK_IVAL_VAR) {
69294 			duk_regconst_t reg_varbind;
69295 			duk_regconst_t rc_varname;
69296 			duk_regconst_t reg_temp;
69297 
69298 			duk_dup(thr, res->x1.valstack_idx);
69299 			if (!duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
69300 				DUK_DDD(DUK_DDDPRINT("typeof for an identifier name which could not be resolved "
69301 				                     "at compile time, need to use special run-time handling"));
69302 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
69303 				duk__emit_a_bc(comp_ctx,
69304 				               DUK_OP_TYPEOFID,
69305 				               reg_temp,
69306 				               rc_varname);
69307 				duk__ivalue_regconst(res, reg_temp);
69308 				return;
69309 			}
69310 		}
69311 
69312 		args = DUK_OP_TYPEOF;
69313 		goto unary;
69314 	}
69315 	case DUK_TOK_INCREMENT: {
69316 		args = (DUK_OP_PREINCP << 8) + DUK_OP_PREINCR;
69317 		goto preincdec;
69318 	}
69319 	case DUK_TOK_DECREMENT: {
69320 		args = (DUK_OP_PREDECP << 8) + DUK_OP_PREDECR;
69321 		goto preincdec;
69322 	}
69323 	case DUK_TOK_ADD: {
69324 		/* unary plus */
69325 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
69326 		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
69327 		    duk_is_number(thr, res->x1.valstack_idx)) {
69328 			/* unary plus of a number is identity */
69329 			return;
69330 		}
69331 		args = DUK_OP_UNP;
69332 		goto unary;
69333 	}
69334 	case DUK_TOK_SUB: {
69335 		/* unary minus */
69336 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
69337 		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
69338 		    duk_is_number(thr, res->x1.valstack_idx)) {
69339 			/* this optimization is important to handle negative literals
69340 			 * (which are not directly provided by the lexical grammar)
69341 			 */
69342 			duk_tval *tv_num;
69343 			duk_double_union du;
69344 
69345 			tv_num = DUK_GET_TVAL_POSIDX(thr, res->x1.valstack_idx);
69346 			DUK_ASSERT(tv_num != NULL);
69347 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_num));
69348 			du.d = DUK_TVAL_GET_NUMBER(tv_num);
69349 			du.d = -du.d;
69350 			DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
69351 			DUK_TVAL_SET_NUMBER(tv_num, du.d);
69352 			return;
69353 		}
69354 		args = DUK_OP_UNM;
69355 		goto unary;
69356 	}
69357 	case DUK_TOK_BNOT: {
69358 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
69359 		args = DUK_OP_BNOT;
69360 		goto unary;
69361 	}
69362 	case DUK_TOK_LNOT: {
69363 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
69364 		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE) {
69365 			/* Very minimal inlining to handle common idioms '!0' and '!1',
69366 			 * and also boolean arguments like '!false' and '!true'.
69367 			 */
69368 			duk_tval *tv_val;
69369 
69370 			tv_val = DUK_GET_TVAL_POSIDX(thr, res->x1.valstack_idx);
69371 			DUK_ASSERT(tv_val != NULL);
69372 			if (DUK_TVAL_IS_NUMBER(tv_val)) {
69373 				duk_double_t d;
69374 				d = DUK_TVAL_GET_NUMBER(tv_val);
69375 				if (d == 0.0) {
69376 					/* Matches both +0 and -0 on purpose. */
69377 					DUK_DDD(DUK_DDDPRINT("inlined lnot: !0 -> true"));
69378 					DUK_TVAL_SET_BOOLEAN_TRUE(tv_val);
69379 					return;
69380 				} else if (d == 1.0) {
69381 					DUK_DDD(DUK_DDDPRINT("inlined lnot: !1 -> false"));
69382 					DUK_TVAL_SET_BOOLEAN_FALSE(tv_val);
69383 					return;
69384 				}
69385 			} else if (DUK_TVAL_IS_BOOLEAN(tv_val)) {
69386 				duk_small_uint_t v;
69387 				v = DUK_TVAL_GET_BOOLEAN(tv_val);
69388 				DUK_DDD(DUK_DDDPRINT("inlined lnot boolean: %ld", (long) v));
69389 				DUK_ASSERT(v == 0 || v == 1);
69390 				DUK_TVAL_SET_BOOLEAN(tv_val, v ^ 0x01);
69391 				return;
69392 			}
69393 		}
69394 		args = DUK_OP_LNOT;
69395 		goto unary;
69396 	}
69397 
69398 	}  /* end switch */
69399 
69400 	DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
69401 	DUK_WO_NORETURN(return;);
69402 
69403  unary:
69404 	{
69405 		/* Unary opcodes use just the 'BC' register source because it
69406 		 * matches current shuffle limits, and maps cleanly to 16 high
69407 		 * bits of the opcode.
69408 		 */
69409 
69410 		duk_regconst_t reg_src, reg_res;
69411 
69412 		reg_src = duk__ivalue_toregconst_raw(comp_ctx, res, -1 /*forced_reg*/, 0 /*flags*/);
69413 		if (DUK__ISREG_TEMP(comp_ctx, reg_src)) {
69414 			reg_res = reg_src;
69415 		} else {
69416 			reg_res = DUK__ALLOCTEMP(comp_ctx);
69417 		}
69418 		duk__emit_a_bc(comp_ctx,
69419 		             args,
69420 		             reg_res,
69421 		             reg_src);
69422 		duk__ivalue_regconst(res, reg_res);
69423 		return;
69424 	}
69425 
69426  preincdec:
69427 	{
69428 		/* preincrement and predecrement */
69429 		duk_regconst_t reg_res;
69430 		duk_small_uint_t args_op1 = args & 0xff;  /* DUK_OP_PREINCR/DUK_OP_PREDECR */
69431 		duk_small_uint_t args_op2 = args >> 8;    /* DUK_OP_PREINCP_RR/DUK_OP_PREDECP_RR */
69432 
69433 		/* Specific assumptions for opcode numbering. */
69434 		DUK_ASSERT(DUK_OP_PREINCR + 4 == DUK_OP_PREINCV);
69435 		DUK_ASSERT(DUK_OP_PREDECR + 4 == DUK_OP_PREDECV);
69436 
69437 		reg_res = DUK__ALLOCTEMP(comp_ctx);
69438 
69439 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
69440 		if (res->t == DUK_IVAL_VAR) {
69441 			duk_hstring *h_varname;
69442 			duk_regconst_t reg_varbind;
69443 			duk_regconst_t rc_varname;
69444 
69445 			h_varname = duk_known_hstring(thr, res->x1.valstack_idx);
69446 
69447 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
69448 				goto syntax_error;
69449 			}
69450 
69451 			duk_dup(thr, res->x1.valstack_idx);
69452 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
69453 				duk__emit_a_bc(comp_ctx,
69454 				               args_op1,  /* e.g. DUK_OP_PREINCR */
69455 				               reg_res,
69456 				               reg_varbind);
69457 			} else {
69458 				duk__emit_a_bc(comp_ctx,
69459 				                args_op1 + 4,  /* e.g. DUK_OP_PREINCV */
69460 				                reg_res,
69461 				                rc_varname);
69462 			}
69463 
69464 			DUK_DDD(DUK_DDDPRINT("preincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
69465 			                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
69466 		} else if (res->t == DUK_IVAL_PROP) {
69467 			duk_regconst_t reg_obj;  /* allocate to reg only (not const) */
69468 			duk_regconst_t rc_key;
69469 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
69470 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
69471 			duk__emit_a_b_c(comp_ctx,
69472 			                args_op2 | DUK__EMIT_FLAG_BC_REGCONST,  /* e.g. DUK_OP_PREINCP */
69473 			                reg_res,
69474 			                reg_obj,
69475 			                rc_key);
69476 		} else {
69477 			/* Technically return value is not needed because INVLHS will
69478 			 * unconditially throw a ReferenceError.  Coercion is necessary
69479 			 * for proper semantics (consider ToNumber() called for an object).
69480 			 * Use DUK_OP_UNP with a dummy register to get ToNumber().
69481 			 */
69482 
69483 			duk__ivalue_toforcedreg(comp_ctx, res, reg_res);
69484 			duk__emit_bc(comp_ctx,
69485 			             DUK_OP_UNP,
69486 			             reg_res);  /* for side effects, result ignored */
69487 			duk__emit_op_only(comp_ctx,
69488 			                  DUK_OP_INVLHS);
69489 		}
69490 		DUK__SETTEMP(comp_ctx, reg_res + 1);
69491 		duk__ivalue_regconst(res, reg_res);
69492 		return;
69493 	}
69494 
69495  plain_value:
69496 	{
69497 		/* Stack top contains plain value */
69498 		duk__ivalue_plain_fromstack(comp_ctx, res);
69499 		return;
69500 	}
69501 
69502 #if defined(DUK_USE_ES6)
69503  syntax_error_newtarget:
69504 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_NEWTARGET);
69505 	DUK_WO_NORETURN(return;);
69506 #endif
69507 
69508  syntax_error:
69509 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
69510 	DUK_WO_NORETURN(return;);
69511 }
69512 
69513 /* XXX: add flag to indicate whether caller cares about return value; this
69514  * affects e.g. handling of assignment expressions.  This change needs API
69515  * changes elsewhere too.
69516  */
69517 DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res) {
69518 	duk_hthread *thr = comp_ctx->thr;
69519 	duk_token *tk;
69520 	duk_small_uint_t tok;
69521 	duk_uint32_t args;  /* temp variable to pass constants and flags to shared code */
69522 
69523 	/*
69524 	 *  ctx->prev_token     token to process with duk__expr_led()
69525 	 *  ctx->curr_token     updated by caller
69526 	 */
69527 
69528 	comp_ctx->curr_func.led_count++;
69529 
69530 	/* The token in the switch has already been eaten here */
69531 	tk = &comp_ctx->prev_token;
69532 	tok = tk->t;
69533 
69534 	DUK_DDD(DUK_DDDPRINT("duk__expr_led(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
69535 	                     (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
69536 
69537 	/* XXX: default priority for infix operators is duk__expr_lbp(tok) -> get it here? */
69538 
69539 	switch (tok) {
69540 
69541 	/* PRIMARY EXPRESSIONS */
69542 
69543 	case DUK_TOK_PERIOD: {
69544 		/* Property access expressions are critical for correct LHS ordering,
69545 		 * see comments in duk__expr()!
69546 		 *
69547 		 * A conservative approach would be to use duk__ivalue_totempconst()
69548 		 * for 'left'.  However, allowing a reg-bound variable seems safe here
69549 		 * and is nice because "foo.bar" is a common expression.  If the ivalue
69550 		 * is used in an expression a GETPROP will occur before any changes to
69551 		 * the base value can occur.  If the ivalue is used as an assignment
69552 		 * LHS, the assignment code will ensure the base value is safe from
69553 		 * RHS mutation.
69554 		 */
69555 
69556 		/* XXX: This now coerces an identifier into a GETVAR to a temp, which
69557 		 * causes an extra LDREG in call setup.  It's sufficient to coerce to a
69558 		 * unary ivalue?
69559 		 */
69560 		duk__ivalue_toplain(comp_ctx, left);
69561 
69562 		/* NB: must accept reserved words as property name */
69563 		if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER) {
69564 			DUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER);
69565 			DUK_WO_NORETURN(return;);
69566 		}
69567 
69568 		res->t = DUK_IVAL_PROP;
69569 		duk__copy_ispec(comp_ctx, &left->x1, &res->x1);  /* left.x1 -> res.x1 */
69570 		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
69571 		duk_push_hstring(thr, comp_ctx->curr_token.str1);
69572 		duk_replace(thr, res->x2.valstack_idx);
69573 		res->x2.t = DUK_ISPEC_VALUE;
69574 
69575 		/* special RegExp literal handling after IdentifierName */
69576 		comp_ctx->curr_func.reject_regexp_in_adv = 1;
69577 
69578 		duk__advance(comp_ctx);
69579 		return;
69580 	}
69581 	case DUK_TOK_LBRACKET: {
69582 		/* Property access expressions are critical for correct LHS ordering,
69583 		 * see comments in duk__expr()!
69584 		 */
69585 
69586 		/* XXX: optimize temp reg use */
69587 		/* XXX: similar coercion issue as in DUK_TOK_PERIOD */
69588 		/* XXX: coerce to regs? it might be better for enumeration use, where the
69589 		 * same PROP ivalue is used multiple times.  Or perhaps coerce PROP further
69590 		 * there?
69591 		 */
69592 		/* XXX: for simple cases like x['y'] an unnecessary LDREG is
69593 		 * emitted for the base value; could avoid it if we knew that
69594 		 * the key expression is safe (e.g. just a single literal).
69595 		 */
69596 
69597 		/* The 'left' value must not be a register bound variable
69598 		 * because it may be mutated during the rest of the expression
69599 		 * and E5.1 Section 11.2.1 specifies the order of evaluation
69600 		 * so that the base value is evaluated first.
69601 		 * See: test-bug-nested-prop-mutate.js.
69602 		 */
69603 		duk__ivalue_totempconst(comp_ctx, left);
69604 		duk__expr_toplain(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression, ']' terminates */
69605 		duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);
69606 
69607 		res->t = DUK_IVAL_PROP;
69608 		duk__copy_ispec(comp_ctx, &res->x1, &res->x2);   /* res.x1 -> res.x2 */
69609 		duk__copy_ispec(comp_ctx, &left->x1, &res->x1);  /* left.x1 -> res.x1 */
69610 		return;
69611 	}
69612 	case DUK_TOK_LPAREN: {
69613 		/* function call */
69614 		duk_regconst_t reg_cs = DUK__ALLOCTEMPS(comp_ctx, 2);
69615 		duk_int_t nargs;
69616 		duk_small_uint_t call_op = DUK_OP_CALL0;
69617 
69618 		/* XXX: attempt to get the call result to "next temp" whenever
69619 		 * possible to avoid unnecessary register shuffles.
69620 		 */
69621 
69622 		/*
69623 		 *  Setup call: target and 'this' binding.  Three cases:
69624 		 *
69625 		 *    1. Identifier base (e.g. "foo()")
69626 		 *    2. Property base (e.g. "foo.bar()")
69627 		 *    3. Register base (e.g. "foo()()"; i.e. when a return value is a function)
69628 		 */
69629 
69630 		if (left->t == DUK_IVAL_VAR) {
69631 			duk_hstring *h_varname;
69632 			duk_regconst_t reg_varbind;
69633 			duk_regconst_t rc_varname;
69634 
69635 			DUK_DDD(DUK_DDDPRINT("function call with identifier base"));
69636 
69637 			h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
69638 			if (h_varname == DUK_HTHREAD_STRING_EVAL(thr)) {
69639 				/* Potential direct eval call detected, flag the CALL
69640 				 * so that a run-time "direct eval" check is made and
69641 				 * special behavior may be triggered.  Note that this
69642 				 * does not prevent 'eval' from being register bound.
69643 				 */
69644 				DUK_DDD(DUK_DDDPRINT("function call with identifier 'eval' "
69645 				                     "-> using EVALCALL, marking function "
69646 				                     "as may_direct_eval"));
69647 				call_op |= DUK_BC_CALL_FLAG_CALLED_AS_EVAL;
69648 				comp_ctx->curr_func.may_direct_eval = 1;
69649 			}
69650 
69651 			duk_dup(thr, left->x1.valstack_idx);
69652 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
69653 				duk__emit_a_bc(comp_ctx,
69654 				              DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE,
69655 				              reg_varbind,
69656 				              reg_cs + 0);
69657 			} else {
69658 				/* XXX: expand target register or constant field to
69659 				 * reduce shuffling.
69660 				 */
69661 				DUK_ASSERT(DUK__ISCONST(rc_varname));
69662 				duk__emit_a_b(comp_ctx,
69663 				              DUK_OP_CSVAR | DUK__EMIT_FLAG_BC_REGCONST,
69664 				              reg_cs + 0,
69665 				              rc_varname);
69666 			}
69667 		} else if (left->t == DUK_IVAL_PROP) {
69668 			/* Call through a property lookup, E5 Section 11.2.3, step 6.a.i,
69669 			 * E5 Section 10.4.3.  There used to be a separate CSPROP opcode
69670 			 * but a typical call setup took 3 opcodes (e.g. LDREG, LDCONST,
69671 			 * CSPROP) and the same can be achieved with ordinary loads.
69672 			 */
69673 #if defined(DUK_USE_VERBOSE_ERRORS)
69674 			duk_regconst_t reg_key;
69675 #endif
69676 
69677 			DUK_DDD(DUK_DDDPRINT("function call with property base"));
69678 
69679 			/* XXX: For Math.sin() this generates: LDCONST + LDREG +
69680 			 * GETPROPC + call.  The LDREG is unnecessary because LDCONST
69681 			 * could be loaded directly into reg_cs + 1.  This doesn't
69682 			 * happen now because a variable cannot be in left->x1 of a
69683 			 * DUK_IVAL_PROP.  We could notice that left->x1 is a temp
69684 			 * and reuse, but it would still be in the wrong position
69685 			 * (reg_cs + 0 rather than reg_cs + 1).
69686 			 */
69687 			duk__ispec_toforcedreg(comp_ctx, &left->x1, reg_cs + 1);  /* base */
69688 #if defined(DUK_USE_VERBOSE_ERRORS)
69689 			reg_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
69690 			duk__emit_a_b_c(comp_ctx,
69691 			                DUK_OP_GETPROPC | DUK__EMIT_FLAG_BC_REGCONST,
69692 			                reg_cs + 0,
69693 			                reg_cs + 1,
69694 			                reg_key);
69695 #else
69696 			duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);  /* base[key] */
69697 #endif
69698 		} else {
69699 			DUK_DDD(DUK_DDDPRINT("function call with register base"));
69700 
69701 			duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);
69702 #if 0
69703 			duk__emit_a_bc(comp_ctx,
69704 			               DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE,
69705 			               reg_cs + 0,
69706 			               reg_cs + 0);  /* in-place setup */
69707 #endif
69708 			/* Because of in-place setup, REGCS is equivalent to
69709 			 * just this LDUNDEF.
69710 			 */
69711 			duk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, reg_cs + 1);
69712 		}
69713 
69714 		DUK__SETTEMP(comp_ctx, reg_cs + 2);
69715 		nargs = duk__parse_arguments(comp_ctx, res);  /* parse args starting from "next temp" */
69716 
69717 		/* Tailcalls are handled by back-patching the already emitted opcode
69718 		 * later in return statement parser.
69719 		 */
69720 
69721 		duk__emit_a_bc(comp_ctx,
69722 		               call_op,
69723 		               (duk_regconst_t) nargs /*numargs*/,
69724 		               reg_cs /*basereg*/);
69725 		DUK__SETTEMP(comp_ctx, reg_cs + 1);    /* result in csreg */
69726 
69727 		duk__ivalue_regconst(res, reg_cs);
69728 		return;
69729 	}
69730 
69731 	/* POSTFIX EXPRESSION */
69732 
69733 	case DUK_TOK_INCREMENT: {
69734 		args = (DUK_OP_POSTINCP_RR << 16) + (DUK_OP_POSTINCR << 8) + 0;
69735 		goto postincdec;
69736 	}
69737 	case DUK_TOK_DECREMENT: {
69738 		args = (DUK_OP_POSTDECP_RR << 16) + (DUK_OP_POSTDECR << 8) + 0;
69739 		goto postincdec;
69740 	}
69741 
69742 	/* EXPONENTIATION EXPRESSION */
69743 
69744 #if defined(DUK_USE_ES7_EXP_OPERATOR)
69745 	case DUK_TOK_EXP: {
69746 		args = (DUK_OP_EXP << 8) + DUK__BP_EXPONENTIATION - 1;  /* UnaryExpression */
69747 		goto binary;
69748 	}
69749 #endif
69750 
69751 	/* MULTIPLICATIVE EXPRESSION */
69752 
69753 	case DUK_TOK_MUL: {
69754 		args = (DUK_OP_MUL << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */
69755 		goto binary;
69756 	}
69757 	case DUK_TOK_DIV: {
69758 		args = (DUK_OP_DIV << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */
69759 		goto binary;
69760 	}
69761 	case DUK_TOK_MOD: {
69762 		args = (DUK_OP_MOD << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */
69763 		goto binary;
69764 	}
69765 
69766 	/* ADDITIVE EXPRESSION */
69767 
69768 	case DUK_TOK_ADD: {
69769 		args = (DUK_OP_ADD << 8) + DUK__BP_ADDITIVE;  /* MultiplicativeExpression */
69770 		goto binary;
69771 	}
69772 	case DUK_TOK_SUB: {
69773 		args = (DUK_OP_SUB << 8) + DUK__BP_ADDITIVE;  /* MultiplicativeExpression */
69774 		goto binary;
69775 	}
69776 
69777 	/* SHIFT EXPRESSION */
69778 
69779 	case DUK_TOK_ALSHIFT: {
69780 		/* << */
69781 		args = (DUK_OP_BASL << 8) + DUK__BP_SHIFT;
69782 		goto binary;
69783 	}
69784 	case DUK_TOK_ARSHIFT: {
69785 		/* >> */
69786 		args = (DUK_OP_BASR << 8) + DUK__BP_SHIFT;
69787 		goto binary;
69788 	}
69789 	case DUK_TOK_RSHIFT: {
69790 		/* >>> */
69791 		args = (DUK_OP_BLSR << 8) + DUK__BP_SHIFT;
69792 		goto binary;
69793 	}
69794 
69795 	/* RELATIONAL EXPRESSION */
69796 
69797 	case DUK_TOK_LT: {
69798 		/* < */
69799 		args = (DUK_OP_LT << 8) + DUK__BP_RELATIONAL;
69800 		goto binary;
69801 	}
69802 	case DUK_TOK_GT: {
69803 		args = (DUK_OP_GT << 8) + DUK__BP_RELATIONAL;
69804 		goto binary;
69805 	}
69806 	case DUK_TOK_LE: {
69807 		args = (DUK_OP_LE << 8) + DUK__BP_RELATIONAL;
69808 		goto binary;
69809 	}
69810 	case DUK_TOK_GE: {
69811 		args = (DUK_OP_GE << 8) + DUK__BP_RELATIONAL;
69812 		goto binary;
69813 	}
69814 	case DUK_TOK_INSTANCEOF: {
69815 		args = (DUK_OP_INSTOF << 8) + DUK__BP_RELATIONAL;
69816 		goto binary;
69817 	}
69818 	case DUK_TOK_IN: {
69819 		args = (DUK_OP_IN << 8) + DUK__BP_RELATIONAL;
69820 		goto binary;
69821 	}
69822 
69823 	/* EQUALITY EXPRESSION */
69824 
69825 	case DUK_TOK_EQ: {
69826 		args = (DUK_OP_EQ << 8) + DUK__BP_EQUALITY;
69827 		goto binary;
69828 	}
69829 	case DUK_TOK_NEQ: {
69830 		args = (DUK_OP_NEQ << 8) + DUK__BP_EQUALITY;
69831 		goto binary;
69832 	}
69833 	case DUK_TOK_SEQ: {
69834 		args = (DUK_OP_SEQ << 8) + DUK__BP_EQUALITY;
69835 		goto binary;
69836 	}
69837 	case DUK_TOK_SNEQ: {
69838 		args = (DUK_OP_SNEQ << 8) + DUK__BP_EQUALITY;
69839 		goto binary;
69840 	}
69841 
69842 	/* BITWISE EXPRESSIONS */
69843 
69844 	case DUK_TOK_BAND: {
69845 		args = (DUK_OP_BAND << 8) + DUK__BP_BAND;
69846 		goto binary;
69847 	}
69848 	case DUK_TOK_BXOR: {
69849 		args = (DUK_OP_BXOR << 8) + DUK__BP_BXOR;
69850 		goto binary;
69851 	}
69852 	case DUK_TOK_BOR: {
69853 		args = (DUK_OP_BOR << 8) + DUK__BP_BOR;
69854 		goto binary;
69855 	}
69856 
69857 	/* LOGICAL EXPRESSIONS */
69858 
69859 	case DUK_TOK_LAND: {
69860 		/* syntactically left-associative but parsed as right-associative */
69861 		args = (1 << 8) + DUK__BP_LAND - 1;
69862 		goto binary_logical;
69863 	}
69864 	case DUK_TOK_LOR: {
69865 		/* syntactically left-associative but parsed as right-associative */
69866 		args = (0 << 8) + DUK__BP_LOR - 1;
69867 		goto binary_logical;
69868 	}
69869 
69870 	/* CONDITIONAL EXPRESSION */
69871 
69872 	case DUK_TOK_QUESTION: {
69873 		/* XXX: common reg allocation need is to reuse a sub-expression's temp reg,
69874 		 * but only if it really is a temp.  Nothing fancy here now.
69875 		 */
69876 		duk_regconst_t reg_temp;
69877 		duk_int_t pc_jump1;
69878 		duk_int_t pc_jump2;
69879 
69880 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
69881 		duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
69882 		duk__emit_if_true_skip(comp_ctx, reg_temp);
69883 		pc_jump1 = duk__emit_jump_empty(comp_ctx);  /* jump to false */
69884 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);  /* AssignmentExpression */
69885 		duk__advance_expect(comp_ctx, DUK_TOK_COLON);
69886 		pc_jump2 = duk__emit_jump_empty(comp_ctx);  /* jump to end */
69887 		duk__patch_jump_here(comp_ctx, pc_jump1);
69888 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);  /* AssignmentExpression */
69889 		duk__patch_jump_here(comp_ctx, pc_jump2);
69890 
69891 		DUK__SETTEMP(comp_ctx, reg_temp + 1);
69892 		duk__ivalue_regconst(res, reg_temp);
69893 		return;
69894 	}
69895 
69896 	/* ASSIGNMENT EXPRESSION */
69897 
69898 	case DUK_TOK_EQUALSIGN: {
69899 		/*
69900 		 *  Assignments are right associative, allows e.g.
69901 		 *    a = 5;
69902 		 *    a += b = 9;   // same as a += (b = 9)
69903 		 *  -> expression value 14, a = 14, b = 9
69904 		 *
69905 		 *  Right associativiness is reflected in the BP for recursion,
69906 		 *  "-1" ensures assignment operations are allowed.
69907 		 *
69908 		 *  XXX: just use DUK__BP_COMMA (i.e. no need for 2-step bp levels)?
69909 		 */
69910 		args = (DUK_OP_NONE << 8) + DUK__BP_ASSIGNMENT - 1;   /* DUK_OP_NONE marks a 'plain' assignment */
69911 		goto assign;
69912 	}
69913 	case DUK_TOK_ADD_EQ: {
69914 		/* right associative */
69915 		args = (DUK_OP_ADD << 8) + DUK__BP_ASSIGNMENT - 1;
69916 		goto assign;
69917 	}
69918 	case DUK_TOK_SUB_EQ: {
69919 		/* right associative */
69920 		args = (DUK_OP_SUB << 8) + DUK__BP_ASSIGNMENT - 1;
69921 		goto assign;
69922 	}
69923 	case DUK_TOK_MUL_EQ: {
69924 		/* right associative */
69925 		args = (DUK_OP_MUL << 8) + DUK__BP_ASSIGNMENT - 1;
69926 		goto assign;
69927 	}
69928 	case DUK_TOK_DIV_EQ: {
69929 		/* right associative */
69930 		args = (DUK_OP_DIV << 8) + DUK__BP_ASSIGNMENT - 1;
69931 		goto assign;
69932 	}
69933 	case DUK_TOK_MOD_EQ: {
69934 		/* right associative */
69935 		args = (DUK_OP_MOD << 8) + DUK__BP_ASSIGNMENT - 1;
69936 		goto assign;
69937 	}
69938 #if defined(DUK_USE_ES7_EXP_OPERATOR)
69939 	case DUK_TOK_EXP_EQ: {
69940 		/* right associative */
69941 		args = (DUK_OP_EXP << 8) + DUK__BP_ASSIGNMENT - 1;
69942 		goto assign;
69943 	}
69944 #endif
69945 	case DUK_TOK_ALSHIFT_EQ: {
69946 		/* right associative */
69947 		args = (DUK_OP_BASL << 8) + DUK__BP_ASSIGNMENT - 1;
69948 		goto assign;
69949 	}
69950 	case DUK_TOK_ARSHIFT_EQ: {
69951 		/* right associative */
69952 		args = (DUK_OP_BASR << 8) + DUK__BP_ASSIGNMENT - 1;
69953 		goto assign;
69954 	}
69955 	case DUK_TOK_RSHIFT_EQ: {
69956 		/* right associative */
69957 		args = (DUK_OP_BLSR << 8) + DUK__BP_ASSIGNMENT - 1;
69958 		goto assign;
69959 	}
69960 	case DUK_TOK_BAND_EQ: {
69961 		/* right associative */
69962 		args = (DUK_OP_BAND << 8) + DUK__BP_ASSIGNMENT - 1;
69963 		goto assign;
69964 	}
69965 	case DUK_TOK_BOR_EQ: {
69966 		/* right associative */
69967 		args = (DUK_OP_BOR << 8) + DUK__BP_ASSIGNMENT - 1;
69968 		goto assign;
69969 	}
69970 	case DUK_TOK_BXOR_EQ: {
69971 		/* right associative */
69972 		args = (DUK_OP_BXOR << 8) + DUK__BP_ASSIGNMENT - 1;
69973 		goto assign;
69974 	}
69975 
69976 	/* COMMA */
69977 
69978 	case DUK_TOK_COMMA: {
69979 		/* right associative */
69980 
69981 		duk__ivalue_toplain_ignore(comp_ctx, left);  /* need side effects, not value */
69982 		duk__expr_toplain(comp_ctx, res, DUK__BP_COMMA - 1 /*rbp_flags*/);
69983 
69984 		/* return 'res' (of right part) as our result */
69985 		return;
69986 	}
69987 
69988 	default: {
69989 		break;
69990 	}
69991 	}
69992 
69993 	DUK_D(DUK_DPRINT("parse error: unexpected token: %ld", (long) tok));
69994 	DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
69995 	DUK_WO_NORETURN(return;);
69996 
69997 #if 0
69998 	/* XXX: shared handling for 'duk__expr_lhs'? */
69999 	if (comp_ctx->curr_func.paren_level == 0 && XXX) {
70000 		comp_ctx->curr_func.duk__expr_lhs = 0;
70001 	}
70002 #endif
70003 
70004  binary:
70005 	/*
70006 	 *  Shared handling of binary operations
70007 	 *
70008 	 *  args = (opcode << 8) + rbp
70009 	 */
70010 	{
70011 		duk__ivalue_toplain(comp_ctx, left);
70012 		duk__expr_toplain(comp_ctx, res, args & 0xff /*rbp_flags*/);
70013 
70014 		/* combine left->x1 and res->x1 (right->x1, really) -> (left->x1 OP res->x1) */
70015 		DUK_ASSERT(left->t == DUK_IVAL_PLAIN);
70016 		DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
70017 
70018 		res->t = DUK_IVAL_ARITH;
70019 		res->op = (args >> 8) & 0xff;
70020 
70021 		res->x2.t = res->x1.t;
70022 		res->x2.regconst = res->x1.regconst;
70023 		duk_copy(thr, res->x1.valstack_idx, res->x2.valstack_idx);
70024 
70025 		res->x1.t = left->x1.t;
70026 		res->x1.regconst = left->x1.regconst;
70027 		duk_copy(thr, left->x1.valstack_idx, res->x1.valstack_idx);
70028 
70029 		DUK_DDD(DUK_DDDPRINT("binary op, res: t=%ld, x1.t=%ld, x1.regconst=0x%08lx, x2.t=%ld, x2.regconst=0x%08lx",
70030 		                     (long) res->t, (long) res->x1.t, (unsigned long) res->x1.regconst, (long) res->x2.t, (unsigned long) res->x2.regconst));
70031 		return;
70032 	}
70033 
70034  binary_logical:
70035 	/*
70036 	 *  Shared handling for logical AND and logical OR.
70037 	 *
70038 	 *  args = (truthval << 8) + rbp
70039 	 *
70040 	 *  Truthval determines when to skip right-hand-side.
70041 	 *  For logical AND truthval=1, for logical OR truthval=0.
70042 	 *
70043 	 *  See doc/compiler.rst for discussion on compiling logical
70044 	 *  AND and OR expressions.  The approach here is very simplistic,
70045 	 *  generating extra jumps and multiple evaluations of truth values,
70046 	 *  but generates code on-the-fly with only local back-patching.
70047 	 *
70048 	 *  Both logical AND and OR are syntactically left-associated.
70049 	 *  However, logical ANDs are compiled as right associative
70050 	 *  expressions, i.e. "A && B && C" as "A && (B && C)", to allow
70051 	 *  skip jumps to skip over the entire tail.  Similarly for logical OR.
70052 	 */
70053 
70054 	{
70055 		duk_regconst_t reg_temp;
70056 		duk_int_t pc_jump;
70057 		duk_small_uint_t args_truthval = args >> 8;
70058 		duk_small_uint_t args_rbp = args & 0xff;
70059 
70060 		/* XXX: unoptimal use of temps, resetting */
70061 
70062 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
70063 
70064 		duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
70065 		DUK_ASSERT(DUK__ISREG(reg_temp));
70066 		duk__emit_bc(comp_ctx,
70067 		            (args_truthval ? DUK_OP_IFTRUE_R : DUK_OP_IFFALSE_R),
70068 		            reg_temp);  /* skip jump conditionally */
70069 		pc_jump = duk__emit_jump_empty(comp_ctx);
70070 		duk__expr_toforcedreg(comp_ctx, res, args_rbp /*rbp_flags*/, reg_temp /*forced_reg*/);
70071 		duk__patch_jump_here(comp_ctx, pc_jump);
70072 
70073 		duk__ivalue_regconst(res, reg_temp);
70074 		return;
70075 	}
70076 
70077  assign:
70078 	/*
70079 	 *  Shared assignment expression handling
70080 	 *
70081 	 *  args = (opcode << 8) + rbp
70082 	 *
70083 	 *  If 'opcode' is DUK_OP_NONE, plain assignment without arithmetic.
70084 	 *  Syntactically valid left-hand-side forms which are not accepted as
70085 	 *  left-hand-side values (e.g. as in "f() = 1") must NOT cause a
70086 	 *  SyntaxError, but rather a run-time ReferenceError.
70087 	 *
70088 	 *  When evaluating X <op>= Y, the LHS (X) is conceptually evaluated
70089 	 *  to a temporary first.  The RHS is then evaluated.  Finally, the
70090 	 *  <op> is applied to the initial value of RHS (not the value after
70091 	 *  RHS evaluation), and written to X.  Doing so concretely generates
70092 	 *  inefficient code so we'd like to avoid the temporary when possible.
70093 	 *  See: https://github.com/svaarala/duktape/pull/992.
70094 	 *
70095 	 *  The expression value (final LHS value, written to RHS) is
70096 	 *  conceptually copied into a fresh temporary so that it won't
70097 	 *  change even if the LHS/RHS values change in outer expressions.
70098 	 *  For example, it'd be generally incorrect for the expression value
70099 	 *  to be the RHS register binding, unless there's a guarantee that it
70100 	 *  won't change during further expression evaluation.  Using the
70101 	 *  temporary concretely produces inefficient bytecode, so we try to
70102 	 *  avoid the extra temporary for some known-to-be-safe cases.
70103 	 *  Currently the only safe case we detect is a "top level assignment",
70104 	 *  for example "x = y + z;", where the assignment expression value is
70105 	 *  ignored.
70106 	 *  See: test-dev-assign-expr.js and test-bug-assign-mutate-gh381.js.
70107 	 */
70108 
70109 	{
70110 		duk_small_uint_t args_op = args >> 8;
70111 		duk_small_uint_t args_rbp = args & 0xff;
70112 		duk_bool_t toplevel_assign;
70113 
70114 		/* XXX: here we need to know if 'left' is left-hand-side compatible.
70115 		 * That information is no longer available from current expr parsing
70116 		 * state; it would need to be carried into the 'left' ivalue or by
70117 		 * some other means.
70118 		 */
70119 
70120 		/* A top-level assignment is e.g. "x = y;".  For these it's safe
70121 		 * to use the RHS as-is as the expression value, even if the RHS
70122 		 * is a reg-bound identifier.  The RHS ('res') is right associative
70123 		 * so it has consumed all other assignment level operations; the
70124 		 * only relevant lower binding power construct is comma operator
70125 		 * which will ignore the expression value provided here.  Usually
70126 		 * the top level assignment expression value is ignored, but it
70127 		 * is relevant for e.g. eval code.
70128 		 */
70129 		toplevel_assign = (comp_ctx->curr_func.nud_count == 1 && /* one token before */
70130 		                   comp_ctx->curr_func.led_count == 1);  /* one operator (= assign) */
70131 		DUK_DDD(DUK_DDDPRINT("assignment: nud_count=%ld, led_count=%ld, toplevel_assign=%ld",
70132 		                     (long) comp_ctx->curr_func.nud_count,
70133 		                     (long) comp_ctx->curr_func.led_count,
70134 		                     (long) toplevel_assign));
70135 
70136 		if (left->t == DUK_IVAL_VAR) {
70137 			duk_hstring *h_varname;
70138 			duk_regconst_t reg_varbind;
70139 			duk_regconst_t rc_varname;
70140 
70141 			DUK_ASSERT(left->x1.t == DUK_ISPEC_VALUE);  /* LHS is already side effect free */
70142 
70143 			h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
70144 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
70145 				/* E5 Section 11.13.1 (and others for other assignments), step 4. */
70146 				goto syntax_error_lvalue;
70147 			}
70148 			duk_dup(thr, left->x1.valstack_idx);
70149 			(void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
70150 
70151 			if (args_op == DUK_OP_NONE) {
70152 				duk__expr(comp_ctx, res, args_rbp /*rbp_flags*/);
70153 				if (toplevel_assign) {
70154 					/* Any 'res' will do. */
70155 					DUK_DDD(DUK_DDDPRINT("plain assignment, toplevel assign, use as is"));
70156 				} else {
70157 					/* 'res' must be a plain ivalue, and not register-bound variable. */
70158 					DUK_DDD(DUK_DDDPRINT("plain assignment, not toplevel assign, ensure not a reg-bound identifier"));
70159 					if (res->t != DUK_IVAL_PLAIN || (res->x1.t == DUK_ISPEC_REGCONST &&
70160 					                                 DUK__ISREG_NOTTEMP(comp_ctx, res->x1.regconst))) {
70161 						duk__ivalue_totempconst(comp_ctx, res);
70162 					}
70163 				}
70164 			} else {
70165 				/* For X <op>= Y we need to evaluate the pre-op
70166 				 * value of X before evaluating the RHS: the RHS
70167 				 * can change X, but when we do <op> we must use
70168 				 * the pre-op value.
70169 				 */
70170 				duk_regconst_t reg_temp;
70171 
70172 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
70173 
70174 				if (reg_varbind >= 0) {
70175 					duk_regconst_t reg_res;
70176 					duk_regconst_t reg_src;
70177 					duk_int_t pc_temp_load;
70178 					duk_int_t pc_before_rhs;
70179 					duk_int_t pc_after_rhs;
70180 
70181 					if (toplevel_assign) {
70182 						/* 'reg_varbind' is the operation result and can also
70183 						 * become the expression value for top level assignments
70184 						 * such as: "var x; x += y;".
70185 						 */
70186 						DUK_DD(DUK_DDPRINT("<op>= expression is top level, write directly to reg_varbind"));
70187 						reg_res = reg_varbind;
70188 					} else {
70189 						/* Not safe to use 'reg_varbind' as assignment expression
70190 						 * value, so go through a temp.
70191 						 */
70192 						DUK_DD(DUK_DDPRINT("<op>= expression is not top level, write to reg_temp"));
70193 						reg_res = reg_temp;  /* reg_res should be smallest possible */
70194 						reg_temp = DUK__ALLOCTEMP(comp_ctx);
70195 					}
70196 
70197 					/* Try to optimize X <op>= Y for reg-bound
70198 					 * variables.  Detect side-effect free RHS
70199 					 * narrowly by seeing whether it emits code.
70200 					 * If not, rewind the code emitter and overwrite
70201 					 * the unnecessary temp reg load.
70202 					 */
70203 
70204 					pc_temp_load = duk__get_current_pc(comp_ctx);
70205 					duk__emit_a_bc(comp_ctx,
70206 					               DUK_OP_LDREG,
70207 					               reg_temp,
70208 					               reg_varbind);
70209 
70210 					pc_before_rhs = duk__get_current_pc(comp_ctx);
70211 					duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
70212 					DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
70213 					pc_after_rhs = duk__get_current_pc(comp_ctx);
70214 
70215 					DUK_DD(DUK_DDPRINT("pc_temp_load=%ld, pc_before_rhs=%ld, pc_after_rhs=%ld",
70216 					                   (long) pc_temp_load, (long) pc_before_rhs,
70217 					                   (long) pc_after_rhs));
70218 
70219 					if (pc_after_rhs == pc_before_rhs) {
70220 						/* Note: if the reg_temp load generated shuffling
70221 						 * instructions, we may need to rewind more than
70222 						 * one instruction, so use explicit PC computation.
70223 						 */
70224 						DUK_DD(DUK_DDPRINT("rhs is side effect free, rewind and avoid unnecessary temp for reg-based <op>="));
70225 						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));
70226 						reg_src = reg_varbind;
70227 					} else {
70228 						DUK_DD(DUK_DDPRINT("rhs evaluation emitted code, not sure if rhs is side effect free; use temp reg for LHS"));
70229 						reg_src = reg_temp;
70230 					}
70231 
70232 					duk__emit_a_b_c(comp_ctx,
70233 					                args_op | DUK__EMIT_FLAG_BC_REGCONST,
70234 					                reg_res,
70235 					                reg_src,
70236 					                res->x1.regconst);
70237 
70238 					res->x1.regconst = reg_res;
70239 
70240 					/* Ensure compact use of temps. */
70241 					if (DUK__ISREG_TEMP(comp_ctx, reg_res)) {
70242 						DUK__SETTEMP(comp_ctx, reg_res + 1);
70243 					}
70244 				} else {
70245 					/* When LHS is not register bound, always go through a
70246 					 * temporary.  No optimization for top level assignment.
70247 					 */
70248 
70249 					duk__emit_a_bc(comp_ctx,
70250 					               DUK_OP_GETVAR,
70251 					               reg_temp,
70252 					               rc_varname);
70253 
70254 					duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
70255 					DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
70256 
70257 					duk__emit_a_b_c(comp_ctx,
70258 					                args_op | DUK__EMIT_FLAG_BC_REGCONST,
70259 					                reg_temp,
70260 					                reg_temp,
70261 					                res->x1.regconst);
70262 					res->x1.regconst = reg_temp;
70263 				}
70264 
70265 				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
70266 			}
70267 
70268 			/* At this point 'res' holds the potential expression value.
70269 			 * It can be basically any ivalue here, including a reg-bound
70270 			 * identifier (if code above deems it safe) or a unary/binary
70271 			 * operation.  Operations must be resolved to a side effect free
70272 			 * plain value, and the side effects must happen exactly once.
70273 			 */
70274 
70275 			if (reg_varbind >= 0) {
70276 				if (res->t != DUK_IVAL_PLAIN) {
70277 					/* Resolve 'res' directly into the LHS binding, and use
70278 					 * that as the expression value if safe.  If not safe,
70279 					 * resolve to a temp/const and copy to LHS.
70280 					 */
70281 					if (toplevel_assign) {
70282 						duk__ivalue_toforcedreg(comp_ctx, res, (duk_int_t) reg_varbind);
70283 					} else {
70284 						duk__ivalue_totempconst(comp_ctx, res);
70285 						duk__copy_ivalue(comp_ctx, res, left);  /* use 'left' as a temp */
70286 						duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
70287 					}
70288 				} else {
70289 					/* Use 'res' as the expression value (it's side effect
70290 					 * free and may be a plain value, a register, or a
70291 					 * constant) and write it to the LHS binding too.
70292 					 */
70293 					duk__copy_ivalue(comp_ctx, res, left);  /* use 'left' as a temp */
70294 					duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
70295 				}
70296 			} else {
70297 				/* Only a reg fits into 'A' so coerce 'res' into a register
70298 				 * for PUTVAR.
70299 				 *
70300 				 * XXX: here the current A/B/C split is suboptimal: we could
70301 				 * just use 9 bits for reg_res (and support constants) and 17
70302 				 * instead of 18 bits for the varname const index.
70303 				 */
70304 
70305 				duk__ivalue_toreg(comp_ctx, res);
70306 				duk__emit_a_bc(comp_ctx,
70307 				               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
70308 				               res->x1.regconst,
70309 				               rc_varname);
70310 			}
70311 
70312 			/* 'res' contains expression value */
70313 		} else if (left->t == DUK_IVAL_PROP) {
70314 			/* E5 Section 11.13.1 (and others) step 4 never matches for prop writes -> no check */
70315 			duk_regconst_t reg_obj;
70316 			duk_regconst_t rc_key;
70317 			duk_regconst_t rc_res;
70318 			duk_regconst_t reg_temp;
70319 
70320 			/* Property access expressions ('a[b]') are critical to correct
70321 			 * LHS evaluation ordering, see test-dev-assign-eval-order*.js.
70322 			 * We must make sure that the LHS target slot (base object and
70323 			 * key) don't change during RHS evaluation.  The only concrete
70324 			 * problem is a register reference to a variable-bound register
70325 			 * (i.e., non-temp).  Require temp regs for both key and base.
70326 			 *
70327 			 * Don't allow a constant for the object (even for a number
70328 			 * etc), as it goes into the 'A' field of the opcode.
70329 			 */
70330 
70331 			reg_obj = duk__ispec_toregconst_raw(comp_ctx,
70332 			                                    &left->x1,
70333 			                                    -1 /*forced_reg*/,
70334 			                                    DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
70335 
70336 			rc_key = duk__ispec_toregconst_raw(comp_ctx,
70337 			                                   &left->x2,
70338 			                                   -1 /*forced_reg*/,
70339 			                                   DUK__IVAL_FLAG_REQUIRE_TEMP | DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
70340 
70341 			/* Evaluate RHS only when LHS is safe. */
70342 
70343 			if (args_op == DUK_OP_NONE) {
70344 				duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
70345 				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
70346 				rc_res = res->x1.regconst;
70347 			} else {
70348 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
70349 				duk__emit_a_b_c(comp_ctx,
70350 				                DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST,
70351 				                reg_temp,
70352 				                reg_obj,
70353 				                rc_key);
70354 
70355 				duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
70356 				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
70357 
70358 				duk__emit_a_b_c(comp_ctx,
70359 				                args_op | DUK__EMIT_FLAG_BC_REGCONST,
70360 				                reg_temp,
70361 				                reg_temp,
70362 				                res->x1.regconst);
70363 				rc_res = reg_temp;
70364 			}
70365 
70366 			duk__emit_a_b_c(comp_ctx,
70367 			                DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE | DUK__EMIT_FLAG_BC_REGCONST,
70368 			                reg_obj,
70369 			                rc_key,
70370 			                rc_res);
70371 
70372 			duk__ivalue_regconst(res, rc_res);
70373 		} else {
70374 			/* No support for lvalues returned from new or function call expressions.
70375 			 * However, these must NOT cause compile-time SyntaxErrors, but run-time
70376 			 * ReferenceErrors.  Both left and right sides of the assignment must be
70377 			 * evaluated before throwing a ReferenceError.  For instance:
70378 			 *
70379 			 *     f() = g();
70380 			 *
70381 			 * must result in f() being evaluated, then g() being evaluated, and
70382 			 * finally, a ReferenceError being thrown.  See E5 Section 11.13.1.
70383 			 */
70384 
70385 			duk_regconst_t rc_res;
70386 
70387 			/* First evaluate LHS fully to ensure all side effects are out. */
70388 			duk__ivalue_toplain_ignore(comp_ctx, left);
70389 
70390 			/* Then evaluate RHS fully (its value becomes the expression value too).
70391 			 * Technically we'd need the side effect safety check here too, but because
70392 			 * we always throw using INVLHS the result doesn't matter.
70393 			 */
70394 			rc_res = duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
70395 
70396 			duk__emit_op_only(comp_ctx, DUK_OP_INVLHS);
70397 
70398 			duk__ivalue_regconst(res, rc_res);
70399 		}
70400 
70401 		return;
70402 	}
70403 
70404  postincdec:
70405 	{
70406 		/*
70407 		 *  Post-increment/decrement will return the original value as its
70408 		 *  result value.  However, even that value will be coerced using
70409 		 *  ToNumber() which is quite awkward.  Specific bytecode opcodes
70410 		 *  are used to handle these semantics.
70411 		 *
70412 		 *  Note that post increment/decrement has a "no LineTerminator here"
70413 		 *  restriction.  This is handled by duk__expr_lbp(), which forcibly terminates
70414 		 *  the previous expression if a LineTerminator occurs before '++'/'--'.
70415 		 */
70416 
70417 		duk_regconst_t reg_res;
70418 		duk_small_uint_t args_op1 = (args >> 8) & 0xff;  /* DUK_OP_POSTINCR/DUK_OP_POSTDECR */
70419 		duk_small_uint_t args_op2 = args >> 16;          /* DUK_OP_POSTINCP_RR/DUK_OP_POSTDECP_RR */
70420 
70421 		/* Specific assumptions for opcode numbering. */
70422 		DUK_ASSERT(DUK_OP_POSTINCR + 4 == DUK_OP_POSTINCV);
70423 		DUK_ASSERT(DUK_OP_POSTDECR + 4 == DUK_OP_POSTDECV);
70424 
70425 		reg_res = DUK__ALLOCTEMP(comp_ctx);
70426 
70427 		if (left->t == DUK_IVAL_VAR) {
70428 			duk_hstring *h_varname;
70429 			duk_regconst_t reg_varbind;
70430 			duk_regconst_t rc_varname;
70431 
70432 			h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
70433 
70434 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
70435 				goto syntax_error;
70436 			}
70437 
70438 			duk_dup(thr, left->x1.valstack_idx);
70439 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
70440 				duk__emit_a_bc(comp_ctx,
70441 				               args_op1,  /* e.g. DUK_OP_POSTINCR */
70442 				               reg_res,
70443 				               reg_varbind);
70444 			} else {
70445 				duk__emit_a_bc(comp_ctx,
70446 				               args_op1 + 4,  /* e.g. DUK_OP_POSTINCV */
70447 				               reg_res,
70448 				               rc_varname);
70449 			}
70450 
70451 			DUK_DDD(DUK_DDDPRINT("postincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
70452 			                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
70453 		} else if (left->t == DUK_IVAL_PROP) {
70454 			duk_regconst_t reg_obj;  /* allocate to reg only (not const) */
70455 			duk_regconst_t rc_key;
70456 
70457 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &left->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
70458 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
70459 			duk__emit_a_b_c(comp_ctx,
70460 			                args_op2 | DUK__EMIT_FLAG_BC_REGCONST,  /* e.g. DUK_OP_POSTINCP */
70461 			                reg_res,
70462 			                reg_obj,
70463 			                rc_key);
70464 		} else {
70465 			/* Technically return value is not needed because INVLHS will
70466 			 * unconditially throw a ReferenceError.  Coercion is necessary
70467 			 * for proper semantics (consider ToNumber() called for an object).
70468 			 * Use DUK_OP_UNP with a dummy register to get ToNumber().
70469 			 */
70470 			duk__ivalue_toforcedreg(comp_ctx, left, reg_res);
70471 			duk__emit_bc(comp_ctx,
70472 			             DUK_OP_UNP,
70473 			             reg_res);  /* for side effects, result ignored */
70474 			duk__emit_op_only(comp_ctx,
70475 			                  DUK_OP_INVLHS);
70476 		}
70477 
70478 		DUK__SETTEMP(comp_ctx, reg_res + 1);
70479 		duk__ivalue_regconst(res, reg_res);
70480 		return;
70481 	}
70482 
70483  syntax_error:
70484 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
70485 	DUK_WO_NORETURN(return;);
70486 
70487  syntax_error_lvalue:
70488 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LVALUE);
70489 	DUK_WO_NORETURN(return;);
70490 }
70491 
70492 DUK_LOCAL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx) {
70493 	duk_small_uint_t tok = comp_ctx->curr_token.t;
70494 
70495 	DUK_ASSERT_DISABLE(tok >= DUK_TOK_MINVAL);  /* unsigned */
70496 	DUK_ASSERT(tok <= DUK_TOK_MAXVAL);
70497 	DUK_ASSERT(sizeof(duk__token_lbp) == DUK_TOK_MAXVAL + 1);
70498 
70499 	/* XXX: integrate support for this into led() instead?
70500 	 * Similar issue as post-increment/post-decrement.
70501 	 */
70502 
70503 	/* prevent duk__expr_led() by using a binding power less than anything valid */
70504 	if (tok == DUK_TOK_IN && !comp_ctx->curr_func.allow_in) {
70505 		return 0;
70506 	}
70507 
70508 	if ((tok == DUK_TOK_DECREMENT || tok == DUK_TOK_INCREMENT) &&
70509 	    (comp_ctx->curr_token.lineterm)) {
70510 		/* '++' or '--' in a post-increment/decrement position,
70511 		 * and a LineTerminator occurs between the operator and
70512 		 * the preceding expression.  Force the previous expr
70513 		 * to terminate, in effect treating e.g. "a,b\n++" as
70514 		 * "a,b;++" (= SyntaxError).
70515 		 */
70516 		return 0;
70517 	}
70518 
70519 	return DUK__TOKEN_LBP_GET_BP(duk__token_lbp[tok]);  /* format is bit packed */
70520 }
70521 
70522 /*
70523  *  Expression parsing.
70524  *
70525  *  Upon entry to 'expr' and its variants, 'curr_tok' is assumed to be the
70526  *  first token of the expression.  Upon exit, 'curr_tok' will be the first
70527  *  token not part of the expression (e.g. semicolon terminating an expression
70528  *  statement).
70529  */
70530 
70531 #define DUK__EXPR_RBP_MASK           0xff
70532 #define DUK__EXPR_FLAG_REJECT_IN     (1 << 8)   /* reject 'in' token (used for for-in) */
70533 #define DUK__EXPR_FLAG_ALLOW_EMPTY   (1 << 9)   /* allow empty expression */
70534 #define DUK__EXPR_FLAG_REQUIRE_INIT  (1 << 10)  /* require initializer for var/const */
70535 
70536 /* main expression parser function */
70537 DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70538 	duk_hthread *thr = comp_ctx->thr;
70539 	duk_ivalue tmp_alloc;   /* 'res' is used for "left", and 'tmp' for "right" */
70540 	duk_ivalue *tmp = &tmp_alloc;
70541 	duk_small_uint_t rbp;
70542 
70543 	DUK__RECURSION_INCREASE(comp_ctx, thr);
70544 
70545 	duk_require_stack(thr, DUK__PARSE_EXPR_SLOTS);
70546 
70547 	/* filter out flags from exprtop rbp_flags here to save space */
70548 	rbp = rbp_flags & DUK__EXPR_RBP_MASK;
70549 
70550 	DUK_DDD(DUK_DDDPRINT("duk__expr(), rbp_flags=%ld, rbp=%ld, allow_in=%ld, paren_level=%ld",
70551 	                     (long) rbp_flags, (long) rbp, (long) comp_ctx->curr_func.allow_in,
70552 	                     (long) comp_ctx->curr_func.paren_level));
70553 
70554 	duk_memzero(&tmp_alloc, sizeof(tmp_alloc));
70555 	tmp->x1.valstack_idx = duk_get_top(thr);
70556 	tmp->x2.valstack_idx = tmp->x1.valstack_idx + 1;
70557 	duk_push_undefined(thr);
70558 	duk_push_undefined(thr);
70559 
70560 	/* XXX: where to release temp regs in intermediate expressions?
70561 	 * e.g. 1+2+3 -> don't inflate temp register count when parsing this.
70562 	 * that particular expression temp regs can be forced here.
70563 	 */
70564 
70565 	/* XXX: increase ctx->expr_tokens here for every consumed token
70566 	 * (this would be a nice statistic)?
70567 	 */
70568 
70569 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
70570 		/* XXX: possibly incorrect handling of empty expression */
70571 		DUK_DDD(DUK_DDDPRINT("empty expression"));
70572 		if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY)) {
70573 			DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);
70574 			DUK_WO_NORETURN(return;);
70575 		}
70576 		duk_push_undefined(thr);
70577 		duk__ivalue_plain_fromstack(comp_ctx, res);
70578 		goto cleanup;
70579 	}
70580 
70581 	duk__advance(comp_ctx);
70582 	duk__expr_nud(comp_ctx, res);  /* reuse 'res' as 'left' */
70583 	while (rbp < duk__expr_lbp(comp_ctx)) {
70584 		duk__advance(comp_ctx);
70585 		duk__expr_led(comp_ctx, res, tmp);
70586 		duk__copy_ivalue(comp_ctx, tmp, res);  /* tmp -> res */
70587 	}
70588 
70589  cleanup:
70590 	/* final result is already in 'res' */
70591 
70592 	duk_pop_2(thr);
70593 
70594 	DUK__RECURSION_DECREASE(comp_ctx, thr);
70595 }
70596 
70597 DUK_LOCAL void duk__exprtop(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70598 	duk_hthread *thr = comp_ctx->thr;
70599 
70600 	/* Note: these variables must reside in 'curr_func' instead of the global
70601 	 * context: when parsing function expressions, expression parsing is nested.
70602 	 */
70603 	comp_ctx->curr_func.nud_count = 0;
70604 	comp_ctx->curr_func.led_count = 0;
70605 	comp_ctx->curr_func.paren_level = 0;
70606 	comp_ctx->curr_func.expr_lhs = 1;
70607 	comp_ctx->curr_func.allow_in = (rbp_flags & DUK__EXPR_FLAG_REJECT_IN ? 0 : 1);
70608 
70609 	duk__expr(comp_ctx, res, rbp_flags);
70610 
70611 	if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY) && duk__expr_is_empty(comp_ctx)) {
70612 		DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);
70613 		DUK_WO_NORETURN(return;);
70614 	}
70615 }
70616 
70617 /* A bunch of helpers (for size optimization) that combine duk__expr()/duk__exprtop()
70618  * and result conversions.
70619  *
70620  * Each helper needs at least 2-3 calls to make it worth while to wrap.
70621  */
70622 
70623 #if 0  /* unused */
70624 DUK_LOCAL duk_regconst_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70625 	duk__expr(comp_ctx, res, rbp_flags);
70626 	return duk__ivalue_toreg(comp_ctx, res);
70627 }
70628 #endif
70629 
70630 #if 0  /* unused */
70631 DUK_LOCAL duk_regconst_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70632 	duk__expr(comp_ctx, res, rbp_flags);
70633 	return duk__ivalue_totemp(comp_ctx, res);
70634 }
70635 #endif
70636 
70637 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) {
70638 	DUK_ASSERT(forced_reg >= 0);
70639 	duk__expr(comp_ctx, res, rbp_flags);
70640 	duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
70641 }
70642 
70643 DUK_LOCAL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70644 	duk__expr(comp_ctx, res, rbp_flags);
70645 	return duk__ivalue_toregconst(comp_ctx, res);
70646 }
70647 
70648 #if 0  /* unused */
70649 DUK_LOCAL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70650 	duk__expr(comp_ctx, res, rbp_flags);
70651 	return duk__ivalue_totempconst(comp_ctx, res);
70652 }
70653 #endif
70654 
70655 DUK_LOCAL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70656 	duk__expr(comp_ctx, res, rbp_flags);
70657 	duk__ivalue_toplain(comp_ctx, res);
70658 }
70659 
70660 DUK_LOCAL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70661 	duk__expr(comp_ctx, res, rbp_flags);
70662 	duk__ivalue_toplain_ignore(comp_ctx, res);
70663 }
70664 
70665 DUK_LOCAL duk_regconst_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70666 	duk__exprtop(comp_ctx, res, rbp_flags);
70667 	return duk__ivalue_toreg(comp_ctx, res);
70668 }
70669 
70670 #if 0  /* unused */
70671 DUK_LOCAL duk_regconst_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70672 	duk__exprtop(comp_ctx, res, rbp_flags);
70673 	return duk__ivalue_totemp(comp_ctx, res);
70674 }
70675 #endif
70676 
70677 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) {
70678 	DUK_ASSERT(forced_reg >= 0);
70679 	duk__exprtop(comp_ctx, res, rbp_flags);
70680 	duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
70681 }
70682 
70683 DUK_LOCAL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70684 	duk__exprtop(comp_ctx, res, rbp_flags);
70685 	return duk__ivalue_toregconst(comp_ctx, res);
70686 }
70687 
70688 #if 0  /* unused */
70689 DUK_LOCAL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, int rbp_flags) {
70690 	duk__exprtop(comp_ctx, res, rbp_flags);
70691 	duk__ivalue_toplain_ignore(comp_ctx, res);
70692 }
70693 #endif
70694 
70695 /*
70696  *  Parse an individual source element (top level statement) or a statement.
70697  *
70698  *  Handles labeled statements automatically (peeling away labels before
70699  *  parsing an expression that follows the label(s)).
70700  *
70701  *  Upon entry, 'curr_tok' contains the first token of the statement (parsed
70702  *  in "allow regexp literal" mode).  Upon exit, 'curr_tok' contains the first
70703  *  token following the statement (if the statement has a terminator, this is
70704  *  the token after the terminator).
70705  */
70706 
70707 #define DUK__HAS_VAL                  (1 << 0)  /* stmt has non-empty value */
70708 #define DUK__HAS_TERM                 (1 << 1)  /* stmt has explicit/implicit semicolon terminator */
70709 #define DUK__ALLOW_AUTO_SEMI_ALWAYS   (1 << 2)  /* allow automatic semicolon even without lineterm (compatibility) */
70710 #define DUK__STILL_PROLOGUE           (1 << 3)  /* statement does not terminate directive prologue */
70711 #define DUK__IS_TERMINAL              (1 << 4)  /* statement is guaranteed to be terminal (control doesn't flow to next statement) */
70712 
70713 /* Parse a single variable declaration (e.g. "i" or "i=10").  A leading 'var'
70714  * has already been eaten.  These is no return value in 'res', it is used only
70715  * as a temporary.
70716  *
70717  * When called from 'for-in' statement parser, the initializer expression must
70718  * not allow the 'in' token.  The caller supply additional expression parsing
70719  * flags (like DUK__EXPR_FLAG_REJECT_IN) in 'expr_flags'.
70720  *
70721  * Finally, out_rc_varname and out_reg_varbind are updated to reflect where
70722  * the identifier is bound:
70723  *
70724  *    If register bound:      out_reg_varbind >= 0, out_rc_varname == 0 (ignore)
70725  *    If not register bound:  out_reg_varbind < 0, out_rc_varname >= 0
70726  *
70727  * These allow the caller to use the variable for further assignment, e.g.
70728  * as is done in 'for-in' parsing.
70729  */
70730 
70731 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) {
70732 	duk_hthread *thr = comp_ctx->thr;
70733 	duk_hstring *h_varname;
70734 	duk_regconst_t reg_varbind;
70735 	duk_regconst_t rc_varname;
70736 
70737 	/* assume 'var' has been eaten */
70738 
70739 	/* Note: Identifier rejects reserved words */
70740 	if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
70741 		goto syntax_error;
70742 	}
70743 	h_varname = comp_ctx->curr_token.str1;
70744 
70745 	DUK_ASSERT(h_varname != NULL);
70746 
70747 	/* strict mode restrictions (E5 Section 12.2.1) */
70748 	if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
70749 		goto syntax_error;
70750 	}
70751 
70752 	/* register declarations in first pass */
70753 	if (comp_ctx->curr_func.in_scanning) {
70754 		duk_uarridx_t n;
70755 		DUK_DDD(DUK_DDDPRINT("register variable declaration %!O in pass 1",
70756 		                     (duk_heaphdr *) h_varname));
70757 		n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
70758 		duk_push_hstring(thr, h_varname);
70759 		duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n);
70760 		duk_push_int(thr, DUK_DECL_TYPE_VAR + (0 << 8));
70761 		duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n + 1);
70762 	}
70763 
70764 	duk_push_hstring(thr, h_varname);  /* push before advancing to keep reachable */
70765 
70766 	/* register binding lookup is based on varmap (even in first pass) */
70767 	duk_dup_top(thr);
70768 	(void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
70769 
70770 	duk__advance(comp_ctx);  /* eat identifier */
70771 
70772 	if (comp_ctx->curr_token.t == DUK_TOK_EQUALSIGN) {
70773 		duk__advance(comp_ctx);
70774 
70775 		DUK_DDD(DUK_DDDPRINT("vardecl, assign to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
70776 		                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
70777 
70778 		duk__exprtop(comp_ctx, res, DUK__BP_COMMA | expr_flags /*rbp_flags*/);  /* AssignmentExpression */
70779 
70780 		if (reg_varbind >= 0) {
70781 			duk__ivalue_toforcedreg(comp_ctx, res, reg_varbind);
70782 		} else {
70783 			duk_regconst_t reg_val;
70784 			reg_val = duk__ivalue_toreg(comp_ctx, res);
70785 			duk__emit_a_bc(comp_ctx,
70786 			               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
70787 			               reg_val,
70788 			               rc_varname);
70789 		}
70790 	} else {
70791 		if (expr_flags & DUK__EXPR_FLAG_REQUIRE_INIT) {
70792 			/* Used for minimal 'const': initializer required. */
70793 			goto syntax_error;
70794 		}
70795 	}
70796 
70797 	duk_pop(thr);  /* pop varname */
70798 
70799 	*out_rc_varname = rc_varname;
70800 	*out_reg_varbind = reg_varbind;
70801 
70802 	return;
70803 
70804  syntax_error:
70805 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_VAR_DECLARATION);
70806 	DUK_WO_NORETURN(return;);
70807 }
70808 
70809 DUK_LOCAL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags) {
70810 	duk_regconst_t reg_varbind;
70811 	duk_regconst_t rc_varname;
70812 
70813 	duk__advance(comp_ctx);  /* eat 'var' */
70814 
70815 	for (;;) {
70816 		/* rc_varname and reg_varbind are ignored here */
70817 		duk__parse_var_decl(comp_ctx, res, 0 | expr_flags, &reg_varbind, &rc_varname);
70818 
70819 		if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
70820 			break;
70821 		}
70822 		duk__advance(comp_ctx);
70823 	}
70824 }
70825 
70826 DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
70827 	duk_hthread *thr = comp_ctx->thr;
70828 	duk_int_t pc_v34_lhs;         /* start variant 3/4 left-hand-side code (L1 in doc/compiler.rst example) */
70829 	duk_regconst_t temp_reset;    /* knock back "next temp" to this whenever possible */
70830 	duk_regconst_t reg_temps;     /* preallocated temporaries (2) for variants 3 and 4 */
70831 
70832 	DUK_DDD(DUK_DDDPRINT("start parsing a for/for-in statement"));
70833 
70834 	/* Two temporaries are preallocated here for variants 3 and 4 which need
70835 	 * registers which are never clobbered by expressions in the loop
70836 	 * (concretely: for the enumerator object and the next enumerated value).
70837 	 * Variants 1 and 2 "release" these temps.
70838 	 */
70839 
70840 	reg_temps = DUK__ALLOCTEMPS(comp_ctx, 2);
70841 
70842 	temp_reset = DUK__GETTEMP(comp_ctx);
70843 
70844 	/*
70845 	 *  For/for-in main variants are:
70846 	 *
70847 	 *    1. for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement
70848 	 *    2. for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement
70849 	 *    3. for (LeftHandSideExpression in Expression) Statement
70850 	 *    4. for (var VariableDeclarationNoIn in Expression) Statement
70851 	 *
70852 	 *  Parsing these without arbitrary lookahead or backtracking is relatively
70853 	 *  tricky but we manage to do so for now.
70854 	 *
70855 	 *  See doc/compiler.rst for a detailed discussion of control flow
70856 	 *  issues, evaluation order issues, etc.
70857 	 */
70858 
70859 	duk__advance(comp_ctx);  /* eat 'for' */
70860 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
70861 
70862 	DUK_DDD(DUK_DDDPRINT("detecting for/for-in loop variant, pc=%ld", (long) duk__get_current_pc(comp_ctx)));
70863 
70864 	/* a label site has been emitted by duk__parse_stmt() automatically
70865 	 * (it will also emit the ENDLABEL).
70866 	 */
70867 
70868 	if (comp_ctx->curr_token.t == DUK_TOK_VAR) {
70869 		/*
70870 		 *  Variant 2 or 4
70871 		 */
70872 
70873 		duk_regconst_t reg_varbind;  /* variable binding register if register-bound (otherwise < 0) */
70874 		duk_regconst_t rc_varname;   /* variable name reg/const, if variable not register-bound */
70875 
70876 		duk__advance(comp_ctx);  /* eat 'var' */
70877 		duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
70878 		DUK__SETTEMP(comp_ctx, temp_reset);
70879 
70880 		if (comp_ctx->curr_token.t == DUK_TOK_IN) {
70881 			/*
70882 			 *  Variant 4
70883 			 */
70884 
70885 			DUK_DDD(DUK_DDDPRINT("detected for variant 4: for (var VariableDeclarationNoIn in Expression) Statement"));
70886 			pc_v34_lhs = duk__get_current_pc(comp_ctx);  /* jump is inserted here */
70887 			if (reg_varbind >= 0) {
70888 				duk__emit_a_bc(comp_ctx,
70889 				               DUK_OP_LDREG,
70890 				               reg_varbind,
70891 				               reg_temps + 0);
70892 			} else {
70893 				duk__emit_a_bc(comp_ctx,
70894 				               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
70895 				               reg_temps + 0,
70896 				               rc_varname);
70897 			}
70898 			goto parse_3_or_4;
70899 		} else {
70900 			/*
70901 			 *  Variant 2
70902 			 */
70903 
70904 			DUK_DDD(DUK_DDDPRINT("detected for variant 2: for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement"));
70905 			for (;;) {
70906 				/* more initializers */
70907 				if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
70908 					break;
70909 				}
70910 				DUK_DDD(DUK_DDDPRINT("variant 2 has another variable initializer"));
70911 
70912 				duk__advance(comp_ctx);  /* eat comma */
70913 				duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
70914 			}
70915 			goto parse_1_or_2;
70916 		}
70917 	} else {
70918 		/*
70919 		 *  Variant 1 or 3
70920 		 */
70921 
70922 		pc_v34_lhs = duk__get_current_pc(comp_ctx);  /* jump is inserted here (variant 3) */
70923 
70924 		/* Note that duk__exprtop() here can clobber any reg above current temp_next,
70925 		 * so any loop variables (e.g. enumerator) must be "preallocated".
70926 		 */
70927 
70928 		/* don't coerce yet to a plain value (variant 3 needs special handling) */
70929 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_REJECT_IN | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression */
70930 		if (comp_ctx->curr_token.t == DUK_TOK_IN) {
70931 			/*
70932 			 *  Variant 3
70933 			 */
70934 
70935 			/* XXX: need to determine LHS type, and check that it is LHS compatible */
70936 			DUK_DDD(DUK_DDDPRINT("detected for variant 3: for (LeftHandSideExpression in Expression) Statement"));
70937 			if (duk__expr_is_empty(comp_ctx)) {
70938 				goto syntax_error;  /* LeftHandSideExpression does not allow empty expression */
70939 			}
70940 
70941 			if (res->t == DUK_IVAL_VAR) {
70942 				duk_regconst_t reg_varbind;
70943 				duk_regconst_t rc_varname;
70944 
70945 				duk_dup(thr, res->x1.valstack_idx);
70946 				if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
70947 					duk__emit_a_bc(comp_ctx,
70948 					               DUK_OP_LDREG,
70949 					               reg_varbind,
70950 					               reg_temps + 0);
70951 				} else {
70952 					duk__emit_a_bc(comp_ctx,
70953 					               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
70954 					               reg_temps + 0,
70955 					               rc_varname);
70956 				}
70957 			} else if (res->t == DUK_IVAL_PROP) {
70958 				/* Don't allow a constant for the object (even for a number etc), as
70959 				 * it goes into the 'A' field of the opcode.
70960 				 */
70961 				duk_regconst_t reg_obj;
70962 				duk_regconst_t rc_key;
70963 				reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
70964 				rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
70965 				duk__emit_a_b_c(comp_ctx,
70966 				                DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE | DUK__EMIT_FLAG_BC_REGCONST,
70967 				                reg_obj,
70968 				                rc_key,
70969 				                reg_temps + 0);
70970 			} else {
70971 				duk__ivalue_toplain_ignore(comp_ctx, res);  /* just in case */
70972 				duk__emit_op_only(comp_ctx,
70973 				                  DUK_OP_INVLHS);
70974 			}
70975 			goto parse_3_or_4;
70976 		} else {
70977 			/*
70978 			 *  Variant 1
70979 			 */
70980 
70981 			DUK_DDD(DUK_DDDPRINT("detected for variant 1: for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement"));
70982 			duk__ivalue_toplain_ignore(comp_ctx, res);
70983 			goto parse_1_or_2;
70984 		}
70985 	}
70986 
70987  parse_1_or_2:
70988 	/*
70989 	 *  Parse variant 1 or 2.  The first part expression (which differs
70990 	 *  in the variants) has already been parsed and its code emitted.
70991 	 *
70992 	 *  reg_temps + 0: unused
70993 	 *  reg_temps + 1: unused
70994 	 */
70995 	{
70996 		duk_regconst_t rc_cond;
70997 		duk_int_t pc_l1, pc_l2, pc_l3, pc_l4;
70998 		duk_int_t pc_jumpto_l3, pc_jumpto_l4;
70999 		duk_bool_t expr_c_empty;
71000 
71001 		DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 1 and 2"));
71002 
71003 		/* "release" preallocated temps since we won't need them */
71004 		temp_reset = reg_temps + 0;
71005 		DUK__SETTEMP(comp_ctx, temp_reset);
71006 
71007 		duk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);
71008 
71009 		pc_l1 = duk__get_current_pc(comp_ctx);
71010 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression_opt */
71011 		if (duk__expr_is_empty(comp_ctx)) {
71012 			/* no need to coerce */
71013 			pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* to body */
71014 			pc_jumpto_l4 = -1;  /* omitted */
71015 		} else {
71016 			rc_cond = duk__ivalue_toregconst(comp_ctx, res);
71017 			duk__emit_if_false_skip(comp_ctx, rc_cond);
71018 			pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* to body */
71019 			pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);  /* to exit */
71020 		}
71021 		DUK__SETTEMP(comp_ctx, temp_reset);
71022 
71023 		duk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);
71024 
71025 		pc_l2 = duk__get_current_pc(comp_ctx);
71026 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression_opt */
71027 		if (duk__expr_is_empty(comp_ctx)) {
71028 			/* no need to coerce */
71029 			expr_c_empty = 1;
71030 			/* JUMP L1 omitted */
71031 		} else {
71032 			duk__ivalue_toplain_ignore(comp_ctx, res);
71033 			expr_c_empty = 0;
71034 			duk__emit_jump(comp_ctx, pc_l1);
71035 		}
71036 		DUK__SETTEMP(comp_ctx, temp_reset);
71037 
71038 		comp_ctx->curr_func.allow_regexp_in_adv = 1;
71039 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
71040 
71041 		pc_l3 = duk__get_current_pc(comp_ctx);
71042 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
71043 		if (expr_c_empty) {
71044 			duk__emit_jump(comp_ctx, pc_l1);
71045 		} else {
71046 			duk__emit_jump(comp_ctx, pc_l2);
71047 		}
71048 		/* temp reset is not necessary after duk__parse_stmt(), which already does it */
71049 
71050 		pc_l4 = duk__get_current_pc(comp_ctx);
71051 
71052 		DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l3: %ld->%ld, jumpto_l4: %ld->%ld, "
71053 		                     "break: %ld->%ld, continue: %ld->%ld",
71054 			             (long) pc_jumpto_l3, (long) pc_l3, (long) pc_jumpto_l4, (long) pc_l4,
71055 		                     (long) (pc_label_site + 1), (long) pc_l4, (long) (pc_label_site + 2), (long) pc_l2));
71056 
71057 		duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
71058 		duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
71059 		duk__patch_jump(comp_ctx,
71060 		                pc_label_site + 1,
71061 		                pc_l4);                         /* break jump */
71062 		duk__patch_jump(comp_ctx,
71063 		                pc_label_site + 2,
71064 		                expr_c_empty ? pc_l1 : pc_l2);  /* continue jump */
71065 	}
71066 	goto finished;
71067 
71068  parse_3_or_4:
71069 	/*
71070 	 *  Parse variant 3 or 4.
71071 	 *
71072 	 *  For variant 3 (e.g. "for (A in C) D;") the code for A (except the
71073 	 *  final property/variable write) has already been emitted.  The first
71074 	 *  instruction of that code is at pc_v34_lhs; a JUMP needs to be inserted
71075 	 *  there to satisfy control flow needs.
71076 	 *
71077 	 *  For variant 4, if the variable declaration had an initializer
71078 	 *  (e.g. "for (var A = B in C) D;") the code for the assignment
71079 	 *  (B) has already been emitted.
71080 	 *
71081 	 *  Variables set before entering here:
71082 	 *
71083 	 *    pc_v34_lhs:    insert a "JUMP L2" here (see doc/compiler.rst example).
71084 	 *    reg_temps + 0: iteration target value (written to LHS)
71085 	 *    reg_temps + 1: enumerator object
71086 	 */
71087 	{
71088 		duk_int_t pc_l1, pc_l2, pc_l3, pc_l4, pc_l5;
71089 		duk_int_t pc_jumpto_l2, pc_jumpto_l3, pc_jumpto_l4, pc_jumpto_l5;
71090 		duk_regconst_t reg_target;
71091 
71092 		DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 3 and 4, pc_v34_lhs=%ld", (long) pc_v34_lhs));
71093 
71094 		DUK__SETTEMP(comp_ctx, temp_reset);
71095 
71096 		/* First we need to insert a jump in the middle of previously
71097 		 * emitted code to get the control flow right.  No jumps can
71098 		 * cross the position where the jump is inserted.  See doc/compiler.rst
71099 		 * for discussion on the intricacies of control flow and side effects
71100 		 * for variants 3 and 4.
71101 		 */
71102 
71103 		duk__insert_jump_entry(comp_ctx, pc_v34_lhs);
71104 		pc_jumpto_l2 = pc_v34_lhs;  /* inserted jump */
71105 		pc_l1 = pc_v34_lhs + 1;     /* +1, right after inserted jump */
71106 
71107 		/* The code for writing reg_temps + 0 to the left hand side has already
71108 		 * been emitted.
71109 		 */
71110 
71111 		pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* -> loop body */
71112 
71113 		duk__advance(comp_ctx);  /* eat 'in' */
71114 
71115 		/* Parse enumeration target and initialize enumerator.  For 'null' and 'undefined',
71116 		 * INITENUM will creates a 'null' enumerator which works like an empty enumerator
71117 		 * (E5 Section 12.6.4, step 3).  Note that INITENUM requires the value to be in a
71118 		 * register (constant not allowed).
71119 		 */
71120 
71121 		pc_l2 = duk__get_current_pc(comp_ctx);
71122 		reg_target = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression */
71123 		duk__emit_b_c(comp_ctx,
71124 		              DUK_OP_INITENUM | DUK__EMIT_FLAG_B_IS_TARGET,
71125 		              reg_temps + 1,
71126 		              reg_target);
71127 		pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);
71128 		DUK__SETTEMP(comp_ctx, temp_reset);
71129 
71130 		comp_ctx->curr_func.allow_regexp_in_adv = 1;
71131 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
71132 
71133 		pc_l3 = duk__get_current_pc(comp_ctx);
71134 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
71135 		/* temp reset is not necessary after duk__parse_stmt(), which already does it */
71136 
71137 		/* NEXTENUM needs a jump slot right after the main opcode.
71138 		 * We need the code emitter to reserve the slot: if there's
71139 		 * target shuffling, the target shuffle opcodes must happen
71140 		 * after the jump slot (for NEXTENUM the shuffle opcodes are
71141 		 * not needed if the enum is finished).
71142 		 */
71143 		pc_l4 = duk__get_current_pc(comp_ctx);
71144 		duk__emit_b_c(comp_ctx,
71145 		              DUK_OP_NEXTENUM | DUK__EMIT_FLAG_B_IS_TARGET | DUK__EMIT_FLAG_RESERVE_JUMPSLOT,
71146 		              reg_temps + 0,
71147 		              reg_temps + 1);
71148 		pc_jumpto_l5 = comp_ctx->emit_jumpslot_pc;  /* NEXTENUM jump slot: executed when enum finished */
71149 		duk__emit_jump(comp_ctx, pc_l1);  /* jump to next loop, using reg_v34_iter as iterated value */
71150 
71151 		pc_l5 = duk__get_current_pc(comp_ctx);
71152 
71153 		/* XXX: since the enumerator may be a memory expensive object,
71154 		 * perhaps clear it explicitly here?  If so, break jump must
71155 		 * go through this clearing operation.
71156 		 */
71157 
71158 		DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l2: %ld->%ld, jumpto_l3: %ld->%ld, "
71159 		                     "jumpto_l4: %ld->%ld, jumpto_l5: %ld->%ld, "
71160 		                     "break: %ld->%ld, continue: %ld->%ld",
71161 			             (long) pc_jumpto_l2, (long) pc_l2, (long) pc_jumpto_l3, (long) pc_l3,
71162 			             (long) pc_jumpto_l4, (long) pc_l4, (long) pc_jumpto_l5, (long) pc_l5,
71163 		                     (long) (pc_label_site + 1), (long) pc_l5, (long) (pc_label_site + 2), (long) pc_l4));
71164 
71165 		duk__patch_jump(comp_ctx, pc_jumpto_l2, pc_l2);
71166 		duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
71167 		duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
71168 		duk__patch_jump(comp_ctx, pc_jumpto_l5, pc_l5);
71169 		duk__patch_jump(comp_ctx, pc_label_site + 1, pc_l5);  /* break jump */
71170 		duk__patch_jump(comp_ctx, pc_label_site + 2, pc_l4);  /* continue jump */
71171 	}
71172 	goto finished;
71173 
71174  finished:
71175 	DUK_DDD(DUK_DDDPRINT("end parsing a for/for-in statement"));
71176 	return;
71177 
71178  syntax_error:
71179 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FOR);
71180 	DUK_WO_NORETURN(return;);
71181 }
71182 
71183 DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
71184 	duk_hthread *thr = comp_ctx->thr;
71185 	duk_regconst_t temp_at_loop;
71186 	duk_regconst_t rc_switch;    /* reg/const for switch value */
71187 	duk_regconst_t rc_case;      /* reg/const for case value */
71188 	duk_regconst_t reg_temp;     /* general temp register */
71189 	duk_int_t pc_prevcase = -1;
71190 	duk_int_t pc_prevstmt = -1;
71191 	duk_int_t pc_default = -1;   /* -1 == not set, -2 == pending (next statement list) */
71192 
71193 	/* Note: negative pc values are ignored when patching jumps, so no explicit checks needed */
71194 
71195 	/*
71196 	 *  Switch is pretty complicated because of several conflicting concerns:
71197 	 *
71198 	 *    - Want to generate code without an intermediate representation,
71199 	 *      i.e., in one go
71200 	 *
71201 	 *    - Case selectors are expressions, not values, and may thus e.g. throw
71202 	 *      exceptions (which causes evaluation order concerns)
71203 	 *
71204 	 *    - Evaluation semantics of case selectors and default clause need to be
71205 	 *      carefully implemented to provide correct behavior even with case value
71206 	 *      side effects
71207 	 *
71208 	 *    - Fall through case and default clauses; avoiding dead JUMPs if case
71209 	 *      ends with an unconditional jump (a break or a continue)
71210 	 *
71211 	 *    - The same case value may occur multiple times, but evaluation rules
71212 	 *      only process the first match before switching to a "propagation" mode
71213 	 *      where case values are no longer evaluated
71214 	 *
71215 	 *  See E5 Section 12.11.  Also see doc/compiler.rst for compilation
71216 	 *  discussion.
71217 	 */
71218 
71219 	duk__advance(comp_ctx);
71220 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
71221 	rc_switch = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
71222 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* RegExp mode does not matter. */
71223 	duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
71224 
71225 	DUK_DDD(DUK_DDDPRINT("switch value in register %ld", (long) rc_switch));
71226 
71227 	temp_at_loop = DUK__GETTEMP(comp_ctx);
71228 
71229 	for (;;) {
71230 		duk_int_t num_stmts;
71231 		duk_small_uint_t tok;
71232 
71233 		/* sufficient for keeping temp reg numbers in check */
71234 		DUK__SETTEMP(comp_ctx, temp_at_loop);
71235 
71236 		if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
71237 			break;
71238 		}
71239 
71240 		/*
71241 		 *  Parse a case or default clause.
71242 		 */
71243 
71244 		if (comp_ctx->curr_token.t == DUK_TOK_CASE) {
71245 			/*
71246 			 *  Case clause.
71247 			 *
71248 			 *  Note: cannot use reg_case as a temp register (for SEQ target)
71249 			 *  because it may be a constant.
71250 			 */
71251 
71252 			duk__patch_jump_here(comp_ctx, pc_prevcase);  /* chain jumps for case
71253 			                                               * evaluation and checking
71254 			                                               */
71255 
71256 			duk__advance(comp_ctx);
71257 			rc_case = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
71258 			duk__advance_expect(comp_ctx, DUK_TOK_COLON);
71259 
71260 			reg_temp = DUK__ALLOCTEMP(comp_ctx);
71261 			duk__emit_a_b_c(comp_ctx,
71262 			                DUK_OP_SEQ | DUK__EMIT_FLAG_BC_REGCONST,
71263 			                reg_temp,
71264 			                rc_switch,
71265 			                rc_case);
71266 			duk__emit_if_true_skip(comp_ctx, reg_temp);
71267 
71268 			/* jump to next case clause */
71269 			pc_prevcase = duk__emit_jump_empty(comp_ctx);  /* no match, next case */
71270 
71271 			/* statements go here (if any) on next loop */
71272 		} else if (comp_ctx->curr_token.t == DUK_TOK_DEFAULT) {
71273 			/*
71274 			 *  Default clause.
71275 			 */
71276 
71277 			if (pc_default >= 0) {
71278 				goto syntax_error;
71279 			}
71280 			duk__advance(comp_ctx);
71281 			duk__advance_expect(comp_ctx, DUK_TOK_COLON);
71282 
71283 			/* Fix for https://github.com/svaarala/duktape/issues/155:
71284 			 * If 'default' is first clause (detected by pc_prevcase < 0)
71285 			 * we need to ensure we stay in the matching chain.
71286 			 */
71287 			if (pc_prevcase < 0) {
71288 				DUK_DD(DUK_DDPRINT("default clause is first, emit prevcase jump"));
71289 				pc_prevcase = duk__emit_jump_empty(comp_ctx);
71290 			}
71291 
71292 			/* default clause matches next statement list (if any) */
71293 			pc_default = -2;
71294 		} else {
71295 			/* Code is not accepted before the first case/default clause */
71296 			goto syntax_error;
71297 		}
71298 
71299 		/*
71300 		 *  Parse code after the clause.  Possible terminators are
71301 		 *  'case', 'default', and '}'.
71302 		 *
71303 		 *  Note that there may be no code at all, not even an empty statement,
71304 		 *  between case clauses.  This must be handled just like an empty statement
71305 		 *  (omitting seemingly pointless JUMPs), to avoid situations like
71306 		 *  test-bug-case-fallthrough.js.
71307 		 */
71308 
71309 		num_stmts = 0;
71310 		if (pc_default == -2) {
71311 			pc_default = duk__get_current_pc(comp_ctx);
71312 		}
71313 
71314 		/* Note: this is correct even for default clause statements:
71315 		 * they participate in 'fall-through' behavior even if the
71316 		 * default clause is in the middle.
71317 		 */
71318 		duk__patch_jump_here(comp_ctx, pc_prevstmt);  /* chain jumps for 'fall-through'
71319 		                                               * after a case matches.
71320 		                                               */
71321 
71322 		for (;;) {
71323 			tok = comp_ctx->curr_token.t;
71324 			if (tok == DUK_TOK_CASE || tok == DUK_TOK_DEFAULT ||
71325 			    tok == DUK_TOK_RCURLY) {
71326 				break;
71327 			}
71328 			num_stmts++;
71329 			duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
71330 		}
71331 
71332 		/* fall-through jump to next code of next case (backpatched) */
71333 		pc_prevstmt = duk__emit_jump_empty(comp_ctx);
71334 
71335 		/* XXX: would be nice to omit this jump when the jump is not
71336 		 * reachable, at least in the obvious cases (such as the case
71337 		 * ending with a 'break'.
71338 		 *
71339 		 * Perhaps duk__parse_stmt() could provide some info on whether
71340 		 * the statement is a "dead end"?
71341 		 *
71342 		 * If implemented, just set pc_prevstmt to -1 when not needed.
71343 		 */
71344 	}
71345 
71346 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
71347 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
71348 	duk__advance(comp_ctx);  /* Allow RegExp as part of next stmt. */
71349 
71350 	/* default case control flow patchup; note that if pc_prevcase < 0
71351 	 * (i.e. no case clauses), control enters default case automatically.
71352 	 */
71353 	if (pc_default >= 0) {
71354 		/* default case exists: go there if no case matches */
71355 		duk__patch_jump(comp_ctx, pc_prevcase, pc_default);
71356 	} else {
71357 		/* default case does not exist, or no statements present
71358 		 * after default case: finish case evaluation
71359 		 */
71360 		duk__patch_jump_here(comp_ctx, pc_prevcase);
71361 	}
71362 
71363 	/* fall-through control flow patchup; note that pc_prevstmt may be
71364 	 * < 0 (i.e. no case clauses), in which case this is a no-op.
71365 	 */
71366 	duk__patch_jump_here(comp_ctx, pc_prevstmt);
71367 
71368 	/* continue jump not patched, an INVALID opcode remains there */
71369 	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */
71370 
71371 	/* Note: 'fast' breaks will jump to pc_label_site + 1, which will
71372 	 * then jump here.  The double jump will be eliminated by a
71373 	 * peephole pass, resulting in an optimal jump here.  The label
71374 	 * site jumps will remain in bytecode and will waste code size.
71375 	 */
71376 
71377 	return;
71378 
71379  syntax_error:
71380 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_SWITCH);
71381 	DUK_WO_NORETURN(return;);
71382 }
71383 
71384 DUK_LOCAL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
71385 	duk_regconst_t temp_reset;
71386 	duk_regconst_t rc_cond;
71387 	duk_int_t pc_jump_false;
71388 
71389 	DUK_DDD(DUK_DDDPRINT("begin parsing if statement"));
71390 
71391 	temp_reset = DUK__GETTEMP(comp_ctx);
71392 
71393 	duk__advance(comp_ctx);  /* eat 'if' */
71394 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
71395 
71396 	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
71397 	duk__emit_if_true_skip(comp_ctx, rc_cond);
71398 	pc_jump_false = duk__emit_jump_empty(comp_ctx);  /* jump to end or else part */
71399 	DUK__SETTEMP(comp_ctx, temp_reset);
71400 
71401 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
71402 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
71403 
71404 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
71405 
71406 	/* The 'else' ambiguity is resolved by 'else' binding to the innermost
71407 	 * construct, so greedy matching is correct here.
71408 	 */
71409 
71410 	if (comp_ctx->curr_token.t == DUK_TOK_ELSE) {
71411 		duk_int_t pc_jump_end;
71412 
71413 		DUK_DDD(DUK_DDDPRINT("if has else part"));
71414 
71415 		duk__advance(comp_ctx);
71416 
71417 		pc_jump_end = duk__emit_jump_empty(comp_ctx);  /* jump from true part to end */
71418 		duk__patch_jump_here(comp_ctx, pc_jump_false);
71419 
71420 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
71421 
71422 		duk__patch_jump_here(comp_ctx, pc_jump_end);
71423 	} else {
71424 		DUK_DDD(DUK_DDDPRINT("if does not have else part"));
71425 
71426 		duk__patch_jump_here(comp_ctx, pc_jump_false);
71427 	}
71428 
71429 	DUK_DDD(DUK_DDDPRINT("end parsing if statement"));
71430 }
71431 
71432 DUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
71433 	duk_regconst_t rc_cond;
71434 	duk_int_t pc_start;
71435 
71436 	DUK_DDD(DUK_DDDPRINT("begin parsing do statement"));
71437 
71438 	duk__advance(comp_ctx);  /* Eat 'do'; allow RegExp as part of next stmt. */
71439 
71440 	pc_start = duk__get_current_pc(comp_ctx);
71441 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
71442 	duk__patch_jump_here(comp_ctx, pc_label_site + 2);  /* continue jump */
71443 
71444 	duk__advance_expect(comp_ctx, DUK_TOK_WHILE);
71445 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
71446 
71447 	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
71448 	duk__emit_if_false_skip(comp_ctx, rc_cond);
71449 	duk__emit_jump(comp_ctx, pc_start);
71450 	/* no need to reset temps, as we're finished emitting code */
71451 
71452 	comp_ctx->curr_func.allow_regexp_in_adv = 1;  /* Allow RegExp as part of next stmt. */
71453 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
71454 
71455 	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */
71456 
71457 	DUK_DDD(DUK_DDDPRINT("end parsing do statement"));
71458 }
71459 
71460 DUK_LOCAL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
71461 	duk_regconst_t temp_reset;
71462 	duk_regconst_t rc_cond;
71463 	duk_int_t pc_start;
71464 	duk_int_t pc_jump_false;
71465 
71466 	DUK_DDD(DUK_DDDPRINT("begin parsing while statement"));
71467 
71468 	temp_reset = DUK__GETTEMP(comp_ctx);
71469 
71470 	duk__advance(comp_ctx);  /* eat 'while' */
71471 
71472 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
71473 
71474 	pc_start = duk__get_current_pc(comp_ctx);
71475 	duk__patch_jump_here(comp_ctx, pc_label_site + 2);  /* continue jump */
71476 
71477 	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
71478 	duk__emit_if_true_skip(comp_ctx, rc_cond);
71479 	pc_jump_false = duk__emit_jump_empty(comp_ctx);
71480 	DUK__SETTEMP(comp_ctx, temp_reset);
71481 
71482 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
71483 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
71484 
71485 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
71486 	duk__emit_jump(comp_ctx, pc_start);
71487 
71488 	duk__patch_jump_here(comp_ctx, pc_jump_false);
71489 	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */
71490 
71491 	DUK_DDD(DUK_DDDPRINT("end parsing while statement"));
71492 }
71493 
71494 DUK_LOCAL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
71495 	duk_hthread *thr = comp_ctx->thr;
71496 	duk_bool_t is_break = (comp_ctx->curr_token.t == DUK_TOK_BREAK);
71497 	duk_int_t label_id;
71498 	duk_int_t label_catch_depth;
71499 	duk_int_t label_pc;  /* points to LABEL; pc+1 = jump site for break; pc+2 = jump site for continue */
71500 	duk_bool_t label_is_closest;
71501 
71502 	DUK_UNREF(res);
71503 
71504 	duk__advance(comp_ctx);  /* eat 'break' or 'continue' */
71505 
71506 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON ||  /* explicit semi follows */
71507 	    comp_ctx->curr_token.lineterm ||                /* automatic semi will be inserted */
71508 	    comp_ctx->curr_token.allow_auto_semi) {         /* automatic semi will be inserted */
71509 		/* break/continue without label */
71510 
71511 		duk__lookup_active_label(comp_ctx, DUK_HTHREAD_STRING_EMPTY_STRING(thr), is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
71512 	} else if (comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER) {
71513 		/* break/continue with label (label cannot be a reserved word, production is 'Identifier' */
71514 		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
71515 		duk__lookup_active_label(comp_ctx, comp_ctx->curr_token.str1, is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
71516 		duk__advance(comp_ctx);
71517 	} else {
71518 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BREAK_CONT_LABEL);
71519 		DUK_WO_NORETURN(return;);
71520 	}
71521 
71522 	/* Use a fast break/continue when possible.  A fast break/continue is
71523 	 * just a jump to the LABEL break/continue jump slot, which then jumps
71524 	 * to an appropriate place (for break, going through ENDLABEL correctly).
71525 	 * The peephole optimizer will optimize the jump to a direct one.
71526 	 */
71527 
71528 	if (label_catch_depth == comp_ctx->curr_func.catch_depth &&
71529 	    label_is_closest) {
71530 		DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
71531 		                     "label_catch_depth=%ld, catch_depth=%ld "
71532 		                     "-> use fast variant (direct jump)",
71533 		                     (long) is_break, (long) label_id, (long) label_is_closest,
71534 		                     (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
71535 
71536 		duk__emit_jump(comp_ctx, label_pc + (is_break ? 1 : 2));
71537 	} else {
71538 		DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
71539 		                     "label_catch_depth=%ld, catch_depth=%ld "
71540 		                     "-> use slow variant (longjmp)",
71541 		                     (long) is_break, (long) label_id, (long) label_is_closest,
71542 		                     (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
71543 
71544 		duk__emit_bc(comp_ctx,
71545 		             is_break ? DUK_OP_BREAK : DUK_OP_CONTINUE,
71546 		             (duk_regconst_t) label_id);
71547 	}
71548 }
71549 
71550 DUK_LOCAL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
71551 	duk_hthread *thr = comp_ctx->thr;
71552 	duk_regconst_t rc_val;
71553 
71554 	duk__advance(comp_ctx);  /* eat 'return' */
71555 
71556 	/* A 'return' statement is only allowed inside an actual function body,
71557 	 * not as part of eval or global code.
71558 	 */
71559 	if (!comp_ctx->curr_func.is_function) {
71560 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_RETURN);
71561 		DUK_WO_NORETURN(return;);
71562 	}
71563 
71564 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON ||  /* explicit semi follows */
71565 	    comp_ctx->curr_token.lineterm ||                /* automatic semi will be inserted */
71566 	    comp_ctx->curr_token.allow_auto_semi) {         /* automatic semi will be inserted */
71567 		DUK_DDD(DUK_DDDPRINT("empty return value -> undefined"));
71568 		duk__emit_op_only(comp_ctx, DUK_OP_RETUNDEF);
71569 	} else {
71570 		duk_int_t pc_before_expr;
71571 		duk_int_t pc_after_expr;
71572 
71573 		DUK_DDD(DUK_DDDPRINT("return with a value"));
71574 
71575 		DUK_UNREF(pc_before_expr);
71576 		DUK_UNREF(pc_after_expr);
71577 
71578 		pc_before_expr = duk__get_current_pc(comp_ctx);
71579 		rc_val = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
71580 		pc_after_expr = duk__get_current_pc(comp_ctx);
71581 
71582 		/* Tail call check: if last opcode emitted was CALL, and
71583 		 * the context allows it, add a tailcall flag to the CALL.
71584 		 * This doesn't guarantee that a tail call will be allowed at
71585 		 * runtime, so the RETURN must still be emitted.  (Duktape
71586 		 * 0.10.0 avoided this and simulated a RETURN if a tail call
71587 		 * couldn't be used at runtime; but this didn't work
71588 		 * correctly with a thread yield/resume, see
71589 		 * test-bug-tailcall-thread-yield-resume.js for discussion.)
71590 		 *
71591 		 * In addition to the last opcode being CALL, we also need to
71592 		 * be sure that 'rc_val' is the result register of the CALL.
71593 		 * For instance, for the expression 'return 0, (function ()
71594 		 * { return 1; }), 2' the last opcode emitted is CALL (no
71595 		 * bytecode is emitted for '2') but 'rc_val' indicates
71596 		 * constant '2'.  Similarly if '2' is replaced by a register
71597 		 * bound variable, no opcodes are emitted but tail call would
71598 		 * be incorrect.
71599 		 *
71600 		 * This is tricky and easy to get wrong.  It would be best to
71601 		 * track enough expression metadata to check that 'rc_val' came
71602 		 * from that last CALL instruction.  We don't have that metadata
71603 		 * now, so we check that 'rc_val' is a temporary register result
71604 		 * (not a constant or a register bound variable).  There should
71605 		 * be no way currently for 'rc_val' to be a temporary for an
71606 		 * expression following the CALL instruction without emitting
71607 		 * some opcodes following the CALL.  This proxy check is used
71608 		 * below.
71609 		 *
71610 		 * See: test-bug-comma-expr-gh131.js.
71611 		 *
71612 		 * The non-standard 'caller' property disables tail calls
71613 		 * because they pose some special cases which haven't been
71614 		 * fixed yet.
71615 		 */
71616 
71617 #if defined(DUK_USE_TAILCALL)
71618 		if (comp_ctx->curr_func.catch_depth == 0 &&   /* no catchers */
71619 		    pc_after_expr > pc_before_expr) {         /* at least one opcode emitted */
71620 			duk_compiler_instr *instr;
71621 			duk_instr_t ins;
71622 			duk_small_uint_t op;
71623 
71624 			instr = duk__get_instr_ptr(comp_ctx, pc_after_expr - 1);
71625 			DUK_ASSERT(instr != NULL);
71626 
71627 			ins = instr->ins;
71628 			op = (duk_small_uint_t) DUK_DEC_OP(ins);
71629 			if ((op & ~0x0fU) == DUK_OP_CALL0 &&
71630 			    DUK__ISREG_TEMP(comp_ctx, rc_val) /* see above */) {
71631 				DUK_DDD(DUK_DDDPRINT("return statement detected a tail call opportunity: "
71632 				                     "catch depth is 0, duk__exprtop() emitted >= 1 instructions, "
71633 				                     "and last instruction is a CALL "
71634 				                     "-> change to TAILCALL"));
71635 				ins |= DUK_ENC_OP(DUK_BC_CALL_FLAG_TAILCALL);
71636 				instr->ins = ins;
71637 			}
71638 		}
71639 #endif  /* DUK_USE_TAILCALL */
71640 
71641 		if (DUK__ISREG(rc_val)) {
71642 			duk__emit_bc(comp_ctx, DUK_OP_RETREG, rc_val);
71643 		} else {
71644 			rc_val = DUK__REMOVECONST(rc_val);
71645 			if (duk__const_needs_refcount(comp_ctx, rc_val)) {
71646 				duk__emit_bc(comp_ctx, DUK_OP_RETCONST, rc_val);
71647 			} else {
71648 				duk__emit_bc(comp_ctx, DUK_OP_RETCONSTN, rc_val);
71649 			}
71650 		}
71651 	}
71652 }
71653 
71654 DUK_LOCAL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
71655 	duk_regconst_t reg_val;
71656 
71657 	duk__advance(comp_ctx);  /* eat 'throw' */
71658 
71659 	/* Unlike break/continue, throw statement does not allow an empty value. */
71660 
71661 	if (comp_ctx->curr_token.lineterm) {
71662 		DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_INVALID_THROW);
71663 		DUK_WO_NORETURN(return;);
71664 	}
71665 
71666 	reg_val = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
71667 	duk__emit_bc(comp_ctx,
71668 	             DUK_OP_THROW,
71669 	             reg_val);
71670 }
71671 
71672 DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
71673 	duk_hthread *thr = comp_ctx->thr;
71674 	duk_regconst_t reg_catch;      /* reg_catch+0 and reg_catch+1 are reserved for TRYCATCH */
71675 	duk_regconst_t rc_varname = 0;
71676 	duk_small_uint_t trycatch_flags = 0;
71677 	duk_int_t pc_ldconst = -1;
71678 	duk_int_t pc_trycatch = -1;
71679 	duk_int_t pc_catch = -1;
71680 	duk_int_t pc_finally = -1;
71681 
71682 	DUK_UNREF(res);
71683 
71684 	/*
71685 	 *  See the following documentation for discussion:
71686 	 *
71687 	 *    doc/execution.rst: control flow details
71688 	 *
71689 	 *  Try, catch, and finally "parts" are Blocks, not Statements, so
71690 	 *  they must always be delimited by curly braces.  This is unlike e.g.
71691 	 *  the if statement, which accepts any Statement.  This eliminates any
71692 	 *  questions of matching parts of nested try statements.  The Block
71693 	 *  parsing is implemented inline here (instead of calling out).
71694 	 *
71695 	 *  Finally part has a 'let scoped' variable, which requires a few kinks
71696 	 *  here.
71697 	 */
71698 
71699 	comp_ctx->curr_func.catch_depth++;
71700 
71701 	duk__advance(comp_ctx);  /* eat 'try' */
71702 
71703 	reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
71704 
71705 	/* The target for this LDCONST may need output shuffling, but we assume
71706 	 * that 'pc_ldconst' will be the LDCONST that we can patch later.  This
71707 	 * should be the case because there's no input shuffling.  (If there's
71708 	 * no catch clause, this LDCONST will be replaced with a NOP.)
71709 	 */
71710 	pc_ldconst = duk__get_current_pc(comp_ctx);
71711 	duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, reg_catch, 0 /*patched later*/);
71712 
71713 	pc_trycatch = duk__get_current_pc(comp_ctx);
71714 	duk__emit_invalid(comp_ctx);  /* TRYCATCH, cannot emit now (not enough info) */
71715 	duk__emit_invalid(comp_ctx);  /* jump for 'catch' case */
71716 	duk__emit_invalid(comp_ctx);  /* jump for 'finally' case or end (if no finally) */
71717 
71718 	/* try part */
71719 	duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
71720 	duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
71721 	/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
71722 	duk__emit_op_only(comp_ctx, DUK_OP_ENDTRY);
71723 
71724 	if (comp_ctx->curr_token.t == DUK_TOK_CATCH) {
71725 		/*
71726 		 *  The catch variable must be updated to reflect the new allocated
71727 		 *  register for the duration of the catch clause.  We need to store
71728 		 *  and restore the original value for the varmap entry (if any).
71729 		 */
71730 
71731 		/*
71732 		 *  Note: currently register bindings must be fixed for the entire
71733 		 *  function.  So, even though the catch variable is in a register
71734 		 *  we know, we must use an explicit environment record and slow path
71735 		 *  accesses to read/write the catch binding to make closures created
71736 		 *  within the catch clause work correctly.  This restriction should
71737 		 *  be fixable (at least in common cases) later.
71738 		 *
71739 		 *  See: test-bug-catch-binding-2.js.
71740 		 *
71741 		 *  XXX: improve to get fast path access to most catch clauses.
71742 		 */
71743 
71744 		duk_hstring *h_var;
71745 		duk_int_t varmap_value;  /* for storing/restoring the varmap binding for catch variable */
71746 
71747 		DUK_DDD(DUK_DDDPRINT("stack top at start of catch clause: %ld", (long) duk_get_top(thr)));
71748 
71749 		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_CATCH;
71750 
71751 		pc_catch = duk__get_current_pc(comp_ctx);
71752 
71753 		duk__advance(comp_ctx);
71754 		duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
71755 
71756 		if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
71757 			/* Identifier, i.e. don't allow reserved words */
71758 			goto syntax_error;
71759 		}
71760 		h_var = comp_ctx->curr_token.str1;
71761 		DUK_ASSERT(h_var != NULL);
71762 
71763 		duk_push_hstring(thr, h_var);  /* keep in on valstack, use borrowed ref below */
71764 
71765 		if (comp_ctx->curr_func.is_strict &&
71766 		    ((h_var == DUK_HTHREAD_STRING_EVAL(thr)) ||
71767 		     (h_var == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)))) {
71768 			DUK_DDD(DUK_DDDPRINT("catch identifier 'eval' or 'arguments' in strict mode -> SyntaxError"));
71769 			goto syntax_error;
71770 		}
71771 
71772 		duk_dup_top(thr);
71773 		rc_varname = duk__getconst(comp_ctx);
71774 		DUK_DDD(DUK_DDDPRINT("catch clause, rc_varname=0x%08lx (%ld)",
71775 		                     (unsigned long) rc_varname, (long) rc_varname));
71776 
71777 		duk__advance(comp_ctx);
71778 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
71779 
71780 		duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
71781 
71782 		DUK_DDD(DUK_DDDPRINT("varmap before modifying for catch clause: %!iT",
71783 		                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
71784 
71785 		duk_dup_top(thr);
71786 		duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
71787 		if (duk_is_undefined(thr, -1)) {
71788 			varmap_value = -2;
71789 		} else if (duk_is_null(thr, -1)) {
71790 			varmap_value = -1;
71791 		} else {
71792 			DUK_ASSERT(duk_is_number(thr, -1));
71793 			varmap_value = duk_get_int(thr, -1);
71794 			DUK_ASSERT(varmap_value >= 0);
71795 		}
71796 		duk_pop(thr);
71797 
71798 #if 0
71799 		/* It'd be nice to do something like this - but it doesn't
71800 		 * work for closures created inside the catch clause.
71801 		 */
71802 		duk_dup_top(thr);
71803 		duk_push_int(thr, (duk_int_t) (reg_catch + 0));
71804 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
71805 #endif
71806 		duk_dup_top(thr);
71807 		duk_push_null(thr);
71808 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
71809 
71810 		duk__emit_a_bc(comp_ctx,
71811 		               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
71812 		               reg_catch + 0 /*value*/,
71813 		               rc_varname /*varname*/);
71814 
71815 		DUK_DDD(DUK_DDDPRINT("varmap before parsing catch clause: %!iT",
71816 		                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
71817 
71818 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
71819 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
71820 
71821 		if (varmap_value == -2) {
71822 			/* not present */
71823 			duk_del_prop(thr, comp_ctx->curr_func.varmap_idx);
71824 		} else {
71825 			if (varmap_value == -1) {
71826 				duk_push_null(thr);
71827 			} else {
71828 				DUK_ASSERT(varmap_value >= 0);
71829 				duk_push_int(thr, varmap_value);
71830 			}
71831 			duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
71832 		}
71833 		/* varname is popped by above code */
71834 
71835 		DUK_DDD(DUK_DDDPRINT("varmap after restore catch clause: %!iT",
71836 		                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
71837 
71838 		duk__emit_op_only(comp_ctx,
71839 		                  DUK_OP_ENDCATCH);
71840 
71841 		/*
71842 		 *  XXX: for now, indicate that an expensive catch binding
71843 		 *  declarative environment is always needed.  If we don't
71844 		 *  need it, we don't need the const_varname either.
71845 		 */
71846 
71847 		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_CATCH_BINDING;
71848 
71849 		DUK_DDD(DUK_DDDPRINT("stack top at end of catch clause: %ld", (long) duk_get_top(thr)));
71850 	}
71851 
71852 	if (comp_ctx->curr_token.t == DUK_TOK_FINALLY) {
71853 		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY;
71854 
71855 		pc_finally = duk__get_current_pc(comp_ctx);
71856 
71857 		duk__advance(comp_ctx);
71858 
71859 		duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
71860 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
71861 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
71862 		duk__emit_abc(comp_ctx,
71863 		              DUK_OP_ENDFIN,
71864 		              reg_catch);  /* rethrow */
71865 	}
71866 
71867 	if (!(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) &&
71868 	    !(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY)) {
71869 		/* must have catch and/or finally */
71870 		goto syntax_error;
71871 	}
71872 
71873 	/* If there's no catch block, rc_varname will be 0 and duk__patch_trycatch()
71874 	 * will replace the LDCONST with a NOP.  For any actual constant (including
71875 	 * constant 0) the DUK__CONST_MARKER flag will be set in rc_varname.
71876 	 */
71877 
71878 	duk__patch_trycatch(comp_ctx,
71879 	                    pc_ldconst,
71880 	                    pc_trycatch,
71881 	                    reg_catch,
71882 	                    rc_varname,
71883 	                    trycatch_flags);
71884 
71885 	if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
71886 		DUK_ASSERT(pc_catch >= 0);
71887 		duk__patch_jump(comp_ctx, pc_trycatch + 1, pc_catch);
71888 	}
71889 
71890 	if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
71891 		DUK_ASSERT(pc_finally >= 0);
71892 		duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finally);
71893 	} else {
71894 		/* without finally, the second jump slot is used to jump to end of stmt */
71895 		duk__patch_jump_here(comp_ctx, pc_trycatch + 2);
71896 	}
71897 
71898 	comp_ctx->curr_func.catch_depth--;
71899 	return;
71900 
71901  syntax_error:
71902 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_TRY);
71903 	DUK_WO_NORETURN(return;);
71904 }
71905 
71906 DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
71907 	duk_int_t pc_trycatch;
71908 	duk_int_t pc_finished;
71909 	duk_regconst_t reg_catch;
71910 	duk_small_uint_t trycatch_flags;
71911 
71912 	if (comp_ctx->curr_func.is_strict) {
71913 		DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_WITH_IN_STRICT_MODE);
71914 		DUK_WO_NORETURN(return;);
71915 	}
71916 
71917 	comp_ctx->curr_func.catch_depth++;
71918 
71919 	duk__advance(comp_ctx);  /* eat 'with' */
71920 
71921 	reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
71922 
71923 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
71924 	duk__exprtop_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/, reg_catch);
71925 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
71926 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
71927 
71928 	pc_trycatch = duk__get_current_pc(comp_ctx);
71929 	trycatch_flags = DUK_BC_TRYCATCH_FLAG_WITH_BINDING;
71930 	duk__emit_a_bc(comp_ctx,
71931 	                DUK_OP_TRYCATCH | DUK__EMIT_FLAG_NO_SHUFFLE_A,
71932 	                (duk_regconst_t) trycatch_flags /*a*/,
71933 	                reg_catch /*bc*/);
71934 	duk__emit_invalid(comp_ctx);  /* catch jump */
71935 	duk__emit_invalid(comp_ctx);  /* finished jump */
71936 
71937 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
71938 	duk__emit_op_only(comp_ctx, DUK_OP_ENDTRY);
71939 
71940 	pc_finished = duk__get_current_pc(comp_ctx);
71941 
71942 	duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finished);
71943 
71944 	comp_ctx->curr_func.catch_depth--;
71945 }
71946 
71947 DUK_LOCAL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id) {
71948 	/* if a site already exists, nop: max one label site per statement */
71949 	if (label_id >= 0) {
71950 		return label_id;
71951 	}
71952 
71953 	label_id = comp_ctx->curr_func.label_next++;
71954 	DUK_DDD(DUK_DDDPRINT("allocated new label id for label site: %ld", (long) label_id));
71955 
71956 	duk__emit_bc(comp_ctx,
71957 	             DUK_OP_LABEL,
71958 	             (duk_regconst_t) label_id);
71959 	duk__emit_invalid(comp_ctx);
71960 	duk__emit_invalid(comp_ctx);
71961 
71962 	return label_id;
71963 }
71964 
71965 /* Parse a single statement.
71966  *
71967  * Creates a label site (with an empty label) automatically for iteration
71968  * statements.  Also "peels off" any label statements for explicit labels.
71969  */
71970 DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem) {
71971 	duk_hthread *thr = comp_ctx->thr;
71972 	duk_bool_t dir_prol_at_entry;    /* directive prologue status at entry */
71973 	duk_regconst_t temp_at_entry;
71974 	duk_size_t labels_len_at_entry;
71975 	duk_int_t pc_at_entry;           /* assumed to also be PC of "LABEL" */
71976 	duk_int_t stmt_id;
71977 	duk_small_uint_t stmt_flags = 0;
71978 	duk_int_t label_id = -1;
71979 	duk_small_uint_t tok;
71980 	duk_bool_t test_func_decl;
71981 
71982 	DUK__RECURSION_INCREASE(comp_ctx, thr);
71983 
71984 	temp_at_entry = DUK__GETTEMP(comp_ctx);
71985 	pc_at_entry = duk__get_current_pc(comp_ctx);
71986 	labels_len_at_entry = duk_get_length(thr, comp_ctx->curr_func.labelnames_idx);
71987 	stmt_id = comp_ctx->curr_func.stmt_next++;
71988 	dir_prol_at_entry = comp_ctx->curr_func.in_directive_prologue;
71989 
71990 	DUK_UNREF(stmt_id);
71991 
71992 	DUK_DDD(DUK_DDDPRINT("parsing a statement, stmt_id=%ld, temp_at_entry=%ld, labels_len_at_entry=%ld, "
71993 	                     "is_strict=%ld, in_directive_prologue=%ld, catch_depth=%ld",
71994 	                     (long) stmt_id, (long) temp_at_entry, (long) labels_len_at_entry,
71995 	                     (long) comp_ctx->curr_func.is_strict, (long) comp_ctx->curr_func.in_directive_prologue,
71996 	                     (long) comp_ctx->curr_func.catch_depth));
71997 
71998 	/* The directive prologue flag is cleared by default so that it is
71999 	 * unset for any recursive statement parsing.  It is only "revived"
72000 	 * if a directive is detected.  (We could also make directives only
72001 	 * allowed if 'allow_source_elem' was true.)
72002 	 */
72003 	comp_ctx->curr_func.in_directive_prologue = 0;
72004 
72005  retry_parse:
72006 
72007 	DUK_DDD(DUK_DDDPRINT("try stmt parse, stmt_id=%ld, label_id=%ld, allow_source_elem=%ld, catch_depth=%ld",
72008 	                     (long) stmt_id, (long) label_id, (long) allow_source_elem,
72009 	                     (long) comp_ctx->curr_func.catch_depth));
72010 
72011 	/*
72012 	 *  Detect iteration statements; if encountered, establish an
72013 	 *  empty label.
72014 	 */
72015 
72016 	tok = comp_ctx->curr_token.t;
72017 	if (tok == DUK_TOK_FOR || tok == DUK_TOK_DO || tok == DUK_TOK_WHILE ||
72018 	    tok == DUK_TOK_SWITCH) {
72019 		DUK_DDD(DUK_DDDPRINT("iteration/switch statement -> add empty label"));
72020 
72021 		label_id = duk__stmt_label_site(comp_ctx, label_id);
72022 		duk__add_label(comp_ctx,
72023 		               DUK_HTHREAD_STRING_EMPTY_STRING(thr),
72024 		               pc_at_entry /*pc_label*/,
72025 		               label_id);
72026 	}
72027 
72028 	/*
72029 	 *  Main switch for statement / source element type.
72030 	 */
72031 
72032 	switch (comp_ctx->curr_token.t) {
72033 	case DUK_TOK_FUNCTION: {
72034 		/*
72035 		 *  Function declaration, function expression, or (non-standard)
72036 		 *  function statement.
72037 		 *
72038 		 *  The E5 specification only allows function declarations at
72039 		 *  the top level (in "source elements").  An ExpressionStatement
72040 		 *  is explicitly not allowed to begin with a "function" keyword
72041 		 *  (E5 Section 12.4).  Hence any non-error semantics for such
72042 		 *  non-top-level statements are non-standard.  Duktape semantics
72043 		 *  for function statements are modelled after V8, see
72044 		 *  test-dev-func-decl-outside-top.js.
72045 		 */
72046 		test_func_decl = allow_source_elem;
72047 #if defined(DUK_USE_NONSTD_FUNC_STMT)
72048 		/* Lenient: allow function declarations outside top level in
72049 		 * non-strict mode but reject them in strict mode.
72050 		 */
72051 		test_func_decl = test_func_decl || !comp_ctx->curr_func.is_strict;
72052 #endif  /* DUK_USE_NONSTD_FUNC_STMT */
72053 		/* Strict: never allow function declarations outside top level. */
72054 		if (test_func_decl) {
72055 			/* FunctionDeclaration: not strictly a statement but handled as such.
72056 			 *
72057 			 * O(depth^2) parse count for inner functions is handled by recording a
72058 			 * lexer offset on the first compilation pass, so that the function can
72059 			 * be efficiently skipped on the second pass.  This is encapsulated into
72060 			 * duk__parse_func_like_fnum().
72061 			 */
72062 
72063 			duk_int_t fnum;
72064 #if defined(DUK_USE_ASSERTIONS)
72065 			duk_idx_t top_before;
72066 #endif
72067 
72068 			DUK_DDD(DUK_DDDPRINT("function declaration statement"));
72069 
72070 #if defined(DUK_USE_ASSERTIONS)
72071 			top_before = duk_get_top(thr);
72072 #endif
72073 
72074 			duk__advance(comp_ctx);  /* eat 'function' */
72075 			fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_DECL | DUK__FUNC_FLAG_PUSHNAME_PASS1);
72076 
72077 			/* The value stack convention here is a bit odd: the function
72078 			 * name is only pushed on pass 1 (in_scanning), and is needed
72079 			 * to process function declarations.
72080 			 */
72081 			if (comp_ctx->curr_func.in_scanning) {
72082 				duk_uarridx_t n;
72083 
72084 #if defined(DUK_USE_ASSERTIONS)
72085 				DUK_ASSERT(duk_get_top(thr) == top_before + 1);
72086 #endif
72087 				DUK_DDD(DUK_DDDPRINT("register function declaration %!T in pass 1, fnum %ld",
72088 				                     duk_get_tval(thr, -1), (long) fnum));
72089 				n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
72090 				/* funcname is at index -1 */
72091 				duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n);
72092 				duk_push_int(thr, (duk_int_t) (DUK_DECL_TYPE_FUNC + (fnum << 8)));
72093 				duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n + 1);
72094 			} else {
72095 #if defined(DUK_USE_ASSERTIONS)
72096 				DUK_ASSERT(duk_get_top(thr) == top_before);
72097 #endif
72098 			}
72099 
72100 			/* no statement value (unlike function expression) */
72101 			stmt_flags = 0;
72102 			break;
72103 		} else {
72104 			DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_STMT_NOT_ALLOWED);
72105 			DUK_WO_NORETURN(return;);
72106 		}
72107 		break;
72108 	}
72109 	case DUK_TOK_LCURLY: {
72110 		DUK_DDD(DUK_DDDPRINT("block statement"));
72111 		duk__advance(comp_ctx);
72112 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
72113 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
72114 		if (label_id >= 0) {
72115 			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
72116 		}
72117 		stmt_flags = 0;
72118 		break;
72119 	}
72120 	case DUK_TOK_CONST: {
72121 		DUK_DDD(DUK_DDDPRINT("constant declaration statement"));
72122 		duk__parse_var_stmt(comp_ctx, res, DUK__EXPR_FLAG_REQUIRE_INIT /*expr_flags*/);
72123 		stmt_flags = DUK__HAS_TERM;
72124 		break;
72125 	}
72126 	case DUK_TOK_VAR: {
72127 		DUK_DDD(DUK_DDDPRINT("variable declaration statement"));
72128 		duk__parse_var_stmt(comp_ctx, res, 0 /*expr_flags*/);
72129 		stmt_flags = DUK__HAS_TERM;
72130 		break;
72131 	}
72132 	case DUK_TOK_SEMICOLON: {
72133 		/* empty statement with an explicit semicolon */
72134 		DUK_DDD(DUK_DDDPRINT("empty statement"));
72135 		stmt_flags = DUK__HAS_TERM;
72136 		break;
72137 	}
72138 	case DUK_TOK_IF: {
72139 		DUK_DDD(DUK_DDDPRINT("if statement"));
72140 		duk__parse_if_stmt(comp_ctx, res);
72141 		if (label_id >= 0) {
72142 			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
72143 		}
72144 		stmt_flags = 0;
72145 		break;
72146 	}
72147 	case DUK_TOK_DO: {
72148 		/*
72149 		 *  Do-while statement is mostly trivial, but there is special
72150 		 *  handling for automatic semicolon handling (triggered by the
72151 		 *  DUK__ALLOW_AUTO_SEMI_ALWAYS) flag related to a bug filed at:
72152 		 *
72153 		 *    https://bugs.ecmascript.org/show_bug.cgi?id=8
72154 		 *
72155 		 *  See doc/compiler.rst for details.
72156 		 */
72157 		DUK_DDD(DUK_DDDPRINT("do statement"));
72158 		DUK_ASSERT(label_id >= 0);
72159 		duk__update_label_flags(comp_ctx,
72160 		                        label_id,
72161 		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
72162 		duk__parse_do_stmt(comp_ctx, res, pc_at_entry);
72163 		stmt_flags = DUK__HAS_TERM | DUK__ALLOW_AUTO_SEMI_ALWAYS;  /* DUK__ALLOW_AUTO_SEMI_ALWAYS workaround */
72164 		break;
72165 	}
72166 	case DUK_TOK_WHILE: {
72167 		DUK_DDD(DUK_DDDPRINT("while statement"));
72168 		DUK_ASSERT(label_id >= 0);
72169 		duk__update_label_flags(comp_ctx,
72170 		                        label_id,
72171 		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
72172 		duk__parse_while_stmt(comp_ctx, res, pc_at_entry);
72173 		stmt_flags = 0;
72174 		break;
72175 	}
72176 	case DUK_TOK_FOR: {
72177 		/*
72178 		 *  For/for-in statement is complicated to parse because
72179 		 *  determining the statement type (three-part for vs. a
72180 		 *  for-in) requires potential backtracking.
72181 		 *
72182 		 *  See the helper for the messy stuff.
72183 		 */
72184 		DUK_DDD(DUK_DDDPRINT("for/for-in statement"));
72185 		DUK_ASSERT(label_id >= 0);
72186 		duk__update_label_flags(comp_ctx,
72187 		                        label_id,
72188 		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
72189 		duk__parse_for_stmt(comp_ctx, res, pc_at_entry);
72190 		stmt_flags = 0;
72191 		break;
72192 	}
72193 	case DUK_TOK_CONTINUE:
72194 	case DUK_TOK_BREAK: {
72195 		DUK_DDD(DUK_DDDPRINT("break/continue statement"));
72196 		duk__parse_break_or_continue_stmt(comp_ctx, res);
72197 		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
72198 		break;
72199 	}
72200 	case DUK_TOK_RETURN: {
72201 		DUK_DDD(DUK_DDDPRINT("return statement"));
72202 		duk__parse_return_stmt(comp_ctx, res);
72203 		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
72204 		break;
72205 	}
72206 	case DUK_TOK_WITH: {
72207 		DUK_DDD(DUK_DDDPRINT("with statement"));
72208 		comp_ctx->curr_func.with_depth++;
72209 		duk__parse_with_stmt(comp_ctx, res);
72210 		if (label_id >= 0) {
72211 			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
72212 		}
72213 		comp_ctx->curr_func.with_depth--;
72214 		stmt_flags = 0;
72215 		break;
72216 	}
72217 	case DUK_TOK_SWITCH: {
72218 		/*
72219 		 *  The switch statement is pretty messy to compile.
72220 		 *  See the helper for details.
72221 		 */
72222 		DUK_DDD(DUK_DDDPRINT("switch statement"));
72223 		DUK_ASSERT(label_id >= 0);
72224 		duk__update_label_flags(comp_ctx,
72225 		                        label_id,
72226 		                        DUK_LABEL_FLAG_ALLOW_BREAK);  /* don't allow continue */
72227 		duk__parse_switch_stmt(comp_ctx, res, pc_at_entry);
72228 		stmt_flags = 0;
72229 		break;
72230 	}
72231 	case DUK_TOK_THROW: {
72232 		DUK_DDD(DUK_DDDPRINT("throw statement"));
72233 		duk__parse_throw_stmt(comp_ctx, res);
72234 		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
72235 		break;
72236 	}
72237 	case DUK_TOK_TRY: {
72238 		DUK_DDD(DUK_DDDPRINT("try statement"));
72239 		duk__parse_try_stmt(comp_ctx, res);
72240 		stmt_flags = 0;
72241 		break;
72242 	}
72243 	case DUK_TOK_DEBUGGER: {
72244 		duk__advance(comp_ctx);
72245 #if defined(DUK_USE_DEBUGGER_SUPPORT)
72246 		DUK_DDD(DUK_DDDPRINT("debugger statement: debugging enabled, emit debugger opcode"));
72247 		duk__emit_op_only(comp_ctx, DUK_OP_DEBUGGER);
72248 #else
72249 		DUK_DDD(DUK_DDDPRINT("debugger statement: ignored"));
72250 #endif
72251 		stmt_flags = DUK__HAS_TERM;
72252 		break;
72253 	}
72254 	default: {
72255 		/*
72256 		 *  Else, must be one of:
72257 		 *    - ExpressionStatement, possibly a directive (String)
72258 		 *    - LabelledStatement (Identifier followed by ':')
72259 		 *
72260 		 *  Expressions beginning with 'function' keyword are covered by a case
72261 		 *  above (such expressions are not allowed in standard E5 anyway).
72262 		 *  Also expressions starting with '{' are interpreted as block
72263 		 *  statements.  See E5 Section 12.4.
72264 		 *
72265 		 *  Directive detection is tricky; see E5 Section 14.1 on directive
72266 		 *  prologue.  A directive is an expression statement with a single
72267 		 *  string literal and an explicit or automatic semicolon.  Escape
72268 		 *  characters are significant and no parens etc are allowed:
72269 		 *
72270 		 *    'use strict';          // valid 'use strict' directive
72271 		 *    'use\u0020strict';     // valid directive, not a 'use strict' directive
72272 		 *    ('use strict');        // not a valid directive
72273 		 *
72274 		 *  The expression is determined to consist of a single string literal
72275 		 *  based on duk__expr_nud() and duk__expr_led() call counts.  The string literal
72276 		 *  of a 'use strict' directive is determined to lack any escapes based
72277 		 *  num_escapes count from the lexer.  Note that other directives may be
72278 		 *  allowed to contain escapes, so a directive with escapes does not
72279 		 *  terminate a directive prologue.
72280 		 *
72281 		 *  We rely on the fact that the expression parser will not emit any
72282 		 *  code for a single token expression.  However, it will generate an
72283 		 *  intermediate value which we will then successfully ignore.
72284 		 *
72285 		 *  A similar approach is used for labels.
72286 		 */
72287 
72288 		duk_bool_t single_token;
72289 
72290 		DUK_DDD(DUK_DDDPRINT("expression statement"));
72291 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
72292 
72293 		single_token = (comp_ctx->curr_func.nud_count == 1 &&  /* one token */
72294 		                comp_ctx->curr_func.led_count == 0);   /* no operators */
72295 
72296 		if (single_token &&
72297 		    comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
72298 		    comp_ctx->curr_token.t == DUK_TOK_COLON) {
72299 			/*
72300 			 *  Detected label
72301 			 */
72302 
72303 			duk_hstring *h_lab;
72304 
72305 			/* expected ival */
72306 			DUK_ASSERT(res->t == DUK_IVAL_VAR);
72307 			DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
72308 			DUK_ASSERT(DUK_TVAL_IS_STRING(duk_get_tval(thr, res->x1.valstack_idx)));
72309 			h_lab = comp_ctx->prev_token.str1;
72310 			DUK_ASSERT(h_lab != NULL);
72311 
72312 			DUK_DDD(DUK_DDDPRINT("explicit label site for label '%!O'",
72313 			                     (duk_heaphdr *) h_lab));
72314 
72315 			duk__advance(comp_ctx);  /* eat colon */
72316 
72317 			label_id = duk__stmt_label_site(comp_ctx, label_id);
72318 
72319 			duk__add_label(comp_ctx,
72320 			               h_lab,
72321 			               pc_at_entry /*pc_label*/,
72322 			               label_id);
72323 
72324 			/* a statement following a label cannot be a source element
72325 			 * (a function declaration).
72326 			 */
72327 			allow_source_elem = 0;
72328 
72329 			DUK_DDD(DUK_DDDPRINT("label handled, retry statement parsing"));
72330 			goto retry_parse;
72331 		}
72332 
72333 		stmt_flags = 0;
72334 
72335 		if (dir_prol_at_entry &&                           /* still in prologue */
72336 		    single_token &&                                /* single string token */
72337 		    comp_ctx->prev_token.t == DUK_TOK_STRING) {
72338 			/*
72339 			 *  Detected a directive
72340 			 */
72341 			duk_hstring *h_dir;
72342 
72343 			/* expected ival */
72344 			DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
72345 			DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
72346 			DUK_ASSERT(DUK_TVAL_IS_STRING(duk_get_tval(thr, res->x1.valstack_idx)));
72347 			h_dir = comp_ctx->prev_token.str1;
72348 			DUK_ASSERT(h_dir != NULL);
72349 
72350 			DUK_DDD(DUK_DDDPRINT("potential directive: %!O", h_dir));
72351 
72352 			stmt_flags |= DUK__STILL_PROLOGUE;
72353 
72354 			/* Note: escaped characters differentiate directives */
72355 
72356 			if (comp_ctx->prev_token.num_escapes > 0) {
72357 				DUK_DDD(DUK_DDDPRINT("directive contains escapes: valid directive "
72358 				                     "but we ignore such directives"));
72359 			} else {
72360 				/*
72361 				 * The length comparisons are present to handle
72362 				 * strings like "use strict\u0000foo" as required.
72363 				 */
72364 
72365 				if (DUK_HSTRING_GET_BYTELEN(h_dir) == 10 &&
72366 				    DUK_STRCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use strict") == 0) {
72367 #if defined(DUK_USE_STRICT_DECL)
72368 					DUK_DDD(DUK_DDDPRINT("use strict directive detected: strict flag %ld -> %ld",
72369 					                     (long) comp_ctx->curr_func.is_strict, (long) 1));
72370 					comp_ctx->curr_func.is_strict = 1;
72371 #else
72372 					DUK_DDD(DUK_DDDPRINT("use strict detected but strict declarations disabled, ignoring"));
72373 #endif
72374 				} else if (DUK_HSTRING_GET_BYTELEN(h_dir) == 14 &&
72375 				           DUK_STRCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use duk notail") == 0) {
72376 					DUK_DDD(DUK_DDDPRINT("use duk notail directive detected: notail flag %ld -> %ld",
72377 					                     (long) comp_ctx->curr_func.is_notail, (long) 1));
72378 					comp_ctx->curr_func.is_notail = 1;
72379 				} else {
72380 					DUK_DD(DUK_DDPRINT("unknown directive: '%!O', ignoring but not terminating "
72381 					                   "directive prologue", (duk_hobject *) h_dir));
72382 				}
72383 			}
72384 		} else {
72385 			DUK_DDD(DUK_DDDPRINT("non-directive expression statement or no longer in prologue; "
72386 			                     "prologue terminated if still active"));
72387                 }
72388 
72389 		stmt_flags |= DUK__HAS_VAL | DUK__HAS_TERM;
72390 	}
72391 	}  /* end switch (tok) */
72392 
72393 	/*
72394 	 *  Statement value handling.
72395 	 *
72396 	 *  Global code and eval code has an implicit return value
72397 	 *  which comes from the last statement with a value
72398 	 *  (technically a non-"empty" continuation, which is
72399 	 *  different from an empty statement).
72400 	 *
72401 	 *  Since we don't know whether a later statement will
72402 	 *  override the value of the current statement, we need
72403 	 *  to coerce the statement value to a register allocated
72404 	 *  for implicit return values.  In other cases we need
72405 	 *  to coerce the statement value to a plain value to get
72406 	 *  any side effects out (consider e.g. "foo.bar;").
72407 	 */
72408 
72409 	/* XXX: what about statements which leave a half-cooked value in 'res'
72410 	 * but have no stmt value?  Any such statements?
72411 	 */
72412 
72413 	if (stmt_flags & DUK__HAS_VAL) {
72414 		duk_regconst_t reg_stmt_value = comp_ctx->curr_func.reg_stmt_value;
72415 		if (reg_stmt_value >= 0) {
72416 			duk__ivalue_toforcedreg(comp_ctx, res, reg_stmt_value);
72417 		} else {
72418 			duk__ivalue_toplain_ignore(comp_ctx, res);
72419 		}
72420 	} else {
72421 		;
72422 	}
72423 
72424 	/*
72425 	 *  Statement terminator check, including automatic semicolon
72426 	 *  handling.  After this step, 'curr_tok' should be the first
72427 	 *  token after a possible statement terminator.
72428 	 */
72429 
72430 	if (stmt_flags & DUK__HAS_TERM) {
72431 		if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON) {
72432 			DUK_DDD(DUK_DDDPRINT("explicit semicolon terminates statement"));
72433 			duk__advance(comp_ctx);
72434 		} else {
72435 			if (comp_ctx->curr_token.allow_auto_semi) {
72436 				DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement"));
72437 			} else if (stmt_flags & DUK__ALLOW_AUTO_SEMI_ALWAYS) {
72438 				/* XXX: make this lenience dependent on flags or strictness? */
72439 				DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement (allowed for compatibility "
72440 				                     "even though no lineterm present before next token)"));
72441 			} else {
72442 				DUK_ERROR_SYNTAX(thr, DUK_STR_UNTERMINATED_STMT);
72443 				DUK_WO_NORETURN(return;);
72444 			}
72445 		}
72446 	} else {
72447 		DUK_DDD(DUK_DDDPRINT("statement has no terminator"));
72448 	}
72449 
72450 	/*
72451 	 *  Directive prologue tracking.
72452 	 */
72453 
72454 	if (stmt_flags & DUK__STILL_PROLOGUE) {
72455 		DUK_DDD(DUK_DDDPRINT("setting in_directive_prologue"));
72456 		comp_ctx->curr_func.in_directive_prologue = 1;
72457 	}
72458 
72459 	/*
72460 	 *  Cleanups (all statement parsing flows through here).
72461 	 *
72462 	 *  Pop label site and reset labels.  Reset 'next temp' to value at
72463 	 *  entry to reuse temps.
72464 	 */
72465 
72466 	if (label_id >= 0) {
72467 		duk__emit_bc(comp_ctx,
72468 		             DUK_OP_ENDLABEL,
72469 		             (duk_regconst_t) label_id);
72470 	}
72471 
72472 	DUK__SETTEMP(comp_ctx, temp_at_entry);
72473 
72474 	duk__reset_labels_to_length(comp_ctx, labels_len_at_entry);
72475 
72476 	/* XXX: return indication of "terminalness" (e.g. a 'throw' is terminal) */
72477 
72478 	DUK__RECURSION_DECREASE(comp_ctx, thr);
72479 }
72480 
72481 /*
72482  *  Parse a statement list.
72483  *
72484  *  Handles automatic semicolon insertion and implicit return value.
72485  *
72486  *  Upon entry, 'curr_tok' should contain the first token of the first
72487  *  statement (parsed in the "allow regexp literal" mode).  Upon exit,
72488  *  'curr_tok' contains the token following the statement list terminator
72489  *  (EOF or closing brace).
72490  */
72491 
72492 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) {
72493 	duk_hthread *thr = comp_ctx->thr;
72494 	duk_ivalue res_alloc;
72495 	duk_ivalue *res = &res_alloc;
72496 
72497 	/* Setup state.  Initial ivalue is 'undefined'. */
72498 
72499 	duk_require_stack(thr, DUK__PARSE_STATEMENTS_SLOTS);
72500 
72501 	/* XXX: 'res' setup can be moved to function body level; in fact, two 'res'
72502 	 * intermediate values suffice for parsing of each function.  Nesting is needed
72503 	 * for nested functions (which may occur inside expressions).
72504 	 */
72505 
72506 	duk_memzero(&res_alloc, sizeof(res_alloc));
72507 	res->t = DUK_IVAL_PLAIN;
72508 	res->x1.t = DUK_ISPEC_VALUE;
72509 	res->x1.valstack_idx = duk_get_top(thr);
72510 	res->x2.valstack_idx = res->x1.valstack_idx + 1;
72511 	duk_push_undefined(thr);
72512 	duk_push_undefined(thr);
72513 
72514 	/* Parse statements until a closing token (EOF or '}') is found. */
72515 
72516 	for (;;) {
72517 		/* Check whether statement list ends. */
72518 
72519 		if (expect_eof) {
72520 			if (comp_ctx->curr_token.t == DUK_TOK_EOF) {
72521 				break;
72522 			}
72523 		} else {
72524 			if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
72525 				break;
72526 			}
72527 		}
72528 
72529 		/* Check statement type based on the first token type.
72530 		 *
72531 		 * Note: expression parsing helpers expect 'curr_tok' to
72532 		 * contain the first token of the expression upon entry.
72533 		 */
72534 
72535 		DUK_DDD(DUK_DDDPRINT("TOKEN %ld (non-whitespace, non-comment)", (long) comp_ctx->curr_token.t));
72536 
72537 		duk__parse_stmt(comp_ctx, res, allow_source_elem);
72538 	}
72539 
72540 	/* RegExp is allowed / not allowed depending on context.  For function
72541 	 * declarations RegExp is allowed because it follows a function
72542 	 * declaration statement and may appear as part of the next statement.
72543 	 * For function expressions RegExp is not allowed, and it's possible
72544 	 * to do something like '(function () {} / 123)'.
72545 	 */
72546 	if (regexp_after) {
72547 		comp_ctx->curr_func.allow_regexp_in_adv = 1;
72548 	}
72549 	duk__advance(comp_ctx);
72550 
72551 	/* Tear down state. */
72552 
72553 	duk_pop_2(thr);
72554 }
72555 
72556 /*
72557  *  Declaration binding instantiation conceptually happens when calling a
72558  *  function; for us it essentially means that function prologue.  The
72559  *  conceptual process is described in E5 Section 10.5.
72560  *
72561  *  We need to keep track of all encountered identifiers to (1) create an
72562  *  identifier-to-register map ("varmap"); and (2) detect duplicate
72563  *  declarations.  Identifiers which are not bound to registers still need
72564  *  to be tracked for detecting duplicates.  Currently such identifiers
72565  *  are put into the varmap with a 'null' value, which is later cleaned up.
72566  *
72567  *  To support functions with a large number of variable and function
72568  *  declarations, registers are not allocated beyond a certain limit;
72569  *  after that limit, variables and functions need slow path access.
72570  *  Arguments are currently always register bound, which imposes a hard
72571  *  (and relatively small) argument count limit.
72572  *
72573  *  Some bindings in E5 are not configurable (= deletable) and almost all
72574  *  are mutable (writable).  Exceptions are:
72575  *
72576  *    - The 'arguments' binding, established only if no shadowing argument
72577  *      or function declaration exists.  We handle 'arguments' creation
72578  *      and binding through an explicit slow path environment record.
72579  *
72580  *    - The "name" binding for a named function expression.  This is also
72581  *      handled through an explicit slow path environment record.
72582  */
72583 
72584 /* XXX: add support for variables to not be register bound always, to
72585  * handle cases with a very large number of variables?
72586  */
72587 
72588 DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_stmt_value_reg) {
72589 	duk_hthread *thr = comp_ctx->thr;
72590 	duk_hstring *h_name;
72591 	duk_bool_t configurable_bindings;
72592 	duk_uarridx_t num_args;
72593 	duk_uarridx_t num_decls;
72594 	duk_regconst_t rc_name;
72595 	duk_small_uint_t declvar_flags;
72596 	duk_uarridx_t i;
72597 #if defined(DUK_USE_ASSERTIONS)
72598 	duk_idx_t entry_top;
72599 #endif
72600 
72601 #if defined(DUK_USE_ASSERTIONS)
72602 	entry_top = duk_get_top(thr);
72603 #endif
72604 
72605 	/*
72606 	 *  Preliminaries
72607 	 */
72608 
72609 	configurable_bindings = comp_ctx->curr_func.is_eval;
72610 	DUK_DDD(DUK_DDDPRINT("configurable_bindings=%ld", (long) configurable_bindings));
72611 
72612 	/* varmap is already in comp_ctx->curr_func.varmap_idx */
72613 
72614 	/*
72615 	 *  Function formal arguments, always bound to registers
72616 	 *  (there's no support for shuffling them now).
72617 	 */
72618 
72619 	num_args = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.argnames_idx);
72620 	DUK_DDD(DUK_DDDPRINT("num_args=%ld", (long) num_args));
72621 	/* XXX: check num_args */
72622 
72623 	for (i = 0; i < num_args; i++) {
72624 		duk_get_prop_index(thr, comp_ctx->curr_func.argnames_idx, i);
72625 		h_name = duk_known_hstring(thr, -1);
72626 
72627 		if (comp_ctx->curr_func.is_strict) {
72628 			if (duk__hstring_is_eval_or_arguments(comp_ctx, h_name)) {
72629 				DUK_DDD(DUK_DDDPRINT("arg named 'eval' or 'arguments' in strict mode -> SyntaxError"));
72630 				goto error_argname;
72631 			}
72632 			duk_dup_top(thr);
72633 			if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
72634 				DUK_DDD(DUK_DDDPRINT("duplicate arg name in strict mode -> SyntaxError"));
72635 				goto error_argname;
72636 			}
72637 
72638 			/* Ensure argument name is not a reserved word in current
72639 			 * (final) strictness.  Formal argument parsing may not
72640 			 * catch reserved names if strictness changes during
72641 			 * parsing.
72642 			 *
72643 			 * We only need to do this in strict mode because non-strict
72644 			 * keyword are always detected in formal argument parsing.
72645 			 */
72646 
72647 			if (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(h_name)) {
72648 				goto error_argname;
72649 			}
72650 		}
72651 
72652 		/* overwrite any previous binding of the same name; the effect is
72653 		 * that last argument of a certain name wins.
72654 		 */
72655 
72656 		/* only functions can have arguments */
72657 		DUK_ASSERT(comp_ctx->curr_func.is_function);
72658 		duk_push_uarridx(thr, i);  /* -> [ ... name index ] */
72659 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx); /* -> [ ... ] */
72660 
72661 		/* no code needs to be emitted, the regs already have values */
72662 	}
72663 
72664 	/* use temp_next for tracking register allocations */
72665 	DUK__SETTEMP_CHECKMAX(comp_ctx, (duk_regconst_t) num_args);
72666 
72667 	/*
72668 	 *  After arguments, allocate special registers (like shuffling temps)
72669 	 */
72670 
72671 	if (out_stmt_value_reg) {
72672 		*out_stmt_value_reg = DUK__ALLOCTEMP(comp_ctx);
72673 	}
72674 	if (comp_ctx->curr_func.needs_shuffle) {
72675 		duk_regconst_t shuffle_base = DUK__ALLOCTEMPS(comp_ctx, 3);
72676 		comp_ctx->curr_func.shuffle1 = shuffle_base;
72677 		comp_ctx->curr_func.shuffle2 = shuffle_base + 1;
72678 		comp_ctx->curr_func.shuffle3 = shuffle_base + 2;
72679 		DUK_D(DUK_DPRINT("shuffle registers needed by function, allocated: %ld %ld %ld",
72680 		                 (long) comp_ctx->curr_func.shuffle1,
72681 		                 (long) comp_ctx->curr_func.shuffle2,
72682 		                 (long) comp_ctx->curr_func.shuffle3));
72683 	}
72684 	if (comp_ctx->curr_func.temp_next > 0x100) {
72685 		DUK_D(DUK_DPRINT("not enough 8-bit regs: temp_next=%ld", (long) comp_ctx->curr_func.temp_next));
72686 		goto error_outofregs;
72687 	}
72688 
72689 	/*
72690 	 *  Function declarations
72691 	 */
72692 
72693 	num_decls = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
72694 	DUK_DDD(DUK_DDDPRINT("num_decls=%ld -> %!T",
72695 	                     (long) num_decls,
72696 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.decls_idx)));
72697 	for (i = 0; i < num_decls; i += 2) {
72698 		duk_int_t decl_type;
72699 		duk_int_t fnum;
72700 
72701 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1);  /* decl type */
72702 		decl_type = duk_to_int(thr, -1);
72703 		fnum = decl_type >> 8;  /* XXX: macros */
72704 		decl_type = decl_type & 0xff;
72705 		duk_pop(thr);
72706 
72707 		if (decl_type != DUK_DECL_TYPE_FUNC) {
72708 			continue;
72709 		}
72710 
72711 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */
72712 
72713 		/* XXX: spilling */
72714 		if (comp_ctx->curr_func.is_function) {
72715 			duk_regconst_t reg_bind;
72716 			duk_dup_top(thr);
72717 			if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
72718 				/* shadowed; update value */
72719 				duk_dup_top(thr);
72720 				duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
72721 				reg_bind = duk_to_int(thr, -1);  /* [ ... name reg_bind ] */
72722 				duk__emit_a_bc(comp_ctx,
72723 				               DUK_OP_CLOSURE,
72724 				               reg_bind,
72725 				               (duk_regconst_t) fnum);
72726 			} else {
72727 				/* function: always register bound */
72728 				reg_bind = DUK__ALLOCTEMP(comp_ctx);
72729 				duk__emit_a_bc(comp_ctx,
72730 				               DUK_OP_CLOSURE,
72731 				               reg_bind,
72732 				               (duk_regconst_t) fnum);
72733 				duk_push_int(thr, (duk_int_t) reg_bind);
72734 			}
72735 		} else {
72736 			/* Function declaration for global/eval code is emitted even
72737 			 * for duplicates, because of E5 Section 10.5, step 5.e of
72738 			 * E5.1 (special behavior for variable bound to global object).
72739 			 *
72740 			 * DECLVAR will not re-declare a variable as such, but will
72741 			 * update the binding value.
72742 			 */
72743 
72744 			duk_regconst_t reg_temp = DUK__ALLOCTEMP(comp_ctx);
72745 			duk_dup_top(thr);
72746 			rc_name = duk__getconst(comp_ctx);
72747 			duk_push_null(thr);
72748 
72749 			duk__emit_a_bc(comp_ctx,
72750 			               DUK_OP_CLOSURE,
72751 			               reg_temp,
72752 			               (duk_regconst_t) fnum);
72753 
72754 			declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
72755 			                DUK_PROPDESC_FLAG_ENUMERABLE |
72756 			                DUK_BC_DECLVAR_FLAG_FUNC_DECL;
72757 
72758 			if (configurable_bindings) {
72759 				declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
72760 			}
72761 
72762 			duk__emit_a_b_c(comp_ctx,
72763 			                DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_BC_REGCONST,
72764 			                (duk_regconst_t) declvar_flags /*flags*/,
72765 			                rc_name /*name*/,
72766 			                reg_temp /*value*/);
72767 
72768 			DUK__SETTEMP(comp_ctx, reg_temp);  /* forget temp */
72769 		}
72770 
72771 		DUK_DDD(DUK_DDDPRINT("function declaration to varmap: %!T -> %!T",
72772 		                     (duk_tval *) duk_get_tval(thr, -2),
72773 		                     (duk_tval *) duk_get_tval(thr, -1)));
72774 
72775 #if defined(DUK_USE_FASTINT)
72776 		DUK_ASSERT(DUK_TVAL_IS_NULL(duk_get_tval(thr, -1)) || DUK_TVAL_IS_FASTINT(duk_get_tval(thr, -1)));
72777 #endif
72778 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);  /* [ ... name reg/null ] -> [ ... ] */
72779 	}
72780 
72781 	/*
72782 	 *  'arguments' binding is special; if a shadowing argument or
72783 	 *  function declaration exists, an arguments object will
72784 	 *  definitely not be needed, regardless of whether the identifier
72785 	 *  'arguments' is referenced inside the function body.
72786 	 */
72787 
72788 	if (duk_has_prop_stridx(thr, comp_ctx->curr_func.varmap_idx, DUK_STRIDX_LC_ARGUMENTS)) {
72789 		DUK_DDD(DUK_DDDPRINT("'arguments' is shadowed by argument or function declaration "
72790 		                     "-> arguments object creation can be skipped"));
72791 		comp_ctx->curr_func.is_arguments_shadowed = 1;
72792 	}
72793 
72794 	/*
72795 	 *  Variable declarations.
72796 	 *
72797 	 *  Unlike function declarations, variable declaration values don't get
72798 	 *  assigned on entry.  If a binding of the same name already exists, just
72799 	 *  ignore it silently.
72800 	 */
72801 
72802 	for (i = 0; i < num_decls; i += 2) {
72803 		duk_int_t decl_type;
72804 
72805 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1);  /* decl type */
72806 		decl_type = duk_to_int(thr, -1);
72807 		decl_type = decl_type & 0xff;
72808 		duk_pop(thr);
72809 
72810 		if (decl_type != DUK_DECL_TYPE_VAR) {
72811 			continue;
72812 		}
72813 
72814 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */
72815 
72816 		if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
72817 			/* shadowed, ignore */
72818 		} else {
72819 			duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */
72820 			h_name = duk_known_hstring(thr, -1);
72821 
72822 			if (h_name == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) &&
72823 			    !comp_ctx->curr_func.is_arguments_shadowed) {
72824 				/* E5 Section steps 7-8 */
72825 				DUK_DDD(DUK_DDDPRINT("'arguments' not shadowed by a function declaration, "
72826 				                     "but appears as a variable declaration -> treat as "
72827 				                     "a no-op for variable declaration purposes"));
72828 				duk_pop(thr);
72829 				continue;
72830 			}
72831 
72832 			/* XXX: spilling */
72833 			if (comp_ctx->curr_func.is_function) {
72834 				duk_regconst_t reg_bind = DUK__ALLOCTEMP(comp_ctx);
72835 				/* no need to init reg, it will be undefined on entry */
72836 				duk_push_int(thr, (duk_int_t) reg_bind);
72837 			} else {
72838 				duk_dup_top(thr);
72839 				rc_name = duk__getconst(comp_ctx);
72840 				duk_push_null(thr);
72841 
72842 				declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
72843 			                        DUK_PROPDESC_FLAG_ENUMERABLE;
72844 				if (configurable_bindings) {
72845 					declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
72846 				}
72847 
72848 				duk__emit_a_b_c(comp_ctx,
72849 				                DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_BC_REGCONST,
72850 				                (duk_regconst_t) declvar_flags /*flags*/,
72851 				                rc_name /*name*/,
72852 				                0 /*value*/);
72853 			}
72854 
72855 			duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);  /* [ ... name reg/null ] -> [ ... ] */
72856 		}
72857 	}
72858 
72859 	/*
72860 	 *  Wrap up
72861 	 */
72862 
72863 	DUK_DDD(DUK_DDDPRINT("varmap: %!T, is_arguments_shadowed=%ld",
72864 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx),
72865 	                     (long) comp_ctx->curr_func.is_arguments_shadowed));
72866 
72867 	DUK_ASSERT_TOP(thr, entry_top);
72868 	return;
72869 
72870  error_outofregs:
72871 	DUK_ERROR_RANGE(thr, DUK_STR_REG_LIMIT);
72872 	DUK_WO_NORETURN(return;);
72873 
72874  error_argname:
72875 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARG_NAME);
72876 	DUK_WO_NORETURN(return;);
72877 }
72878 
72879 /*
72880  *  Parse a function-body-like expression (FunctionBody or Program
72881  *  in E5 grammar) using a two-pass parse.  The productions appear
72882  *  in the following contexts:
72883  *
72884  *    - function expression
72885  *    - function statement
72886  *    - function declaration
72887  *    - getter in object literal
72888  *    - setter in object literal
72889  *    - global code
72890  *    - eval code
72891  *    - Function constructor body
72892  *
72893  *  This function only parses the statement list of the body; the argument
72894  *  list and possible function name must be initialized by the caller.
72895  *  For instance, for Function constructor, the argument names are originally
72896  *  on the value stack.  The parsing of statements ends either at an EOF or
72897  *  a closing brace; this is controlled by an input flag.
72898  *
72899  *  Note that there are many differences affecting parsing and even code
72900  *  generation:
72901  *
72902  *    - Global and eval code have an implicit return value generated
72903  *      by the last statement; function code does not
72904  *
72905  *    - Global code, eval code, and Function constructor body end in
72906  *      an EOF, other bodies in a closing brace ('}')
72907  *
72908  *  Upon entry, 'curr_tok' is ignored and the function will pull in the
72909  *  first token on its own.  Upon exit, 'curr_tok' is the terminating
72910  *  token (EOF or closing brace).
72911  */
72912 
72913 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) {
72914 	duk_compiler_func *func;
72915 	duk_hthread *thr;
72916 	duk_regconst_t reg_stmt_value = -1;
72917 	duk_lexer_point lex_pt;
72918 	duk_regconst_t temp_first;
72919 	duk_small_int_t compile_round = 1;
72920 
72921 	DUK_ASSERT(comp_ctx != NULL);
72922 
72923 	thr = comp_ctx->thr;
72924 	DUK_ASSERT(thr != NULL);
72925 
72926 	func = &comp_ctx->curr_func;
72927 	DUK_ASSERT(func != NULL);
72928 
72929 	DUK__RECURSION_INCREASE(comp_ctx, thr);
72930 
72931 	duk_require_stack(thr, DUK__FUNCTION_BODY_REQUIRE_SLOTS);
72932 
72933 	/*
72934 	 *  Store lexer position for a later rewind
72935 	 */
72936 
72937 	DUK_LEXER_GETPOINT(&comp_ctx->lex, &lex_pt);
72938 
72939 	/*
72940 	 *  Program code (global and eval code) has an implicit return value
72941 	 *  from the last statement value (e.g. eval("1; 2+3;") returns 3).
72942 	 *  This is not the case with functions.  If implicit statement return
72943 	 *  value is requested, all statements are coerced to a register
72944 	 *  allocated here, and used in the implicit return statement below.
72945 	 */
72946 
72947 	/* XXX: this is pointless here because pass 1 is throw-away */
72948 	if (implicit_return_value) {
72949 		reg_stmt_value = DUK__ALLOCTEMP(comp_ctx);
72950 
72951 		/* If an implicit return value is needed by caller, it must be
72952 		 * initialized to 'undefined' because we don't know whether any
72953 		 * non-empty (where "empty" is a continuation type, and different
72954 		 * from an empty statement) statements will be executed.
72955 		 *
72956 		 * However, since 1st pass is a throwaway one, no need to emit
72957 		 * it here.
72958 		 */
72959 #if 0
72960 		duk__emit_bc(comp_ctx,
72961 		             DUK_OP_LDUNDEF,
72962 		             0);
72963 #endif
72964 	}
72965 
72966 	/*
72967 	 *  First pass.
72968 	 *
72969 	 *  Gather variable/function declarations needed for second pass.
72970 	 *  Code generated is dummy and discarded.
72971 	 */
72972 
72973 	func->in_directive_prologue = 1;
72974 	func->in_scanning = 1;
72975 	func->may_direct_eval = 0;
72976 	func->id_access_arguments = 0;
72977 	func->id_access_slow = 0;
72978 	func->id_access_slow_own = 0;
72979 	func->reg_stmt_value = reg_stmt_value;
72980 #if defined(DUK_USE_DEBUGGER_SUPPORT)
72981 	func->min_line = DUK_INT_MAX;
72982 	func->max_line = 0;
72983 #endif
72984 
72985 	/* duk__parse_stmts() expects curr_tok to be set; parse in "allow
72986 	 * regexp literal" mode with current strictness.
72987 	 */
72988 	if (expect_token >= 0) {
72989 		/* Eating a left curly; regexp mode is allowed by left curly
72990 		 * based on duk__token_lbp[] automatically.
72991 		 */
72992 		DUK_ASSERT(expect_token == DUK_TOK_LCURLY);
72993 		duk__update_lineinfo_currtoken(comp_ctx);
72994 		duk__advance_expect(comp_ctx, expect_token);
72995 	} else {
72996 		/* Need to set curr_token.t because lexing regexp mode depends on current
72997 		 * token type.  Zero value causes "allow regexp" mode.
72998 		 */
72999 		comp_ctx->curr_token.t = 0;
73000 		duk__advance(comp_ctx);
73001 	}
73002 
73003 	DUK_DDD(DUK_DDDPRINT("begin 1st pass"));
73004 	duk__parse_stmts(comp_ctx,
73005 	                 1,             /* allow source elements */
73006 	                 expect_eof,    /* expect EOF instead of } */
73007 	                 regexp_after); /* regexp after */
73008 	DUK_DDD(DUK_DDDPRINT("end 1st pass"));
73009 
73010 	/*
73011 	 *  Second (and possibly third) pass.
73012 	 *
73013 	 *  Generate actual code.  In most cases the need for shuffle
73014 	 *  registers is detected during pass 1, but in some corner cases
73015 	 *  we'll only detect it during pass 2 and a third pass is then
73016 	 *  needed (see GH-115).
73017 	 */
73018 
73019 	for (;;) {
73020 		duk_bool_t needs_shuffle_before = comp_ctx->curr_func.needs_shuffle;
73021 		compile_round++;
73022 
73023 		/*
73024 		 *  Rewind lexer.
73025 		 *
73026 		 *  duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp
73027 		 *  literal" mode with current strictness.
73028 		 *
73029 		 *  curr_token line number info should be initialized for pass 2 before
73030 		 *  generating prologue, to ensure prologue bytecode gets nice line numbers.
73031 		 */
73032 
73033 		DUK_DDD(DUK_DDDPRINT("rewind lexer"));
73034 		DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
73035 		comp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */
73036 		comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
73037 		duk__advance(comp_ctx);
73038 
73039 		/*
73040 		 *  Reset function state and perform register allocation, which creates
73041 		 *  'varmap' for second pass.  Function prologue for variable declarations,
73042 		 *  binding value initializations etc is emitted as a by-product.
73043 		 *
73044 		 *  Strict mode restrictions for duplicate and invalid argument
73045 		 *  names are checked here now that we know whether the function
73046 		 *  is actually strict.  See: test-dev-strict-mode-boundary.js.
73047 		 *
73048 		 *  Inner functions are compiled during pass 1 and are not reset.
73049 		 */
73050 
73051 		duk__reset_func_for_pass2(comp_ctx);
73052 		func->in_directive_prologue = 1;
73053 		func->in_scanning = 0;
73054 
73055 		/* must be able to emit code, alloc consts, etc. */
73056 
73057 		duk__init_varmap_and_prologue_for_pass2(comp_ctx,
73058 		                                        (implicit_return_value ? &reg_stmt_value : NULL));
73059 		func->reg_stmt_value = reg_stmt_value;
73060 
73061 		temp_first = DUK__GETTEMP(comp_ctx);
73062 
73063 		func->temp_first = temp_first;
73064 		func->temp_next = temp_first;
73065 		func->stmt_next = 0;
73066 		func->label_next = 0;
73067 
73068 		/* XXX: init or assert catch depth etc -- all values */
73069 		func->id_access_arguments = 0;
73070 		func->id_access_slow = 0;
73071 		func->id_access_slow_own = 0;
73072 
73073 		/*
73074 		 *  Check function name validity now that we know strictness.
73075 		 *  This only applies to function declarations and expressions,
73076 		 *  not setter/getter name.
73077 		 *
73078 		 *  See: test-dev-strict-mode-boundary.js
73079 		 */
73080 
73081 		if (func->is_function && !func->is_setget && func->h_name != NULL) {
73082 			if (func->is_strict) {
73083 				if (duk__hstring_is_eval_or_arguments(comp_ctx, func->h_name)) {
73084 					DUK_DDD(DUK_DDDPRINT("func name is 'eval' or 'arguments' in strict mode"));
73085 					goto error_funcname;
73086 				}
73087 				if (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
73088 					DUK_DDD(DUK_DDDPRINT("func name is a reserved word in strict mode"));
73089 					goto error_funcname;
73090 				}
73091 			} else {
73092 				if (DUK_HSTRING_HAS_RESERVED_WORD(func->h_name) &&
73093 				    !DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
73094 					DUK_DDD(DUK_DDDPRINT("func name is a reserved word in non-strict mode"));
73095 					goto error_funcname;
73096 				}
73097 			}
73098 		}
73099 
73100 		/*
73101 		 *  Second pass parsing.
73102 		 */
73103 
73104 		if (implicit_return_value) {
73105 			/* Default implicit return value. */
73106 			duk__emit_bc(comp_ctx,
73107 			             DUK_OP_LDUNDEF,
73108 			             0);
73109 		}
73110 
73111 		DUK_DDD(DUK_DDDPRINT("begin 2nd pass"));
73112 		duk__parse_stmts(comp_ctx,
73113 		                 1,             /* allow source elements */
73114 		                 expect_eof,    /* expect EOF instead of } */
73115 		                 regexp_after); /* regexp after */
73116 		DUK_DDD(DUK_DDDPRINT("end 2nd pass"));
73117 
73118 		duk__update_lineinfo_currtoken(comp_ctx);
73119 
73120 		if (needs_shuffle_before == comp_ctx->curr_func.needs_shuffle) {
73121 			/* Shuffle decision not changed. */
73122 			break;
73123 		}
73124 		if (compile_round >= 3) {
73125 			/* Should never happen but avoid infinite loop just in case. */
73126 			DUK_D(DUK_DPRINT("more than 3 compile passes needed, should never happen"));
73127 			DUK_ERROR_INTERNAL(thr);
73128 			DUK_WO_NORETURN(return;);
73129 		}
73130 		DUK_D(DUK_DPRINT("need additional round to compile function, round now %d", (int) compile_round));
73131 	}
73132 
73133 	/*
73134 	 *  Emit a final RETURN.
73135 	 *
73136 	 *  It would be nice to avoid emitting an unnecessary "return" opcode
73137 	 *  if the current PC is not reachable.  However, this cannot be reliably
73138 	 *  detected; even if the previous instruction is an unconditional jump,
73139 	 *  there may be a previous jump which jumps to current PC (which is the
73140 	 *  case for iteration and conditional statements, for instance).
73141 	 */
73142 
73143 	/* XXX: request a "last statement is terminal" from duk__parse_stmt() and duk__parse_stmts();
73144 	 * we could avoid the last RETURN if we could ensure there is no way to get here
73145 	 * (directly or via a jump)
73146 	 */
73147 
73148 	DUK_ASSERT(comp_ctx->curr_func.catch_depth == 0);
73149 	if (reg_stmt_value >= 0) {
73150 		DUK_ASSERT(DUK__ISREG(reg_stmt_value));
73151 		duk__emit_bc(comp_ctx, DUK_OP_RETREG, reg_stmt_value /*reg*/);
73152 	} else {
73153 		duk__emit_op_only(comp_ctx, DUK_OP_RETUNDEF);
73154 	}
73155 
73156 	/*
73157 	 *  Peephole optimize JUMP chains.
73158 	 */
73159 
73160 	duk__peephole_optimize_bytecode(comp_ctx);
73161 
73162 	/*
73163 	 *  comp_ctx->curr_func is now ready to be converted into an actual
73164 	 *  function template.
73165 	 */
73166 
73167 	DUK__RECURSION_DECREASE(comp_ctx, thr);
73168 	return;
73169 
73170  error_funcname:
73171 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FUNC_NAME);
73172 	DUK_WO_NORETURN(return;);
73173 }
73174 
73175 /*
73176  *  Parse a function-like expression:
73177  *
73178  *    - function expression
73179  *    - function declaration
73180  *    - function statement (non-standard)
73181  *    - setter/getter
73182  *
73183  *  Adds the function to comp_ctx->curr_func function table and returns the
73184  *  function number.
73185  *
73186  *  On entry, curr_token points to:
73187  *
73188  *    - the token after 'function' for function expression/declaration/statement
73189  *    - the token after 'set' or 'get' for setter/getter
73190  */
73191 
73192 /* Parse formals. */
73193 DUK_LOCAL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx) {
73194 	duk_hthread *thr = comp_ctx->thr;
73195 	duk_bool_t first = 1;
73196 	duk_uarridx_t n;
73197 
73198 	for (;;) {
73199 		if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
73200 			break;
73201 		}
73202 
73203 		if (first) {
73204 			/* no comma */
73205 			first = 0;
73206 		} else {
73207 			duk__advance_expect(comp_ctx, DUK_TOK_COMMA);
73208 		}
73209 
73210 		/* Note: when parsing a formal list in non-strict context, e.g.
73211 		 * "implements" is parsed as an identifier.  When the function is
73212 		 * later detected to be strict, the argument list must be rechecked
73213 		 * against a larger set of reserved words (that of strict mode).
73214 		 * This is handled by duk__parse_func_body().  Here we recognize
73215 		 * whatever tokens are considered reserved in current strictness
73216 		 * (which is not always enough).
73217 		 */
73218 
73219 		if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
73220 			DUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER);
73221 			DUK_WO_NORETURN(return;);
73222 		}
73223 		DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER);
73224 		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
73225 		DUK_DDD(DUK_DDDPRINT("formal argument: %!O",
73226 		                     (duk_heaphdr *) comp_ctx->curr_token.str1));
73227 
73228 		/* XXX: append primitive */
73229 		duk_push_hstring(thr, comp_ctx->curr_token.str1);
73230 		n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.argnames_idx);
73231 		duk_put_prop_index(thr, comp_ctx->curr_func.argnames_idx, n);
73232 
73233 		duk__advance(comp_ctx);  /* eat identifier */
73234 	}
73235 }
73236 
73237 /* Parse a function-like expression, assuming that 'comp_ctx->curr_func' is
73238  * correctly set up.  Assumes that curr_token is just after 'function' (or
73239  * 'set'/'get' etc).
73240  */
73241 DUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags) {
73242 	duk_hthread *thr = comp_ctx->thr;
73243 	duk_token *tok;
73244 	duk_bool_t no_advance;
73245 
73246 	DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
73247 	DUK_ASSERT(comp_ctx->curr_func.is_function == 1);
73248 	DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
73249 	DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
73250 	DUK_ASSERT(comp_ctx->curr_func.is_setget == ((flags & DUK__FUNC_FLAG_GETSET) != 0));
73251 
73252 	duk__update_lineinfo_currtoken(comp_ctx);
73253 
73254 	/*
73255 	 *  Function name (if any)
73256 	 *
73257 	 *  We don't check for prohibited names here, because we don't
73258 	 *  yet know whether the function will be strict.  Function body
73259 	 *  parsing handles this retroactively.
73260 	 *
73261 	 *  For function expressions and declarations function name must
73262 	 *  be an Identifer (excludes reserved words).  For setter/getter
73263 	 *  it is a PropertyName which allows reserved words and also
73264 	 *  strings and numbers (e.g. "{ get 1() { ... } }").
73265 	 *
73266 	 *  Function parsing may start either from prev_token or curr_token
73267 	 *  (object literal method definition uses prev_token for example).
73268 	 *  This is dealt with for the initial token.
73269 	 */
73270 
73271 	no_advance = (flags & DUK__FUNC_FLAG_USE_PREVTOKEN);
73272 	if (no_advance) {
73273 		tok = &comp_ctx->prev_token;
73274 	} else {
73275 		tok = &comp_ctx->curr_token;
73276 	}
73277 
73278 	if (flags & DUK__FUNC_FLAG_GETSET) {
73279 		/* PropertyName -> IdentifierName | StringLiteral | NumericLiteral */
73280 		if (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t == DUK_TOK_STRING) {
73281 			duk_push_hstring(thr, tok->str1);       /* keep in valstack */
73282 		} else if (tok->t == DUK_TOK_NUMBER) {
73283 			duk_push_number(thr, tok->num);
73284 			duk_to_string(thr, -1);
73285 		} else {
73286 			DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_GETSET_NAME);
73287 			DUK_WO_NORETURN(return;);
73288 		}
73289 		comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1);  /* borrowed reference */
73290 	} else {
73291 		/* Function name is an Identifier (not IdentifierName), but we get
73292 		 * the raw name (not recognizing keywords) here and perform the name
73293 		 * checks only after pass 1.
73294 		 */
73295 		if (tok->t_nores == DUK_TOK_IDENTIFIER) {
73296 			duk_push_hstring(thr, tok->str1);       /* keep in valstack */
73297 			comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1);  /* borrowed reference */
73298 		} else {
73299 			/* valstack will be unbalanced, which is OK */
73300 			DUK_ASSERT((flags & DUK__FUNC_FLAG_GETSET) == 0);
73301 			DUK_ASSERT(comp_ctx->curr_func.h_name == NULL);
73302 			no_advance = 1;
73303 			if (flags & DUK__FUNC_FLAG_DECL) {
73304 				DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_NAME_REQUIRED);
73305 				DUK_WO_NORETURN(return;);
73306 			}
73307 		}
73308 	}
73309 
73310 	DUK_DD(DUK_DDPRINT("function name: %!O",
73311 	                   (duk_heaphdr *) comp_ctx->curr_func.h_name));
73312 
73313 	if (!no_advance) {
73314 		duk__advance(comp_ctx);
73315 	}
73316 
73317 	/*
73318 	 *  Formal argument list
73319 	 *
73320 	 *  We don't check for prohibited names or for duplicate argument
73321 	 *  names here, becase we don't yet know whether the function will
73322 	 *  be strict.  Function body parsing handles this retroactively.
73323 	 */
73324 
73325 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
73326 
73327 	duk__parse_func_formals(comp_ctx);
73328 
73329 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RPAREN);
73330 	duk__advance(comp_ctx);
73331 
73332 	/*
73333 	 *  Parse function body
73334 	 */
73335 
73336 	duk__parse_func_body(comp_ctx,
73337 	                     0,   /* expect_eof */
73338 	                     0,   /* implicit_return_value */
73339 	                     flags & DUK__FUNC_FLAG_DECL, /* regexp_after */
73340 	                     DUK_TOK_LCURLY);  /* expect_token */
73341 
73342 	/*
73343 	 *  Convert duk_compiler_func to a function template and add it
73344 	 *  to the parent function table.
73345 	 */
73346 
73347 	duk__convert_to_func_template(comp_ctx);  /* -> [ ... func ] */
73348 }
73349 
73350 /* Parse an inner function, adding the function template to the current function's
73351  * function table.  Return a function number to be used by the outer function.
73352  *
73353  * Avoiding O(depth^2) inner function parsing is handled here.  On the first pass,
73354  * compile and register the function normally into the 'funcs' array, also recording
73355  * a lexer point (offset/line) to the closing brace of the function.  On the second
73356  * pass, skip the function and return the same 'fnum' as on the first pass by using
73357  * a running counter.
73358  *
73359  * An unfortunate side effect of this is that when parsing the inner function, almost
73360  * nothing is known of the outer function, i.e. the inner function's scope.  We don't
73361  * need that information at the moment, but it would allow some optimizations if it
73362  * were used.
73363  */
73364 DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags) {
73365 	duk_hthread *thr = comp_ctx->thr;
73366 	duk_compiler_func old_func;
73367 	duk_idx_t entry_top;
73368 	duk_int_t fnum;
73369 
73370 	/*
73371 	 *  On second pass, skip the function.
73372 	 */
73373 
73374 	if (!comp_ctx->curr_func.in_scanning) {
73375 		duk_lexer_point lex_pt;
73376 
73377 		fnum = comp_ctx->curr_func.fnum_next++;
73378 		duk_get_prop_index(thr, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
73379 		lex_pt.offset = (duk_size_t) duk_to_uint(thr, -1);
73380 		duk_pop(thr);
73381 		duk_get_prop_index(thr, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
73382 		lex_pt.line = duk_to_int(thr, -1);
73383 		duk_pop(thr);
73384 
73385 		DUK_DDD(DUK_DDDPRINT("second pass of an inner func, skip the function, reparse closing brace; lex offset=%ld, line=%ld",
73386 		                     (long) lex_pt.offset, (long) lex_pt.line));
73387 
73388 		DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
73389 		comp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */
73390 		comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
73391 		duk__advance(comp_ctx);
73392 
73393 		/* RegExp is not allowed after a function expression, e.g. in
73394 		 * (function () {} / 123).  A RegExp *is* allowed after a
73395 		 * function declaration!
73396 		 */
73397 		if (flags & DUK__FUNC_FLAG_DECL) {
73398 			comp_ctx->curr_func.allow_regexp_in_adv = 1;
73399 		}
73400 		duk__advance_expect(comp_ctx, DUK_TOK_RCURLY);
73401 
73402 		return fnum;
73403 	}
73404 
73405 	/*
73406 	 *  On first pass, perform actual parsing.  Remember valstack top on entry
73407 	 *  to restore it later, and switch to using a new function in comp_ctx.
73408 	 */
73409 
73410 	entry_top = duk_get_top(thr);
73411 	DUK_DDD(DUK_DDDPRINT("before func: entry_top=%ld, curr_tok.start_offset=%ld",
73412 	                     (long) entry_top, (long) comp_ctx->curr_token.start_offset));
73413 
73414 	duk_memcpy(&old_func, &comp_ctx->curr_func, sizeof(duk_compiler_func));
73415 
73416 	duk_memzero(&comp_ctx->curr_func, sizeof(duk_compiler_func));
73417 	duk__init_func_valstack_slots(comp_ctx);
73418 	DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
73419 
73420 	/* inherit initial strictness from parent */
73421 	comp_ctx->curr_func.is_strict = old_func.is_strict;
73422 
73423 	/* XXX: It might be better to just store the flags into the curr_func
73424 	 * struct and use them as is without this flag interpretation step
73425 	 * here.
73426 	 */
73427 	DUK_ASSERT(comp_ctx->curr_func.is_notail == 0);
73428 	comp_ctx->curr_func.is_function = 1;
73429 	DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
73430 	DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
73431 	comp_ctx->curr_func.is_setget = ((flags & DUK__FUNC_FLAG_GETSET) != 0);
73432 	comp_ctx->curr_func.is_namebinding = !(flags & (DUK__FUNC_FLAG_GETSET |
73433 	                                                DUK__FUNC_FLAG_METDEF |
73434 	                                                DUK__FUNC_FLAG_DECL));  /* no name binding for: declarations, objlit getset, objlit method def */
73435 	comp_ctx->curr_func.is_constructable = !(flags & (DUK__FUNC_FLAG_GETSET |
73436 	                                                  DUK__FUNC_FLAG_METDEF));  /* not constructable: objlit getset, objlit method def */
73437 
73438 	/*
73439 	 *  Parse inner function
73440 	 */
73441 
73442 	duk__parse_func_like_raw(comp_ctx, flags);  /* pushes function template */
73443 
73444 	/* prev_token.start_offset points to the closing brace here; when skipping
73445 	 * we're going to reparse the closing brace to ensure semicolon insertion
73446 	 * etc work as expected.
73447 	 */
73448 	DUK_DDD(DUK_DDDPRINT("after func: prev_tok.start_offset=%ld, curr_tok.start_offset=%ld",
73449 	                     (long) comp_ctx->prev_token.start_offset, (long) comp_ctx->curr_token.start_offset));
73450 	DUK_ASSERT(comp_ctx->lex.input[comp_ctx->prev_token.start_offset] == (duk_uint8_t) DUK_ASC_RCURLY);
73451 
73452 	/* XXX: append primitive */
73453 	DUK_ASSERT(duk_get_length(thr, old_func.funcs_idx) == (duk_size_t) (old_func.fnum_next * 3));
73454 	fnum = old_func.fnum_next++;
73455 
73456 	if (fnum > DUK__MAX_FUNCS) {
73457 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_FUNC_LIMIT);
73458 		DUK_WO_NORETURN(return 0;);
73459 	}
73460 
73461 	/* array writes autoincrement length */
73462 	(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3));
73463 	duk_push_size_t(thr, comp_ctx->prev_token.start_offset);
73464 	(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
73465 	duk_push_int(thr, comp_ctx->prev_token.start_line);
73466 	(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
73467 
73468 	/*
73469 	 *  Cleanup: restore original function, restore valstack state.
73470 	 *
73471 	 *  Function declaration handling needs the function name to be pushed
73472 	 *  on the value stack.
73473 	 */
73474 
73475 	if (flags & DUK__FUNC_FLAG_PUSHNAME_PASS1) {
73476 		DUK_ASSERT(comp_ctx->curr_func.h_name != NULL);
73477 		duk_push_hstring(thr, comp_ctx->curr_func.h_name);
73478 		duk_replace(thr, entry_top);
73479 		duk_set_top(thr, entry_top + 1);
73480 	} else {
73481 		duk_set_top(thr, entry_top);
73482 	}
73483 	duk_memcpy((void *) &comp_ctx->curr_func, (void *) &old_func, sizeof(duk_compiler_func));
73484 
73485 	return fnum;
73486 }
73487 
73488 /*
73489  *  Compile input string into an executable function template without
73490  *  arguments.
73491  *
73492  *  The string is parsed as the "Program" production of ECMAScript E5.
73493  *  Compilation context can be either global code or eval code (see E5
73494  *  Sections 14 and 15.1.2.1).
73495  *
73496  *  Input stack:  [ ... filename ]
73497  *  Output stack: [ ... func_template ]
73498  */
73499 
73500 /* XXX: source code property */
73501 
73502 DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_hthread *thr, void *udata) {
73503 	duk_hstring *h_filename;
73504 	duk__compiler_stkstate *comp_stk;
73505 	duk_compiler_ctx *comp_ctx;
73506 	duk_lexer_point *lex_pt;
73507 	duk_compiler_func *func;
73508 	duk_idx_t entry_top;
73509 	duk_bool_t is_strict;
73510 	duk_bool_t is_eval;
73511 	duk_bool_t is_funcexpr;
73512 	duk_small_uint_t flags;
73513 
73514 	DUK_ASSERT(thr != NULL);
73515 	DUK_ASSERT(udata != NULL);
73516 
73517 	/*
73518 	 *  Arguments check
73519 	 */
73520 
73521 	entry_top = duk_get_top(thr);
73522 	DUK_ASSERT(entry_top >= 1);
73523 
73524 	comp_stk = (duk__compiler_stkstate *) udata;
73525 	comp_ctx = &comp_stk->comp_ctx_alloc;
73526 	lex_pt = &comp_stk->lex_pt_alloc;
73527 	DUK_ASSERT(comp_ctx != NULL);
73528 	DUK_ASSERT(lex_pt != NULL);
73529 
73530 	flags = comp_stk->flags;
73531 	is_eval = (flags & DUK_COMPILE_EVAL ? 1 : 0);
73532 	is_strict = (flags & DUK_COMPILE_STRICT ? 1 : 0);
73533 	is_funcexpr = (flags & DUK_COMPILE_FUNCEXPR ? 1 : 0);
73534 
73535 	h_filename = duk_get_hstring(thr, -1);  /* may be undefined */
73536 
73537 	/*
73538 	 *  Init compiler and lexer contexts
73539 	 */
73540 
73541 	func = &comp_ctx->curr_func;
73542 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
73543 	comp_ctx->thr = NULL;
73544 	comp_ctx->h_filename = NULL;
73545 	comp_ctx->prev_token.str1 = NULL;
73546 	comp_ctx->prev_token.str2 = NULL;
73547 	comp_ctx->curr_token.str1 = NULL;
73548 	comp_ctx->curr_token.str2 = NULL;
73549 #endif
73550 
73551 	duk_require_stack(thr, DUK__COMPILE_ENTRY_SLOTS);
73552 
73553 	duk_push_dynamic_buffer(thr, 0);       /* entry_top + 0 */
73554 	duk_push_undefined(thr);               /* entry_top + 1 */
73555 	duk_push_undefined(thr);               /* entry_top + 2 */
73556 	duk_push_undefined(thr);               /* entry_top + 3 */
73557 	duk_push_undefined(thr);               /* entry_top + 4 */
73558 
73559 	comp_ctx->thr = thr;
73560 	comp_ctx->h_filename = h_filename;
73561 	comp_ctx->tok11_idx = entry_top + 1;
73562 	comp_ctx->tok12_idx = entry_top + 2;
73563 	comp_ctx->tok21_idx = entry_top + 3;
73564 	comp_ctx->tok22_idx = entry_top + 4;
73565 	comp_ctx->recursion_limit = DUK_USE_COMPILER_RECLIMIT;
73566 
73567 	/* comp_ctx->lex has been pre-initialized by caller: it has been
73568 	 * zeroed and input/input_length has been set.
73569 	 */
73570 	comp_ctx->lex.thr = thr;
73571 	/* comp_ctx->lex.input and comp_ctx->lex.input_length filled by caller */
73572 	comp_ctx->lex.slot1_idx = comp_ctx->tok11_idx;
73573 	comp_ctx->lex.slot2_idx = comp_ctx->tok12_idx;
73574 	comp_ctx->lex.buf_idx = entry_top + 0;
73575 	comp_ctx->lex.buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, entry_top + 0);
73576 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(comp_ctx->lex.buf) && !DUK_HBUFFER_HAS_EXTERNAL(comp_ctx->lex.buf));
73577 	comp_ctx->lex.token_limit = DUK_COMPILER_TOKEN_LIMIT;
73578 
73579 	lex_pt->offset = 0;
73580 	lex_pt->line = 1;
73581 	DUK_LEXER_SETPOINT(&comp_ctx->lex, lex_pt);    /* fills window */
73582 	comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
73583 
73584 	/*
73585 	 *  Initialize function state for a zero-argument function
73586 	 */
73587 
73588 	duk__init_func_valstack_slots(comp_ctx);
73589 	DUK_ASSERT(func->num_formals == 0);
73590 
73591 	if (is_funcexpr) {
73592 		/* Name will be filled from function expression, not by caller.
73593 		 * This case is used by Function constructor and duk_compile()
73594 		 * API with the DUK_COMPILE_FUNCTION option.
73595 		 */
73596 		DUK_ASSERT(func->h_name == NULL);
73597 	} else {
73598 		duk_push_hstring_stridx(thr, (is_eval ? DUK_STRIDX_EVAL :
73599 		                                        DUK_STRIDX_GLOBAL));
73600 		func->h_name = duk_get_hstring(thr, -1);
73601 	}
73602 
73603 	/*
73604 	 *  Parse a function body or a function-like expression, depending
73605 	 *  on flags.
73606 	 */
73607 
73608 	DUK_ASSERT(func->is_setget == 0);
73609 	func->is_strict = (duk_uint8_t) is_strict;
73610 	DUK_ASSERT(func->is_notail == 0);
73611 
73612 	if (is_funcexpr) {
73613 		func->is_function = 1;
73614 		DUK_ASSERT(func->is_eval == 0);
73615 		DUK_ASSERT(func->is_global == 0);
73616 		func->is_namebinding = 1;
73617 		func->is_constructable = 1;
73618 
73619 		duk__advance(comp_ctx);  /* init 'curr_token' */
73620 		duk__advance_expect(comp_ctx, DUK_TOK_FUNCTION);
73621 		(void) duk__parse_func_like_raw(comp_ctx, 0 /*flags*/);
73622 	} else {
73623 		DUK_ASSERT(func->is_function == 0);
73624 		DUK_ASSERT(is_eval == 0 || is_eval == 1);
73625 		func->is_eval = (duk_uint8_t) is_eval;
73626 		func->is_global = (duk_uint8_t) !is_eval;
73627 		DUK_ASSERT(func->is_namebinding == 0);
73628 		DUK_ASSERT(func->is_constructable == 0);
73629 
73630 		duk__parse_func_body(comp_ctx,
73631 		                     1,             /* expect_eof */
73632 		                     1,             /* implicit_return_value */
73633 		                     1,             /* regexp_after (does not matter) */
73634 		                     -1);           /* expect_token */
73635 	}
73636 
73637 	/*
73638 	 *  Convert duk_compiler_func to a function template
73639 	 */
73640 
73641 	duk__convert_to_func_template(comp_ctx);
73642 
73643 	/*
73644 	 *  Wrapping duk_safe_call() will mangle the stack, just return stack top
73645 	 */
73646 
73647 	/* [ ... filename (temps) func ] */
73648 
73649 	return 1;
73650 }
73651 
73652 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) {
73653 	duk__compiler_stkstate comp_stk;
73654 	duk_compiler_ctx *prev_ctx;
73655 	duk_ret_t safe_rc;
73656 
73657 	DUK_ASSERT(thr != NULL);
73658 	DUK_ASSERT(src_buffer != NULL);
73659 
73660 	/* preinitialize lexer state partially */
73661 	duk_memzero(&comp_stk, sizeof(comp_stk));
73662 	comp_stk.flags = flags;
73663 	DUK_LEXER_INITCTX(&comp_stk.comp_ctx_alloc.lex);
73664 	comp_stk.comp_ctx_alloc.lex.input = src_buffer;
73665 	comp_stk.comp_ctx_alloc.lex.input_length = src_length;
73666 	comp_stk.comp_ctx_alloc.lex.flags = flags;  /* Forward flags directly for now. */
73667 
73668 	/* [ ... filename ] */
73669 
73670 	prev_ctx = thr->compile_ctx;
73671 	thr->compile_ctx = &comp_stk.comp_ctx_alloc;  /* for duk_error_augment.c */
73672 	safe_rc = duk_safe_call(thr, duk__js_compile_raw, (void *) &comp_stk /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
73673 	thr->compile_ctx = prev_ctx;  /* must restore reliably before returning */
73674 
73675 	if (safe_rc != DUK_EXEC_SUCCESS) {
73676 		DUK_D(DUK_DPRINT("compilation failed: %!T", duk_get_tval(thr, -1)));
73677 		(void) duk_throw(thr);
73678 		DUK_WO_NORETURN(return;);
73679 	}
73680 
73681 	/* [ ... template ] */
73682 }
73683 
73684 /* automatic undefs */
73685 #undef DUK__ALLOCTEMP
73686 #undef DUK__ALLOCTEMPS
73687 #undef DUK__ALLOW_AUTO_SEMI_ALWAYS
73688 #undef DUK__BC_INITIAL_INSTS
73689 #undef DUK__BP_ADDITIVE
73690 #undef DUK__BP_ASSIGNMENT
73691 #undef DUK__BP_BAND
73692 #undef DUK__BP_BOR
73693 #undef DUK__BP_BXOR
73694 #undef DUK__BP_CALL
73695 #undef DUK__BP_CLOSING
73696 #undef DUK__BP_COMMA
73697 #undef DUK__BP_CONDITIONAL
73698 #undef DUK__BP_EOF
73699 #undef DUK__BP_EQUALITY
73700 #undef DUK__BP_EXPONENTIATION
73701 #undef DUK__BP_FOR_EXPR
73702 #undef DUK__BP_INVALID
73703 #undef DUK__BP_LAND
73704 #undef DUK__BP_LOR
73705 #undef DUK__BP_MEMBER
73706 #undef DUK__BP_MULTIPLICATIVE
73707 #undef DUK__BP_POSTFIX
73708 #undef DUK__BP_RELATIONAL
73709 #undef DUK__BP_SHIFT
73710 #undef DUK__COMPILE_ENTRY_SLOTS
73711 #undef DUK__CONST_MARKER
73712 #undef DUK__DUMP_ISPEC
73713 #undef DUK__DUMP_IVALUE
73714 #undef DUK__EMIT_FLAG_A_IS_SOURCE
73715 #undef DUK__EMIT_FLAG_BC_REGCONST
73716 #undef DUK__EMIT_FLAG_B_IS_TARGET
73717 #undef DUK__EMIT_FLAG_C_IS_TARGET
73718 #undef DUK__EMIT_FLAG_NO_SHUFFLE_A
73719 #undef DUK__EMIT_FLAG_NO_SHUFFLE_B
73720 #undef DUK__EMIT_FLAG_NO_SHUFFLE_C
73721 #undef DUK__EMIT_FLAG_RESERVE_JUMPSLOT
73722 #undef DUK__EXPR_FLAG_ALLOW_EMPTY
73723 #undef DUK__EXPR_FLAG_REJECT_IN
73724 #undef DUK__EXPR_FLAG_REQUIRE_INIT
73725 #undef DUK__EXPR_RBP_MASK
73726 #undef DUK__FUNCTION_BODY_REQUIRE_SLOTS
73727 #undef DUK__FUNCTION_INIT_REQUIRE_SLOTS
73728 #undef DUK__FUNC_FLAG_DECL
73729 #undef DUK__FUNC_FLAG_GETSET
73730 #undef DUK__FUNC_FLAG_METDEF
73731 #undef DUK__FUNC_FLAG_PUSHNAME_PASS1
73732 #undef DUK__FUNC_FLAG_USE_PREVTOKEN
73733 #undef DUK__GETCONST_MAX_CONSTS_CHECK
73734 #undef DUK__GETTEMP
73735 #undef DUK__HAS_TERM
73736 #undef DUK__HAS_VAL
73737 #undef DUK__ISCONST
73738 #undef DUK__ISREG
73739 #undef DUK__ISREG_NOTTEMP
73740 #undef DUK__ISREG_TEMP
73741 #undef DUK__IS_TERMINAL
73742 #undef DUK__IVAL_FLAG_ALLOW_CONST
73743 #undef DUK__IVAL_FLAG_REQUIRE_SHORT
73744 #undef DUK__IVAL_FLAG_REQUIRE_TEMP
73745 #undef DUK__MAX_ARRAY_INIT_VALUES
73746 #undef DUK__MAX_CONSTS
73747 #undef DUK__MAX_FUNCS
73748 #undef DUK__MAX_OBJECT_INIT_PAIRS
73749 #undef DUK__MAX_TEMPS
73750 #undef DUK__MK_LBP
73751 #undef DUK__MK_LBP_FLAGS
73752 #undef DUK__OBJ_LIT_KEY_GET
73753 #undef DUK__OBJ_LIT_KEY_PLAIN
73754 #undef DUK__OBJ_LIT_KEY_SET
73755 #undef DUK__PARSE_EXPR_SLOTS
73756 #undef DUK__PARSE_STATEMENTS_SLOTS
73757 #undef DUK__RECURSION_DECREASE
73758 #undef DUK__RECURSION_INCREASE
73759 #undef DUK__REMOVECONST
73760 #undef DUK__SETTEMP
73761 #undef DUK__SETTEMP_CHECKMAX
73762 #undef DUK__STILL_PROLOGUE
73763 #undef DUK__TOKEN_LBP_BP_MASK
73764 #undef DUK__TOKEN_LBP_FLAG_NO_REGEXP
73765 #undef DUK__TOKEN_LBP_FLAG_TERMINATES
73766 #undef DUK__TOKEN_LBP_FLAG_UNUSED
73767 #undef DUK__TOKEN_LBP_GET_BP
73768 /*
73769  *  ECMAScript bytecode executor.
73770  */
73771 
73772 /* #include duk_internal.h -> already included */
73773 
73774 /*
73775  *  Local declarations.
73776  */
73777 
73778 DUK_LOCAL_DECL void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_activation *entry_act);
73779 
73780 /*
73781  *  Misc helpers.
73782  */
73783 
73784 /* Forced inline declaration, only applied for performance oriented build. */
73785 #if defined(DUK_USE_EXEC_PREFER_SIZE)
73786 #define DUK__INLINE_PERF
73787 #define DUK__NOINLINE_PERF
73788 #else
73789 #define DUK__INLINE_PERF DUK_ALWAYS_INLINE
73790 #define DUK__NOINLINE_PERF DUK_NOINLINE
73791 #endif
73792 
73793 /* Replace value stack top to value at 'tv_ptr'.  Optimize for
73794  * performance by only applying the net refcount change.
73795  */
73796 #define DUK__REPLACE_TO_TVPTR(thr,tv_ptr) do { \
73797 		duk_hthread *duk__thr; \
73798 		duk_tval *duk__tvsrc; \
73799 		duk_tval *duk__tvdst; \
73800 		duk_tval duk__tvtmp; \
73801 		duk__thr = (thr); \
73802 		duk__tvsrc = DUK_GET_TVAL_NEGIDX(duk__thr, -1); \
73803 		duk__tvdst = (tv_ptr); \
73804 		DUK_TVAL_SET_TVAL(&duk__tvtmp, duk__tvdst); \
73805 		DUK_TVAL_SET_TVAL(duk__tvdst, duk__tvsrc); \
73806 		DUK_TVAL_SET_UNDEFINED(duk__tvsrc);  /* value stack init policy */ \
73807 		duk__thr->valstack_top = duk__tvsrc; \
73808 		DUK_TVAL_DECREF(duk__thr, &duk__tvtmp); \
73809 	} while (0)
73810 
73811 /* XXX: candidate of being an internal shared API call */
73812 #if 0  /* unused */
73813 DUK_LOCAL void duk__push_tvals_incref_only(duk_hthread *thr, duk_tval *tv_src, duk_small_uint_fast_t count) {
73814 	duk_tval *tv_dst;
73815 	duk_size_t copy_size;
73816 	duk_size_t i;
73817 
73818 	tv_dst = thr->valstack_top;
73819 	copy_size = sizeof(duk_tval) * count;
73820 	duk_memcpy((void *) tv_dst, (const void *) tv_src, copy_size);
73821 	for (i = 0; i < count; i++) {
73822 		DUK_TVAL_INCREF(thr, tv_dst);
73823 		tv_dst++;
73824 	}
73825 	thr->valstack_top = tv_dst;
73826 }
73827 #endif
73828 
73829 /*
73830  *  Arithmetic, binary, and logical helpers.
73831  *
73832  *  Note: there is no opcode for logical AND or logical OR; this is on
73833  *  purpose, because the evalution order semantics for them make such
73834  *  opcodes pretty pointless: short circuiting means they are most
73835  *  comfortably implemented as jumps.  However, a logical NOT opcode
73836  *  is useful.
73837  *
73838  *  Note: careful with duk_tval pointers here: they are potentially
73839  *  invalidated by any DECREF and almost any API call.  It's still
73840  *  preferable to work without making a copy but that's not always
73841  *  possible.
73842  */
73843 
73844 DUK_LOCAL DUK__INLINE_PERF duk_double_t duk__compute_mod(duk_double_t d1, duk_double_t d2) {
73845 	return (duk_double_t) duk_js_arith_mod((double) d1, (double) d2);
73846 }
73847 
73848 #if defined(DUK_USE_ES7_EXP_OPERATOR)
73849 DUK_LOCAL DUK__INLINE_PERF duk_double_t duk__compute_exp(duk_double_t d1, duk_double_t d2) {
73850 	return (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);
73851 }
73852 #endif
73853 
73854 DUK_LOCAL DUK__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) {
73855 	/*
73856 	 *  Addition operator is different from other arithmetic
73857 	 *  operations in that it also provides string concatenation.
73858 	 *  Hence it is implemented separately.
73859 	 *
73860 	 *  There is a fast path for number addition.  Other cases go
73861 	 *  through potentially multiple coercions as described in the
73862 	 *  E5 specification.  It may be possible to reduce the number
73863 	 *  of coercions, but this must be done carefully to preserve
73864 	 *  the exact semantics.
73865 	 *
73866 	 *  E5 Section 11.6.1.
73867 	 *
73868 	 *  Custom types also have special behavior implemented here.
73869 	 */
73870 
73871 	duk_double_union du;
73872 
73873 	DUK_ASSERT(thr != NULL);
73874 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
73875 	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
73876 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
73877 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
73878 
73879 	/*
73880 	 *  Fast paths
73881 	 */
73882 
73883 #if defined(DUK_USE_FASTINT)
73884 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
73885 		duk_int64_t v1, v2, v3;
73886 		duk_int32_t v3_hi;
73887 		duk_tval *tv_z;
73888 
73889 		/* Input values are signed 48-bit so we can detect overflow
73890 		 * reliably from high bits or just a comparison.
73891 		 */
73892 
73893 		v1 = DUK_TVAL_GET_FASTINT(tv_x);
73894 		v2 = DUK_TVAL_GET_FASTINT(tv_y);
73895 		v3 = v1 + v2;
73896 		v3_hi = (duk_int32_t) (v3 >> 32);
73897 		if (DUK_LIKELY(v3_hi >= DUK_I64_CONSTANT(-0x8000) && v3_hi <= DUK_I64_CONSTANT(0x7fff))) {
73898 			tv_z = thr->valstack_bottom + idx_z;
73899 			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3);  /* side effects */
73900 			return;
73901 		} else {
73902 			/* overflow, fall through */
73903 			;
73904 		}
73905 	}
73906 #endif  /* DUK_USE_FASTINT */
73907 
73908 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
73909 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
73910 		duk_tval *tv_z;
73911 #endif
73912 
73913 		du.d = DUK_TVAL_GET_NUMBER(tv_x) + DUK_TVAL_GET_NUMBER(tv_y);
73914 #if defined(DUK_USE_EXEC_PREFER_SIZE)
73915 		duk_push_number(thr, du.d);  /* will NaN normalize result */
73916 		duk_replace(thr, (duk_idx_t) idx_z);
73917 #else  /* DUK_USE_EXEC_PREFER_SIZE */
73918 		DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
73919 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
73920 		tv_z = thr->valstack_bottom + idx_z;
73921 		DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d);  /* side effects */
73922 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
73923 		return;
73924 	}
73925 
73926 	/*
73927 	 *  Slow path: potentially requires function calls for coercion
73928 	 */
73929 
73930 	duk_push_tval(thr, tv_x);
73931 	duk_push_tval(thr, tv_y);
73932 	duk_to_primitive(thr, -2, DUK_HINT_NONE);  /* side effects -> don't use tv_x, tv_y after */
73933 	duk_to_primitive(thr, -1, DUK_HINT_NONE);
73934 
73935 	/* Since Duktape 2.x plain buffers are treated like ArrayBuffer. */
73936 	if (duk_is_string(thr, -2) || duk_is_string(thr, -1)) {
73937 		/* Symbols shouldn't technically be handled here, but should
73938 		 * go into the default ToNumber() coercion path instead and
73939 		 * fail there with a TypeError.  However, there's a ToString()
73940 		 * in duk_concat_2() which also fails with TypeError so no
73941 		 * explicit check is needed.
73942 		 */
73943 		duk_concat_2(thr);  /* [... s1 s2] -> [... s1+s2] */
73944 	} else {
73945 		duk_double_t d1, d2;
73946 
73947 		d1 = duk_to_number_m2(thr);
73948 		d2 = duk_to_number_m1(thr);
73949 		DUK_ASSERT(duk_is_number(thr, -2));
73950 		DUK_ASSERT(duk_is_number(thr, -1));
73951 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);
73952 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);
73953 
73954 		du.d = d1 + d2;
73955 		duk_pop_2_unsafe(thr);
73956 		duk_push_number(thr, du.d);  /* will NaN normalize result */
73957 	}
73958 	duk_replace(thr, (duk_idx_t) idx_z);  /* side effects */
73959 }
73960 
73961 DUK_LOCAL DUK__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) {
73962 	/*
73963 	 *  Arithmetic operations other than '+' have number-only semantics
73964 	 *  and are implemented here.  The separate switch-case here means a
73965 	 *  "double dispatch" of the arithmetic opcode, but saves code space.
73966 	 *
73967 	 *  E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
73968 	 */
73969 
73970 	duk_double_t d1, d2;
73971 	duk_double_union du;
73972 	duk_small_uint_fast_t opcode_shifted;
73973 #if defined(DUK_USE_FASTINT) || !defined(DUK_USE_EXEC_PREFER_SIZE)
73974 	duk_tval *tv_z;
73975 #endif
73976 
73977 	DUK_ASSERT(thr != NULL);
73978 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
73979 	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
73980 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
73981 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
73982 
73983 	opcode_shifted = opcode >> 2;  /* Get base opcode without reg/const modifiers. */
73984 
73985 #if defined(DUK_USE_FASTINT)
73986 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
73987 		duk_int64_t v1, v2, v3;
73988 		duk_int32_t v3_hi;
73989 
73990 		v1 = DUK_TVAL_GET_FASTINT(tv_x);
73991 		v2 = DUK_TVAL_GET_FASTINT(tv_y);
73992 
73993 		switch (opcode_shifted) {
73994 		case DUK_OP_SUB >> 2: {
73995 			v3 = v1 - v2;
73996 			break;
73997 		}
73998 		case DUK_OP_MUL >> 2: {
73999 			/* Must ensure result is 64-bit (no overflow); a
74000 			 * simple and sufficient fast path is to allow only
74001 			 * 32-bit inputs.  Avoid zero inputs to avoid
74002 			 * negative zero issues (-1 * 0 = -0, for instance).
74003 			 */
74004 			if (v1 >= DUK_I64_CONSTANT(-0x80000000) && v1 <= DUK_I64_CONSTANT(0x7fffffff) && v1 != 0 &&
74005 			    v2 >= DUK_I64_CONSTANT(-0x80000000) && v2 <= DUK_I64_CONSTANT(0x7fffffff) && v2 != 0) {
74006 				v3 = v1 * v2;
74007 			} else {
74008 				goto skip_fastint;
74009 			}
74010 			break;
74011 		}
74012 		case DUK_OP_DIV >> 2: {
74013 			/* Don't allow a zero divisor.  Fast path check by
74014 			 * "verifying" with multiplication.  Also avoid zero
74015 			 * dividend to avoid negative zero issues (0 / -1 = -0
74016 			 * for instance).
74017 			 */
74018 			if (v1 == 0 || v2 == 0) {
74019 				goto skip_fastint;
74020 			}
74021 			v3 = v1 / v2;
74022 			if (v3 * v2 != v1) {
74023 				goto skip_fastint;
74024 			}
74025 			break;
74026 		}
74027 		case DUK_OP_MOD >> 2: {
74028 			/* Don't allow a zero divisor.  Restrict both v1 and
74029 			 * v2 to positive values to avoid compiler specific
74030 			 * behavior.
74031 			 */
74032 			if (v1 < 1 || v2 < 1) {
74033 				goto skip_fastint;
74034 			}
74035 			v3 = v1 % v2;
74036 			DUK_ASSERT(v3 >= 0);
74037 			DUK_ASSERT(v3 < v2);
74038 			DUK_ASSERT(v1 - (v1 / v2) * v2 == v3);
74039 			break;
74040 		}
74041 		default: {
74042 			/* Possible with DUK_OP_EXP. */
74043 			goto skip_fastint;
74044 		}
74045 		}
74046 
74047 		v3_hi = (duk_int32_t) (v3 >> 32);
74048 		if (DUK_LIKELY(v3_hi >= DUK_I64_CONSTANT(-0x8000) && v3_hi <= DUK_I64_CONSTANT(0x7fff))) {
74049 			tv_z = thr->valstack_bottom + idx_z;
74050 			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3);  /* side effects */
74051 			return;
74052 		}
74053 		/* fall through if overflow etc */
74054 	}
74055  skip_fastint:
74056 #endif  /* DUK_USE_FASTINT */
74057 
74058 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
74059 		/* fast path */
74060 		d1 = DUK_TVAL_GET_NUMBER(tv_x);
74061 		d2 = DUK_TVAL_GET_NUMBER(tv_y);
74062 	} else {
74063 		duk_push_tval(thr, tv_x);
74064 		duk_push_tval(thr, tv_y);
74065 		d1 = duk_to_number_m2(thr);  /* side effects */
74066 		d2 = duk_to_number_m1(thr);
74067 		DUK_ASSERT(duk_is_number(thr, -2));
74068 		DUK_ASSERT(duk_is_number(thr, -1));
74069 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);
74070 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);
74071 		duk_pop_2_unsafe(thr);
74072 	}
74073 
74074 	switch (opcode_shifted) {
74075 	case DUK_OP_SUB >> 2: {
74076 		du.d = d1 - d2;
74077 		break;
74078 	}
74079 	case DUK_OP_MUL >> 2: {
74080 		du.d = d1 * d2;
74081 		break;
74082 	}
74083 	case DUK_OP_DIV >> 2: {
74084 		/* Division-by-zero is undefined behavior, so
74085 		 * rely on a helper.
74086 		 */
74087 		du.d = duk_double_div(d1, d2);
74088 		break;
74089 	}
74090 	case DUK_OP_MOD >> 2: {
74091 		du.d = duk__compute_mod(d1, d2);
74092 		break;
74093 	}
74094 #if defined(DUK_USE_ES7_EXP_OPERATOR)
74095 	case DUK_OP_EXP >> 2: {
74096 		du.d = duk__compute_exp(d1, d2);
74097 		break;
74098 	}
74099 #endif
74100 	default: {
74101 		DUK_UNREACHABLE();
74102 		du.d = DUK_DOUBLE_NAN;  /* should not happen */
74103 		break;
74104 	}
74105 	}
74106 
74107 #if defined(DUK_USE_EXEC_PREFER_SIZE)
74108 	duk_push_number(thr, du.d);  /* will NaN normalize result */
74109 	duk_replace(thr, (duk_idx_t) idx_z);
74110 #else  /* DUK_USE_EXEC_PREFER_SIZE */
74111 	/* important to use normalized NaN with 8-byte tagged types */
74112 	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
74113 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
74114 	tv_z = thr->valstack_bottom + idx_z;
74115 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d);  /* side effects */
74116 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
74117 }
74118 
74119 DUK_LOCAL DUK__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) {
74120 	/*
74121 	 *  Binary bitwise operations use different coercions (ToInt32, ToUint32)
74122 	 *  depending on the operation.  We coerce the arguments first using
74123 	 *  ToInt32(), and then cast to an 32-bit value if necessary.  Note that
74124 	 *  such casts must be correct even if there is no native 32-bit type
74125 	 *  (e.g., duk_int32_t and duk_uint32_t are 64-bit).
74126 	 *
74127 	 *  E5 Sections 11.10, 11.7.1, 11.7.2, 11.7.3
74128 	 */
74129 
74130 	duk_int32_t i1, i2, i3;
74131 	duk_uint32_t u1, u2, u3;
74132 #if defined(DUK_USE_FASTINT)
74133 	duk_int64_t fi3;
74134 #else
74135 	duk_double_t d3;
74136 #endif
74137 	duk_small_uint_fast_t opcode_shifted;
74138 #if defined(DUK_USE_FASTINT) || !defined(DUK_USE_EXEC_PREFER_SIZE)
74139 	duk_tval *tv_z;
74140 #endif
74141 
74142 	DUK_ASSERT(thr != NULL);
74143 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
74144 	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
74145 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
74146 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
74147 
74148 	opcode_shifted = opcode >> 2;  /* Get base opcode without reg/const modifiers. */
74149 
74150 #if defined(DUK_USE_FASTINT)
74151 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
74152 		i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_x);
74153 		i2 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_y);
74154 	}
74155 	else
74156 #endif  /* DUK_USE_FASTINT */
74157 	{
74158 		duk_push_tval(thr, tv_x);
74159 		duk_push_tval(thr, tv_y);
74160 		i1 = duk_to_int32(thr, -2);
74161 		i2 = duk_to_int32(thr, -1);
74162 		duk_pop_2_unsafe(thr);
74163 	}
74164 
74165 	switch (opcode_shifted) {
74166 	case DUK_OP_BAND >> 2: {
74167 		i3 = i1 & i2;
74168 		break;
74169 	}
74170 	case DUK_OP_BOR >> 2: {
74171 		i3 = i1 | i2;
74172 		break;
74173 	}
74174 	case DUK_OP_BXOR >> 2: {
74175 		i3 = i1 ^ i2;
74176 		break;
74177 	}
74178 	case DUK_OP_BASL >> 2: {
74179 		/* Signed shift, named "arithmetic" (asl) because the result
74180 		 * is signed, e.g. 4294967295 << 1 -> -2.  Note that result
74181 		 * must be masked.
74182 		 */
74183 
74184 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
74185 		i3 = (duk_int32_t) (((duk_uint32_t) i1) << (u2 & 0x1fUL));  /* E5 Section 11.7.1, steps 7 and 8 */
74186 		i3 = i3 & ((duk_int32_t) 0xffffffffUL);                     /* Note: left shift, should mask */
74187 		break;
74188 	}
74189 	case DUK_OP_BASR >> 2: {
74190 		/* signed shift */
74191 
74192 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
74193 		i3 = i1 >> (u2 & 0x1fUL);                      /* E5 Section 11.7.2, steps 7 and 8 */
74194 		break;
74195 	}
74196 	case DUK_OP_BLSR >> 2: {
74197 		/* unsigned shift */
74198 
74199 		u1 = ((duk_uint32_t) i1) & 0xffffffffUL;
74200 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
74201 
74202 		/* special result value handling */
74203 		u3 = u1 >> (u2 & 0x1fUL);     /* E5 Section 11.7.2, steps 7 and 8 */
74204 #if defined(DUK_USE_FASTINT)
74205 		fi3 = (duk_int64_t) u3;
74206 		goto fastint_result_set;
74207 #else
74208 		d3 = (duk_double_t) u3;
74209 		goto result_set;
74210 #endif
74211 	}
74212 	default: {
74213 		DUK_UNREACHABLE();
74214 		i3 = 0;  /* should not happen */
74215 		break;
74216 	}
74217 	}
74218 
74219 #if defined(DUK_USE_FASTINT)
74220 	/* Result is always fastint compatible. */
74221 	/* XXX: Set 32-bit result (but must then handle signed and
74222 	 * unsigned results separately).
74223 	 */
74224 	fi3 = (duk_int64_t) i3;
74225 
74226  fastint_result_set:
74227 	tv_z = thr->valstack_bottom + idx_z;
74228 	DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, fi3);  /* side effects */
74229 #else  /* DUK_USE_FASTINT */
74230 	d3 = (duk_double_t) i3;
74231 
74232  result_set:
74233 	DUK_ASSERT(!DUK_ISNAN(d3));            /* 'd3' is never NaN, so no need to normalize */
74234 	DUK_ASSERT_DOUBLE_IS_NORMALIZED(d3);   /* always normalized */
74235 
74236 #if defined(DUK_USE_EXEC_PREFER_SIZE)
74237 	duk_push_number(thr, d3);  /* would NaN normalize result, but unnecessary */
74238 	duk_replace(thr, (duk_idx_t) idx_z);
74239 #else  /* DUK_USE_EXEC_PREFER_SIZE */
74240 	tv_z = thr->valstack_bottom + idx_z;
74241 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d3);  /* side effects */
74242 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
74243 #endif  /* DUK_USE_FASTINT */
74244 }
74245 
74246 /* In-place unary operation. */
74247 DUK_LOCAL DUK__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) {
74248 	/*
74249 	 *  Arithmetic operations other than '+' have number-only semantics
74250 	 *  and are implemented here.  The separate switch-case here means a
74251 	 *  "double dispatch" of the arithmetic opcode, but saves code space.
74252 	 *
74253 	 *  E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
74254 	 */
74255 
74256 	duk_tval *tv;
74257 	duk_double_t d1;
74258 	duk_double_union du;
74259 
74260 	DUK_ASSERT(thr != NULL);
74261 	DUK_ASSERT(opcode == DUK_OP_UNM || opcode == DUK_OP_UNP);
74262 	DUK_ASSERT_DISABLE(idx_src >= 0);
74263 	DUK_ASSERT_DISABLE(idx_dst >= 0);
74264 
74265 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
74266 
74267 #if defined(DUK_USE_FASTINT)
74268 	if (DUK_TVAL_IS_FASTINT(tv)) {
74269 		duk_int64_t v1, v2;
74270 
74271 		v1 = DUK_TVAL_GET_FASTINT(tv);
74272 		if (opcode == DUK_OP_UNM) {
74273 			/* The smallest fastint is no longer 48-bit when
74274 			 * negated.  Positive zero becames negative zero
74275 			 * (cannot be represented) when negated.
74276 			 */
74277 			if (DUK_LIKELY(v1 != DUK_FASTINT_MIN && v1 != 0)) {
74278 				v2 = -v1;
74279 				tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
74280 				DUK_TVAL_SET_FASTINT_UPDREF(thr, tv, v2);
74281 				return;
74282 			}
74283 		} else {
74284 			/* ToNumber() for a fastint is a no-op. */
74285 			DUK_ASSERT(opcode == DUK_OP_UNP);
74286 			v2 = v1;
74287 			tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
74288 			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv, v2);
74289 			return;
74290 		}
74291 		/* fall through if overflow etc */
74292 	}
74293 #endif  /* DUK_USE_FASTINT */
74294 
74295 	if (DUK_TVAL_IS_NUMBER(tv)) {
74296 		d1 = DUK_TVAL_GET_NUMBER(tv);
74297 	} else {
74298 		d1 = duk_to_number_tval(thr, tv);  /* side effects */
74299 	}
74300 
74301 	if (opcode == DUK_OP_UNP) {
74302 		/* ToNumber() for a double is a no-op, but unary plus is
74303 		 * used to force a fastint check so do that here.
74304 		 */
74305 		du.d = d1;
74306 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
74307 #if defined(DUK_USE_FASTINT)
74308 		tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
74309 		DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF(thr, tv, du.d);  /* always 'fast', i.e. inlined */
74310 		return;
74311 #endif
74312 	} else {
74313 		DUK_ASSERT(opcode == DUK_OP_UNM);
74314 		du.d = -d1;
74315 		DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);  /* mandatory if du.d is a NaN */
74316 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
74317 	}
74318 
74319 	/* XXX: size optimize: push+replace? */
74320 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
74321 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, du.d);
74322 }
74323 
74324 DUK_LOCAL DUK__INLINE_PERF void duk__vm_bitwise_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst) {
74325 	/*
74326 	 *  E5 Section 11.4.8
74327 	 */
74328 
74329 	duk_tval *tv;
74330 	duk_int32_t i1, i2;
74331 
74332 	DUK_ASSERT(thr != NULL);
74333 	DUK_ASSERT_DISABLE(idx_src >= 0);
74334 	DUK_ASSERT_DISABLE(idx_dst >= 0);
74335 	DUK_ASSERT((duk_uint_t) idx_src < (duk_uint_t) duk_get_top(thr));
74336 	DUK_ASSERT((duk_uint_t) idx_dst < (duk_uint_t) duk_get_top(thr));
74337 
74338 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
74339 
74340 #if defined(DUK_USE_FASTINT)
74341 	if (DUK_TVAL_IS_FASTINT(tv)) {
74342 		i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv);
74343 	}
74344 	else
74345 #endif  /* DUK_USE_FASTINT */
74346 	{
74347 		duk_push_tval(thr, tv);
74348 		i1 = duk_to_int32(thr, -1);  /* side effects */
74349 		duk_pop_unsafe(thr);
74350 	}
74351 
74352 	/* Result is always fastint compatible. */
74353 	i2 = ~i1;
74354 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
74355 	DUK_TVAL_SET_I32_UPDREF(thr, tv, i2);  /* side effects */
74356 }
74357 
74358 DUK_LOCAL DUK__INLINE_PERF void duk__vm_logical_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst) {
74359 	/*
74360 	 *  E5 Section 11.4.9
74361 	 */
74362 
74363 	duk_tval *tv;
74364 	duk_bool_t res;
74365 
74366 	DUK_ASSERT(thr != NULL);
74367 	DUK_ASSERT_DISABLE(idx_src >= 0);
74368 	DUK_ASSERT_DISABLE(idx_dst >= 0);
74369 	DUK_ASSERT((duk_uint_t) idx_src < (duk_uint_t) duk_get_top(thr));
74370 	DUK_ASSERT((duk_uint_t) idx_dst < (duk_uint_t) duk_get_top(thr));
74371 
74372 	/* ToBoolean() does not require any operations with side effects so
74373 	 * we can do it efficiently.  For footprint it would be better to use
74374 	 * duk_js_toboolean() and then push+replace to the result slot.
74375 	 */
74376 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
74377 	res = duk_js_toboolean(tv);  /* does not modify 'tv' */
74378 	DUK_ASSERT(res == 0 || res == 1);
74379 	res ^= 1;
74380 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
74381 	/* XXX: size optimize: push+replace? */
74382 	DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, res);  /* side effects */
74383 }
74384 
74385 /* XXX: size optimized variant */
74386 DUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_reg_helper(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_small_uint_t op) {
74387 	duk_double_t x, y, z;
74388 
74389 	/* Two lowest bits of opcode are used to distinguish
74390 	 * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
74391 	 */
74392 	DUK_ASSERT((DUK_OP_PREINCR & 0x03) == 0x00);
74393 	DUK_ASSERT((DUK_OP_PREDECR & 0x03) == 0x01);
74394 	DUK_ASSERT((DUK_OP_POSTINCR & 0x03) == 0x02);
74395 	DUK_ASSERT((DUK_OP_POSTDECR & 0x03) == 0x03);
74396 
74397 #if defined(DUK_USE_FASTINT)
74398 	if (DUK_TVAL_IS_FASTINT(tv_src)) {
74399 		duk_int64_t x_fi, y_fi, z_fi;
74400 		x_fi = DUK_TVAL_GET_FASTINT(tv_src);
74401 		if (op & 0x01) {
74402 			if (DUK_UNLIKELY(x_fi == DUK_FASTINT_MIN)) {
74403 				goto skip_fastint;
74404 			}
74405 			y_fi = x_fi - 1;
74406 		} else {
74407 			if (DUK_UNLIKELY(x_fi == DUK_FASTINT_MAX)) {
74408 				goto skip_fastint;
74409 			}
74410 			y_fi = x_fi + 1;
74411 		}
74412 
74413 		DUK_TVAL_SET_FASTINT(tv_src, y_fi);  /* no need for refcount update */
74414 
74415 		z_fi = (op & 0x02) ? x_fi : y_fi;
74416 		DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_dst, z_fi);  /* side effects */
74417 		return;
74418 	}
74419  skip_fastint:
74420 #endif
74421 	if (DUK_TVAL_IS_NUMBER(tv_src)) {
74422 		/* Fast path for the case where the register
74423 		 * is a number (e.g. loop counter).
74424 		 */
74425 
74426 		x = DUK_TVAL_GET_NUMBER(tv_src);
74427 		if (op & 0x01) {
74428 			y = x - 1.0;
74429 		} else {
74430 			y = x + 1.0;
74431 		}
74432 
74433 		DUK_TVAL_SET_NUMBER(tv_src, y);  /* no need for refcount update */
74434 	} else {
74435 		/* Preserve duk_tval pointer(s) across a potential valstack
74436 		 * resize by converting them into offsets temporarily.
74437 		 */
74438 		duk_idx_t bc;
74439 		duk_size_t off_dst;
74440 
74441 		off_dst = (duk_size_t) ((duk_uint8_t *) tv_dst - (duk_uint8_t *) thr->valstack_bottom);
74442 		bc = (duk_idx_t) (tv_src - thr->valstack_bottom);  /* XXX: pass index explicitly? */
74443 		tv_src = NULL;  /* no longer referenced */
74444 
74445 		x = duk_to_number(thr, bc);
74446 		if (op & 0x01) {
74447 			y = x - 1.0;
74448 		} else {
74449 			y = x + 1.0;
74450 		}
74451 
74452 		duk_push_number(thr, y);
74453 		duk_replace(thr, bc);
74454 
74455 		tv_dst = (duk_tval *) (void *) (((duk_uint8_t *) thr->valstack_bottom) + off_dst);
74456 	}
74457 
74458 	z = (op & 0x02) ? x : y;
74459 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z);  /* side effects */
74460 }
74461 
74462 DUK_LOCAL DUK__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) {
74463 	duk_activation *act;
74464 	duk_double_t x, y;
74465 	duk_hstring *name;
74466 
74467 	/* XXX: The pre/post inc/dec for an identifier lookup is
74468 	 * missing the important fast path where the identifier
74469 	 * has a storage location e.g. in a scope object so that
74470 	 * it can be updated in-place.  In particular, the case
74471 	 * where the identifier has a storage location AND the
74472 	 * previous value is a number should be optimized because
74473 	 * it's side effect free.
74474 	 */
74475 
74476 	/* Two lowest bits of opcode are used to distinguish
74477 	 * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
74478 	 */
74479 	DUK_ASSERT((DUK_OP_PREINCV & 0x03) == 0x00);
74480 	DUK_ASSERT((DUK_OP_PREDECV & 0x03) == 0x01);
74481 	DUK_ASSERT((DUK_OP_POSTINCV & 0x03) == 0x02);
74482 	DUK_ASSERT((DUK_OP_POSTDECV & 0x03) == 0x03);
74483 
74484 	DUK_ASSERT(DUK_TVAL_IS_STRING(tv_id));
74485 	name = DUK_TVAL_GET_STRING(tv_id);
74486 	DUK_ASSERT(name != NULL);
74487 	act = thr->callstack_curr;
74488 	(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [ ... val this ] */
74489 
74490 	/* XXX: Fastint fast path would be useful here.  Also fastints
74491 	 * now lose their fastint status in current handling which is
74492 	 * not intuitive.
74493 	 */
74494 
74495 	x = duk_to_number_m2(thr);
74496 	if (op & 0x01) {
74497 		y = x - 1.0;
74498 	} else {
74499 		y = x + 1.0;
74500 	}
74501 
74502 	/* [... x this] */
74503 
74504 	if (op & 0x02) {
74505 		duk_push_number(thr, y);  /* -> [ ... x this y ] */
74506 		DUK_ASSERT(act == thr->callstack_curr);
74507 		duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(thr, -1), is_strict);
74508 		duk_pop_2_unsafe(thr);  /* -> [ ... x ] */
74509 	} else {
74510 		duk_pop_2_unsafe(thr);  /* -> [ ... ] */
74511 		duk_push_number(thr, y);  /* -> [ ... y ] */
74512 		DUK_ASSERT(act == thr->callstack_curr);
74513 		duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(thr, -1), is_strict);
74514 	}
74515 
74516 #if defined(DUK_USE_EXEC_PREFER_SIZE)
74517 	duk_replace(thr, (duk_idx_t) idx_dst);
74518 #else  /* DUK_USE_EXEC_PREFER_SIZE */
74519 	DUK__REPLACE_TO_TVPTR(thr, DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst));
74520 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
74521 }
74522 
74523 /*
74524  *  Longjmp and other control flow transfer for the bytecode executor.
74525  *
74526  *  The longjmp handler can handle all longjmp types: error, yield, and
74527  *  resume (pseudotypes are never actually thrown).
74528  *
74529  *  Error policy for longjmp: should not ordinarily throw errors; if errors
74530  *  occur (e.g. due to out-of-memory) they bubble outwards rather than being
74531  *  handled recursively.
74532  */
74533 
74534 #define DUK__LONGJMP_RESTART   0  /* state updated, restart bytecode execution */
74535 #define DUK__LONGJMP_RETHROW   1  /* exit bytecode executor by rethrowing an error to caller */
74536 
74537 #define DUK__RETHAND_RESTART   0  /* state updated, restart bytecode execution */
74538 #define DUK__RETHAND_FINISHED  1  /* exit bytecode execution with return value */
74539 
74540 /* XXX: optimize reconfig valstack operations so that resize, clamp, and setting
74541  * top are combined into one pass.
74542  */
74543 
74544 /* Reconfigure value stack for return to an ECMAScript function at
74545  * callstack top (caller unwinds).
74546  */
74547 DUK_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr) {
74548 	duk_activation *act;
74549 	duk_hcompfunc *h_func;
74550 	duk_idx_t clamp_top;
74551 
74552 	DUK_ASSERT(thr != NULL);
74553 	act = thr->callstack_curr;
74554 	DUK_ASSERT(act != NULL);
74555 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
74556 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act)));
74557 
74558 	/* Clamp so that values at 'clamp_top' and above are wiped and won't
74559 	 * retain reachable garbage.  Then extend to 'nregs' because we're
74560 	 * returning to an ECMAScript function.
74561 	 */
74562 
74563 	h_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
74564 
74565 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
74566 	DUK_ASSERT(act->retval_byteoff >= act->bottom_byteoff);
74567 	clamp_top = (duk_idx_t) ((act->retval_byteoff - act->bottom_byteoff + sizeof(duk_tval)) / sizeof(duk_tval));  /* +1 = one retval */
74568 	duk_set_top_and_wipe(thr, h_func->nregs, clamp_top);
74569 
74570 	DUK_ASSERT((duk_uint8_t *) thr->valstack_end >= (duk_uint8_t *) thr->valstack + act->reserve_byteoff);
74571 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->reserve_byteoff);
74572 
74573 	/* XXX: a best effort shrink check would be OK here */
74574 }
74575 
74576 /* Reconfigure value stack for an ECMAScript catcher.  Use topmost catcher
74577  * in 'act'.
74578  */
74579 DUK_LOCAL void duk__reconfig_valstack_ecma_catcher(duk_hthread *thr, duk_activation *act) {
74580 	duk_catcher *cat;
74581 	duk_hcompfunc *h_func;
74582 	duk_size_t idx_bottom;
74583 	duk_idx_t clamp_top;
74584 
74585 	DUK_ASSERT(thr != NULL);
74586 	DUK_ASSERT(act != NULL);
74587 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
74588 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act)));
74589 	cat = act->cat;
74590 	DUK_ASSERT(cat != NULL);
74591 
74592 	h_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
74593 
74594 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
74595 	idx_bottom = (duk_size_t) (thr->valstack_bottom - thr->valstack);
74596 	DUK_ASSERT(cat->idx_base >= idx_bottom);
74597 	clamp_top = (duk_idx_t) (cat->idx_base - idx_bottom + 2);  /* +2 = catcher value, catcher lj_type */
74598 	duk_set_top_and_wipe(thr, h_func->nregs, clamp_top);
74599 
74600 	DUK_ASSERT((duk_uint8_t *) thr->valstack_end >= (duk_uint8_t *) thr->valstack + act->reserve_byteoff);
74601 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->reserve_byteoff);
74602 
74603 	/* XXX: a best effort shrink check would be OK here */
74604 }
74605 
74606 /* Set catcher regs: idx_base+0 = value, idx_base+1 = lj_type.
74607  * No side effects.
74608  */
74609 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) {
74610 	duk_tval *tv1;
74611 
74612 	DUK_ASSERT(thr != NULL);
74613 	DUK_ASSERT(tv_val_unstable != NULL);
74614 
74615 	tv1 = thr->valstack + cat->idx_base;
74616 	DUK_ASSERT(tv1 < thr->valstack_top);
74617 	DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr, tv1, tv_val_unstable);
74618 
74619 	tv1++;
74620 	DUK_ASSERT(tv1 == thr->valstack + cat->idx_base + 1);
74621 	DUK_ASSERT(tv1 < thr->valstack_top);
74622 	DUK_TVAL_SET_U32_UPDREF_NORZ(thr, tv1, (duk_uint32_t) lj_type);
74623 }
74624 
74625 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) {
74626 	duk_activation *act;
74627 	duk_catcher *cat;
74628 
74629 	DUK_ASSERT(thr != NULL);
74630 	DUK_ASSERT(tv_val_unstable != NULL);
74631 
74632 	act = thr->callstack_curr;
74633 	DUK_ASSERT(act != NULL);
74634 	DUK_DD(DUK_DDPRINT("handle catch, part 1; act=%!A, cat=%!C", act, act->cat));
74635 
74636 	DUK_ASSERT(act->cat != NULL);
74637 	DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);
74638 
74639 	/* The part1/part2 split could also be made here at the very top
74640 	 * of catch handling.  Value stack would be reconfigured inside
74641 	 * part2's protection.  Value stack reconfiguration should be free
74642 	 * of allocs, however.
74643 	 */
74644 
74645 	duk__set_catcher_regs_norz(thr, act->cat, tv_val_unstable, lj_type);
74646 
74647 	DUK_ASSERT(thr->callstack_top >= 1);
74648 	DUK_ASSERT(thr->callstack_curr != NULL);
74649 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
74650 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
74651 
74652 	DUK_ASSERT(thr->callstack_top >= 1);
74653 	DUK_ASSERT(act == thr->callstack_curr);
74654 	DUK_ASSERT(act != NULL);
74655 	duk__reconfig_valstack_ecma_catcher(thr, act);
74656 
74657 	DUK_ASSERT(thr->callstack_top >= 1);
74658 	DUK_ASSERT(act == thr->callstack_curr);
74659 	DUK_ASSERT(act != NULL);
74660 	cat = act->cat;
74661 	DUK_ASSERT(cat != NULL);
74662 
74663 	act->curr_pc = cat->pc_base + 0;  /* +0 = catch */
74664 
74665 	/*
74666 	 *  If the catch block has an automatic catch variable binding,
74667 	 *  we need to create a lexical environment for it which requires
74668 	 *  allocations.  Move out of "error handling state" before the
74669 	 *  allocations to avoid e.g. out-of-memory errors (leading to
74670 	 *  GH-2022 or similar).
74671 	 */
74672 
74673 	if (DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat)) {
74674 		DUK_DDD(DUK_DDDPRINT("catcher has an automatic catch binding, handle in part 2"));
74675 		*out_delayed_catch_setup = 1;
74676 	} else {
74677 		DUK_DDD(DUK_DDDPRINT("catcher has no catch binding"));
74678 	}
74679 
74680 	DUK_CAT_CLEAR_CATCH_ENABLED(cat);
74681 }
74682 
74683 DUK_LOCAL void duk__handle_catch_part2(duk_hthread *thr) {
74684 	duk_activation *act;
74685 	duk_catcher *cat;
74686 	duk_hdecenv *new_env;
74687 
74688 	DUK_ASSERT(thr != NULL);
74689 
74690 	act = thr->callstack_curr;
74691 	DUK_ASSERT(act != NULL);
74692 	DUK_DD(DUK_DDPRINT("handle catch, part 2; act=%!A, cat=%!C", act, act->cat));
74693 
74694 	DUK_ASSERT(act->cat != NULL);
74695 	cat = act->cat;
74696 	DUK_ASSERT(cat != NULL);
74697 	DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
74698 	DUK_ASSERT(DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat));
74699 	DUK_ASSERT(thr->valstack + cat->idx_base < thr->valstack_top);
74700 
74701 	/*
74702 	 *  Create lexical environment for the catch clause, containing
74703 	 *  a binding for the caught value.
74704 	 *
74705 	 *  The binding is mutable (= writable) but not deletable.
74706 	 *  Step 4 for the catch production in E5 Section 12.14;
74707 	 *  no value is given for CreateMutableBinding 'D' argument,
74708 	 *  which implies the binding is not deletable.
74709 	 */
74710 
74711 	if (act->lex_env == NULL) {
74712 		DUK_ASSERT(act->var_env == NULL);
74713 		DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
74714 
74715 		duk_js_init_activation_environment_records_delayed(thr, act);
74716 		DUK_ASSERT(act == thr->callstack_curr);
74717 		DUK_ASSERT(act != NULL);
74718 	}
74719 	DUK_ASSERT(act->lex_env != NULL);
74720 	DUK_ASSERT(act->var_env != NULL);
74721 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
74722 
74723 	new_env = duk_hdecenv_alloc(thr,
74724 	                            DUK_HOBJECT_FLAG_EXTENSIBLE |
74725 	                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
74726 	DUK_ASSERT(new_env != NULL);
74727 	duk_push_hobject(thr, (duk_hobject *) new_env);
74728 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
74729 	DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
74730 
74731 	/* Note: currently the catch binding is handled without a register
74732 	 * binding because we don't support dynamic register bindings (they
74733 	 * must be fixed for an entire function).  So, there is no need to
74734 	 * record regbases etc.
74735 	 */
74736 
74737 	/* [ ...env ] */
74738 
74739 	DUK_ASSERT(cat->h_varname != NULL);
74740 	duk_push_hstring(thr, cat->h_varname);
74741 	DUK_ASSERT(thr->valstack + cat->idx_base < thr->valstack_top);
74742 	duk_push_tval(thr, thr->valstack + cat->idx_base);
74743 	duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_W);  /* writable, not configurable */
74744 
74745 	/* [ ... env ] */
74746 
74747 	DUK_ASSERT(act == thr->callstack_curr);
74748 	DUK_ASSERT(act != NULL);
74749 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, act->lex_env);
74750 	act->lex_env = (duk_hobject *) new_env;
74751 	DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);  /* reachable through activation */
74752 	/* Net refcount change to act->lex_env is 0: incref for new_env's
74753 	 * prototype, decref for act->lex_env overwrite.
74754 	 */
74755 
74756 	DUK_CAT_SET_LEXENV_ACTIVE(cat);
74757 
74758 	duk_pop_unsafe(thr);
74759 
74760 	DUK_DDD(DUK_DDDPRINT("new_env finished: %!iO", (duk_heaphdr *) new_env));
74761 }
74762 
74763 DUK_LOCAL void duk__handle_finally(duk_hthread *thr, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
74764 	duk_activation *act;
74765 	duk_catcher *cat;
74766 
74767 	DUK_ASSERT(thr != NULL);
74768 	DUK_ASSERT(tv_val_unstable != NULL);
74769 
74770 	act = thr->callstack_curr;
74771 	DUK_ASSERT(act != NULL);
74772 	DUK_ASSERT(act->cat != NULL);
74773 	DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);
74774 
74775 	duk__set_catcher_regs_norz(thr, act->cat, tv_val_unstable, lj_type);
74776 
74777 	DUK_ASSERT(thr->callstack_top >= 1);
74778 	DUK_ASSERT(thr->callstack_curr != NULL);
74779 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
74780 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
74781 
74782 	DUK_ASSERT(thr->callstack_top >= 1);
74783 	DUK_ASSERT(act == thr->callstack_curr);
74784 	DUK_ASSERT(act != NULL);
74785 	duk__reconfig_valstack_ecma_catcher(thr, act);
74786 
74787 	DUK_ASSERT(thr->callstack_top >= 1);
74788 	DUK_ASSERT(act == thr->callstack_curr);
74789 	DUK_ASSERT(act != NULL);
74790 	cat = act->cat;
74791 	DUK_ASSERT(cat != NULL);
74792 
74793 	act->curr_pc = cat->pc_base + 1;  /* +1 = finally */
74794 
74795 	DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
74796 }
74797 
74798 DUK_LOCAL void duk__handle_label(duk_hthread *thr, duk_small_uint_t lj_type) {
74799 	duk_activation *act;
74800 	duk_catcher *cat;
74801 
74802 	DUK_ASSERT(thr != NULL);
74803 
74804 	DUK_ASSERT(thr->callstack_top >= 1);
74805 	act = thr->callstack_curr;
74806 	DUK_ASSERT(act != NULL);
74807 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
74808 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(DUK_ACT_GET_FUNC(act)));
74809 
74810 	/* +0 = break, +1 = continue */
74811 	cat = act->cat;
74812 	DUK_ASSERT(cat != NULL);
74813 	DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL);
74814 
74815 	act->curr_pc = cat->pc_base + (lj_type == DUK_LJ_TYPE_CONTINUE ? 1 : 0);
74816 
74817 	/* valstack should not need changes */
74818 #if defined(DUK_USE_ASSERTIONS)
74819 	DUK_ASSERT(thr->callstack_top >= 1);
74820 	DUK_ASSERT(act == thr->callstack_curr);
74821 	DUK_ASSERT(act != NULL);
74822 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) ==
74823 	           (duk_size_t) ((duk_hcompfunc *) DUK_ACT_GET_FUNC(act))->nregs);
74824 #endif
74825 }
74826 
74827 /* Called for handling both a longjmp() with type DUK_LJ_TYPE_YIELD and
74828  * when a RETURN opcode terminates a thread and yields to the resumer.
74829  * Caller unwinds so that top of callstack is the activation we return to.
74830  */
74831 #if defined(DUK_USE_COROUTINE_SUPPORT)
74832 DUK_LOCAL void duk__handle_yield(duk_hthread *thr, duk_hthread *resumer, duk_tval *tv_val_unstable) {
74833 	duk_activation *act_resumer;
74834 	duk_tval *tv1;
74835 
74836 	DUK_ASSERT(thr != NULL);
74837 	DUK_ASSERT(resumer != NULL);
74838 	DUK_ASSERT(tv_val_unstable != NULL);
74839 	act_resumer = resumer->callstack_curr;
74840 	DUK_ASSERT(act_resumer != NULL);
74841 	DUK_ASSERT(DUK_ACT_GET_FUNC(act_resumer) != NULL);
74842 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act_resumer)));  /* resume caller must be an ECMAScript func */
74843 
74844 	tv1 = (duk_tval *) (void *) ((duk_uint8_t *) resumer->valstack + act_resumer->retval_byteoff);  /* return value from Duktape.Thread.resume() */
74845 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable);  /* side effects */  /* XXX: avoid side effects */
74846 
74847 	duk__reconfig_valstack_ecma_return(resumer);
74848 
74849 	/* caller must change active thread, and set thr->resumer to NULL */
74850 }
74851 #endif  /* DUK_USE_COROUTINE_SUPPORT */
74852 
74853 DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation *entry_act, volatile duk_bool_t *out_delayed_catch_setup) {
74854 	duk_small_uint_t retval = DUK__LONGJMP_RESTART;
74855 
74856 	DUK_ASSERT(thr != NULL);
74857 	DUK_ASSERT(entry_act != NULL);
74858 
74859 	/* 'thr' is the current thread, as no-one resumes except us and we
74860 	 * switch 'thr' in that case.
74861 	 */
74862 	DUK_ASSERT(thr == thr->heap->curr_thread);
74863 
74864 	/*
74865 	 *  (Re)try handling the longjmp.
74866 	 *
74867 	 *  A longjmp handler may convert the longjmp to a different type and
74868 	 *  "virtually" rethrow by goto'ing to 'check_longjmp'.  Before the goto,
74869 	 *  the following must be updated:
74870 	 *    - the heap 'lj' state
74871 	 *    - 'thr' must reflect the "throwing" thread
74872 	 */
74873 
74874  check_longjmp:
74875 
74876 	DUK_DD(DUK_DDPRINT("handling longjmp: type=%ld, value1=%!T, value2=%!T, iserror=%ld, top=%ld",
74877 	                   (long) thr->heap->lj.type,
74878 	                   (duk_tval *) &thr->heap->lj.value1,
74879 	                   (duk_tval *) &thr->heap->lj.value2,
74880 	                   (long) thr->heap->lj.iserror,
74881 			   (long) duk_get_top(thr)));
74882 
74883 	switch (thr->heap->lj.type) {
74884 
74885 #if defined(DUK_USE_COROUTINE_SUPPORT)
74886 	case DUK_LJ_TYPE_RESUME: {
74887 		/*
74888 		 *  Note: lj.value1 is 'value', lj.value2 is 'resumee'.
74889 		 *  This differs from YIELD.
74890 		 */
74891 
74892 		duk_tval *tv;
74893 		duk_tval *tv2;
74894 		duk_hthread *resumee;
74895 
74896 		/* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
74897 
74898 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);                                                         /* unchanged by Duktape.Thread.resume() */
74899 		DUK_ASSERT(thr->callstack_top >= 2);                                                                         /* ECMAScript activation + Duktape.Thread.resume() activation */
74900 		DUK_ASSERT(thr->callstack_curr != NULL);
74901 		DUK_ASSERT(thr->callstack_curr->parent != NULL);
74902 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL &&
74903 		           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)) &&
74904 		           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack_curr))->func == duk_bi_thread_resume);
74905 
74906 		tv = &thr->heap->lj.value2;  /* resumee */
74907 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
74908 		DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv) != NULL);
74909 		DUK_ASSERT(DUK_HOBJECT_IS_THREAD(DUK_TVAL_GET_OBJECT(tv)));
74910 		resumee = (duk_hthread *) DUK_TVAL_GET_OBJECT(tv);
74911 
74912 		DUK_ASSERT(resumee != NULL);
74913 		DUK_ASSERT(resumee->resumer == NULL);
74914 		DUK_ASSERT(resumee->state == DUK_HTHREAD_STATE_INACTIVE ||
74915 		           resumee->state == DUK_HTHREAD_STATE_YIELDED);                                                     /* checked by Duktape.Thread.resume() */
74916 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
74917 		           resumee->callstack_top >= 2);                                                                     /* YIELDED: ECMAScript activation + Duktape.Thread.yield() activation */
74918 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
74919 		           (DUK_ACT_GET_FUNC(resumee->callstack_curr) != NULL &&
74920 		            DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumee->callstack_curr)) &&
74921 		            ((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumee->callstack_curr))->func == duk_bi_thread_yield));
74922 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_INACTIVE ||
74923 		           resumee->callstack_top == 0);                                                                     /* INACTIVE: no activation, single function value on valstack */
74924 
74925 		if (thr->heap->lj.iserror) {
74926 			/*
74927 			 *  Throw the error in the resumed thread's context; the
74928 			 *  error value is pushed onto the resumee valstack.
74929 			 *
74930 			 *  Note: the callstack of the target may empty in this case
74931 			 *  too (i.e. the target thread has never been resumed).  The
74932 			 *  value stack will contain the initial function in that case,
74933 			 *  which we simply ignore.
74934 			 */
74935 
74936 			DUK_ASSERT(resumee->resumer == NULL);
74937 			resumee->resumer = thr;
74938 			DUK_HTHREAD_INCREF(thr, thr);
74939 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
74940 			thr->state = DUK_HTHREAD_STATE_RESUMED;
74941 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
74942 			thr = resumee;
74943 
74944 			thr->heap->lj.type = DUK_LJ_TYPE_THROW;
74945 
74946 			/* thr->heap->lj.value1 is already the value to throw */
74947 			/* thr->heap->lj.value2 is 'thread', will be wiped out at the end */
74948 
74949 			DUK_ASSERT(thr->heap->lj.iserror);  /* already set */
74950 
74951 			DUK_DD(DUK_DDPRINT("-> resume with an error, converted to a throw in the resumee, propagate"));
74952 			goto check_longjmp;
74953 		} else if (resumee->state == DUK_HTHREAD_STATE_YIELDED) {
74954 			/* Unwind previous Duktape.Thread.yield() call.  The
74955 			 * activation remaining must always be an ECMAScript
74956 			 * call now (yield() accepts calls from ECMAScript
74957 			 * only).
74958 			 */
74959 			duk_activation *act_resumee;
74960 
74961 			DUK_ASSERT(resumee->callstack_top >= 2);
74962 			act_resumee = resumee->callstack_curr;  /* Duktape.Thread.yield() */
74963 			DUK_ASSERT(act_resumee != NULL);
74964 			act_resumee = act_resumee->parent;      /* ECMAScript call site for yield() */
74965 			DUK_ASSERT(act_resumee != NULL);
74966 
74967 			tv = (duk_tval *) (void *) ((duk_uint8_t *) resumee->valstack + act_resumee->retval_byteoff);  /* return value from Duktape.Thread.yield() */
74968 			DUK_ASSERT(tv >= resumee->valstack && tv < resumee->valstack_top);
74969 			tv2 = &thr->heap->lj.value1;
74970 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv2);  /* side effects */  /* XXX: avoid side effects */
74971 
74972 			duk_hthread_activation_unwind_norz(resumee);  /* unwind to 'yield' caller */
74973 			/* no need to unwind catch stack */
74974 
74975 			duk__reconfig_valstack_ecma_return(resumee);
74976 
74977 			DUK_ASSERT(resumee->resumer == NULL);
74978 			resumee->resumer = thr;
74979 			DUK_HTHREAD_INCREF(thr, thr);
74980 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
74981 			thr->state = DUK_HTHREAD_STATE_RESUMED;
74982 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
74983 #if 0
74984 			thr = resumee;  /* not needed, as we exit right away */
74985 #endif
74986 			DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
74987 			retval = DUK__LONGJMP_RESTART;
74988 			goto wipe_and_return;
74989 		} else {
74990 			/* Initial resume call. */
74991 			duk_small_uint_t call_flags;
74992 			duk_int_t setup_rc;
74993 
74994 			/* resumee: [... initial_func]  (currently actually: [initial_func]) */
74995 
74996 			duk_push_undefined(resumee);
74997 			tv = &thr->heap->lj.value1;
74998 			duk_push_tval(resumee, tv);
74999 
75000 			/* resumee: [... initial_func undefined(= this) resume_value ] */
75001 
75002 			call_flags = DUK_CALL_FLAG_ALLOW_ECMATOECMA;  /* not tailcall, ecma-to-ecma (assumed to succeed) */
75003 
75004 			setup_rc = duk_handle_call_unprotected_nargs(resumee, 1 /*nargs*/, call_flags);
75005 			if (setup_rc == 0) {
75006 				/* This shouldn't happen; Duktape.Thread.resume()
75007 				 * should make sure of that.  If it does happen
75008 				 * this internal error will propagate out of the
75009 				 * executor which can be quite misleading.
75010 				 */
75011 				DUK_ERROR_INTERNAL(thr);
75012 				DUK_WO_NORETURN(return 0;);
75013 			}
75014 
75015 			DUK_ASSERT(resumee->resumer == NULL);
75016 			resumee->resumer = thr;
75017 			DUK_HTHREAD_INCREF(thr, thr);
75018 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
75019 			thr->state = DUK_HTHREAD_STATE_RESUMED;
75020 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
75021 #if 0
75022 			thr = resumee;  /* not needed, as we exit right away */
75023 #endif
75024 			DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
75025 			retval = DUK__LONGJMP_RESTART;
75026 			goto wipe_and_return;
75027 		}
75028 		DUK_UNREACHABLE();
75029 		break;  /* never here */
75030 	}
75031 
75032 	case DUK_LJ_TYPE_YIELD: {
75033 		/*
75034 		 *  Currently only allowed only if yielding thread has only
75035 		 *  ECMAScript activations (except for the Duktape.Thread.yield()
75036 		 *  call at the callstack top) and none of them constructor
75037 		 *  calls.
75038 		 *
75039 		 *  This excludes the 'entry' thread which will always have
75040 		 *  a preventcount > 0.
75041 		 */
75042 
75043 		duk_hthread *resumer;
75044 
75045 		/* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
75046 
75047 #if 0  /* entry_thread not available for assert */
75048 		DUK_ASSERT(thr != entry_thread);                                                                             /* Duktape.Thread.yield() should prevent */
75049 #endif
75050 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);                                                         /* unchanged from Duktape.Thread.yield() */
75051 		DUK_ASSERT(thr->callstack_top >= 2);                                                                         /* ECMAScript activation + Duktape.Thread.yield() activation */
75052 		DUK_ASSERT(thr->callstack_curr != NULL);
75053 		DUK_ASSERT(thr->callstack_curr->parent != NULL);
75054 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL &&
75055 		           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)) &&
75056 		           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack_curr))->func == duk_bi_thread_yield);
75057 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL &&
75058 		           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent)));                              /* an ECMAScript function */
75059 
75060 		resumer = thr->resumer;
75061 
75062 		DUK_ASSERT(resumer != NULL);
75063 		DUK_ASSERT(resumer->state == DUK_HTHREAD_STATE_RESUMED);                                                     /* written by a previous RESUME handling */
75064 		DUK_ASSERT(resumer->callstack_top >= 2);                                                                     /* ECMAScript activation + Duktape.Thread.resume() activation */
75065 		DUK_ASSERT(resumer->callstack_curr != NULL);
75066 		DUK_ASSERT(resumer->callstack_curr->parent != NULL);
75067 		DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr) != NULL &&
75068 		           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr)) &&
75069 		           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumer->callstack_curr))->func == duk_bi_thread_resume);
75070 		DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent) != NULL &&
75071 		           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent)));                            /* an ECMAScript function */
75072 
75073 		if (thr->heap->lj.iserror) {
75074 			thr->state = DUK_HTHREAD_STATE_YIELDED;
75075 			thr->resumer = NULL;
75076 			DUK_HTHREAD_DECREF_NORZ(thr, resumer);
75077 			resumer->state = DUK_HTHREAD_STATE_RUNNING;
75078 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
75079 			thr = resumer;
75080 
75081 			thr->heap->lj.type = DUK_LJ_TYPE_THROW;
75082 			/* lj.value1 is already set */
75083 			DUK_ASSERT(thr->heap->lj.iserror);  /* already set */
75084 
75085 			DUK_DD(DUK_DDPRINT("-> yield an error, converted to a throw in the resumer, propagate"));
75086 			goto check_longjmp;
75087 		} else {
75088 			duk_hthread_activation_unwind_norz(resumer);
75089 			duk__handle_yield(thr, resumer, &thr->heap->lj.value1);
75090 
75091 			thr->state = DUK_HTHREAD_STATE_YIELDED;
75092 			thr->resumer = NULL;
75093 			DUK_HTHREAD_DECREF_NORZ(thr, resumer);
75094 			resumer->state = DUK_HTHREAD_STATE_RUNNING;
75095 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
75096 #if 0
75097 			thr = resumer;  /* not needed, as we exit right away */
75098 #endif
75099 
75100 			DUK_DD(DUK_DDPRINT("-> yield a value, restart execution in resumer"));
75101 			retval = DUK__LONGJMP_RESTART;
75102 			goto wipe_and_return;
75103 		}
75104 		DUK_UNREACHABLE();
75105 		break;  /* never here */
75106 	}
75107 #endif  /* DUK_USE_COROUTINE_SUPPORT */
75108 
75109 	case DUK_LJ_TYPE_THROW: {
75110 		/*
75111 		 *  Three possible outcomes:
75112 		 *    * A try or finally catcher is found => resume there.
75113 		 *      (or)
75114 		 *    * The error propagates to the bytecode executor entry
75115 		 *      level (and we're in the entry thread) => rethrow
75116 		 *      with a new longjmp(), after restoring the previous
75117 		 *      catchpoint.
75118 		 *    * The error is not caught in the current thread, so
75119 		 *      the thread finishes with an error.  This works like
75120 		 *      a yielded error, except that the thread is finished
75121 		 *      and can no longer be resumed.  (There is always a
75122 		 *      resumer in this case.)
75123 		 *
75124 		 *  Note: until we hit the entry level, there can only be
75125 		 *  ECMAScript activations.
75126 		 */
75127 
75128 		duk_activation *act;
75129 		duk_catcher *cat;
75130 		duk_hthread *resumer;
75131 
75132 		for (;;) {
75133 			act = thr->callstack_curr;
75134 			if (act == NULL) {
75135 				break;
75136 			}
75137 
75138 			for (;;) {
75139 				cat = act->cat;
75140 				if (cat == NULL) {
75141 					break;
75142 				}
75143 
75144 				if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
75145 					DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
75146 
75147 					DUK_DDD(DUK_DDDPRINT("before catch part 1: thr=%p, act=%p, cat=%p",
75148 					                     (void *) thr, (void *) act, (void *) act->cat));
75149 					duk__handle_catch_part1(thr,
75150 					                        &thr->heap->lj.value1,
75151 					                        DUK_LJ_TYPE_THROW,
75152 							        out_delayed_catch_setup);
75153 
75154 					DUK_DD(DUK_DDPRINT("-> throw caught by a 'catch' clause, restart execution"));
75155 					retval = DUK__LONGJMP_RESTART;
75156 					goto wipe_and_return;
75157 				}
75158 
75159 				if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
75160 					DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
75161 					DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));
75162 
75163 					duk__handle_finally(thr,
75164 					                    &thr->heap->lj.value1,
75165 					                    DUK_LJ_TYPE_THROW);
75166 
75167 					DUK_DD(DUK_DDPRINT("-> throw caught by a 'finally' clause, restart execution"));
75168 					retval = DUK__LONGJMP_RESTART;
75169 					goto wipe_and_return;
75170 				}
75171 
75172 				duk_hthread_catcher_unwind_norz(thr, act);
75173 			}
75174 
75175 			if (act == entry_act) {
75176 				/* Not caught by anything before entry level; rethrow and let the
75177 				 * final catcher finish unwinding (esp. value stack).
75178 				 */
75179 				DUK_D(DUK_DPRINT("-> throw propagated up to entry level, rethrow and exit bytecode executor"));
75180 				retval = DUK__LONGJMP_RETHROW;
75181 				goto just_return;
75182 			}
75183 
75184 			duk_hthread_activation_unwind_norz(thr);
75185 		}
75186 
75187 		DUK_DD(DUK_DDPRINT("-> throw not caught by current thread, yield error to resumer and recheck longjmp"));
75188 
75189 		/* Not caught by current thread, thread terminates (yield error to resumer);
75190 		 * note that this may cause a cascade if the resumer terminates with an uncaught
75191 		 * exception etc (this is OK, but needs careful testing).
75192 		 */
75193 
75194 		DUK_ASSERT(thr->resumer != NULL);
75195 		DUK_ASSERT(thr->resumer->callstack_top >= 2);  /* ECMAScript activation + Duktape.Thread.resume() activation */
75196 		DUK_ASSERT(thr->resumer->callstack_curr != NULL);
75197 		DUK_ASSERT(thr->resumer->callstack_curr->parent != NULL);
75198 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL &&
75199 		           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent)));  /* an ECMAScript function */
75200 
75201 		resumer = thr->resumer;
75202 
75203 		/* reset longjmp */
75204 
75205 		DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);  /* already set */
75206 		/* lj.value1 already set */
75207 
75208 		duk_hthread_terminate(thr);  /* updates thread state, minimizes its allocations */
75209 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
75210 
75211 		thr->resumer = NULL;
75212 		DUK_HTHREAD_DECREF_NORZ(thr, resumer);
75213 		resumer->state = DUK_HTHREAD_STATE_RUNNING;
75214 		DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
75215 		thr = resumer;
75216 		goto check_longjmp;
75217 	}
75218 
75219 	case DUK_LJ_TYPE_BREAK:  /* pseudotypes, not used in actual longjmps */
75220 	case DUK_LJ_TYPE_CONTINUE:
75221 	case DUK_LJ_TYPE_RETURN:
75222 	case DUK_LJ_TYPE_NORMAL:
75223 	default: {
75224 		/* should never happen, but be robust */
75225 		DUK_D(DUK_DPRINT("caught unknown longjmp type %ld, treat as internal error", (long) thr->heap->lj.type));
75226 		goto convert_to_internal_error;
75227 	}
75228 
75229 	}  /* end switch */
75230 
75231 	DUK_UNREACHABLE();
75232 
75233  wipe_and_return:
75234 	DUK_DD(DUK_DDPRINT("handling longjmp done, wipe-and-return, top=%ld",
75235 	                   (long) duk_get_top(thr)));
75236 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
75237 	thr->heap->lj.iserror = 0;
75238 
75239 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1);  /* side effects */
75240 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2);  /* side effects */
75241 
75242 	DUK_GC_TORTURE(thr->heap);
75243 
75244  just_return:
75245 	return retval;
75246 
75247  convert_to_internal_error:
75248 	/* This could also be thrown internally (set the error, goto check_longjmp),
75249 	 * but it's better for internal errors to bubble outwards so that we won't
75250 	 * infinite loop in this catchpoint.
75251 	 */
75252 	DUK_ERROR_INTERNAL(thr);
75253 	DUK_WO_NORETURN(return 0;);
75254 }
75255 
75256 /* Handle a BREAK/CONTINUE opcode.  Avoid using longjmp() for BREAK/CONTINUE
75257  * handling because it has a measurable performance impact in ordinary
75258  * environments and an extreme impact in Emscripten (GH-342).
75259  */
75260 DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_break_or_continue(duk_hthread *thr,
75261                                                                 duk_uint_t label_id,
75262                                                                 duk_small_uint_t lj_type) {
75263 	duk_activation *act;
75264 	duk_catcher *cat;
75265 
75266 	DUK_ASSERT(thr != NULL);
75267 
75268 	/* Find a matching label catcher or 'finally' catcher in
75269 	 * the same function, unwinding catchers as we go.
75270 	 *
75271 	 * A label catcher must always exist and will match unless
75272 	 * a 'finally' captures the break/continue first.  It is the
75273 	 * compiler's responsibility to ensure that labels are used
75274 	 * correctly.
75275 	 */
75276 
75277 	act = thr->callstack_curr;
75278 	DUK_ASSERT(act != NULL);
75279 
75280 	for (;;) {
75281 		cat = act->cat;
75282 		if (cat == NULL) {
75283 			break;
75284 		}
75285 
75286 		DUK_DDD(DUK_DDDPRINT("considering catcher %p: type=%ld label=%ld",
75287 		                     (void *) cat,
75288 		                     (long) DUK_CAT_GET_TYPE(cat),
75289 		                     (long) DUK_CAT_GET_LABEL(cat)));
75290 
75291 		/* XXX: bit mask test; FINALLY <-> TCF, single bit mask would suffice? */
75292 
75293 		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
75294 		    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
75295 			duk_tval tv_tmp;
75296 
75297 			DUK_TVAL_SET_U32(&tv_tmp, (duk_uint32_t) label_id);
75298 			duk__handle_finally(thr, &tv_tmp, lj_type);
75299 
75300 			DUK_DD(DUK_DDPRINT("-> break/continue caught by 'finally', restart execution"));
75301 			return;
75302 		}
75303 		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL &&
75304 		    (duk_uint_t) DUK_CAT_GET_LABEL(cat) == label_id) {
75305 			duk__handle_label(thr, lj_type);
75306 
75307 			DUK_DD(DUK_DDPRINT("-> break/continue caught by a label catcher (in the same function), restart execution"));
75308 			return;
75309 		}
75310 
75311 		duk_hthread_catcher_unwind_norz(thr, act);
75312 	}
75313 
75314 	/* Should never happen, but be robust. */
75315 	DUK_D(DUK_DPRINT("-> break/continue not caught by anything in the current function (should never happen), throw internal error"));
75316 	DUK_ERROR_INTERNAL(thr);
75317 	DUK_WO_NORETURN(return;);
75318 }
75319 
75320 /* Handle a RETURN opcode.  Avoid using longjmp() for return handling because
75321  * it has a measurable performance impact in ordinary environments and an extreme
75322  * impact in Emscripten (GH-342).  Return value is on value stack top.
75323  */
75324 DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation *entry_act) {
75325 	duk_tval *tv1;
75326 	duk_tval *tv2;
75327 #if defined(DUK_USE_COROUTINE_SUPPORT)
75328 	duk_hthread *resumer;
75329 #endif
75330 	duk_activation *act;
75331 	duk_catcher *cat;
75332 
75333 	/* We can directly access value stack here. */
75334 
75335 	DUK_ASSERT(thr != NULL);
75336 	DUK_ASSERT(entry_act != NULL);
75337 	DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
75338 	tv1 = thr->valstack_top - 1;
75339 	DUK_TVAL_CHKFAST_INPLACE_FAST(tv1);  /* fastint downgrade check for return values */
75340 
75341 	/*
75342 	 *  Four possible outcomes:
75343 	 *
75344 	 *    1. A 'finally' in the same function catches the 'return'.
75345 	 *       It may continue to propagate when 'finally' is finished,
75346 	 *       or it may be neutralized by 'finally' (both handled by
75347 	 *       ENDFIN).
75348 	 *
75349 	 *    2. The return happens at the entry level of the bytecode
75350 	 *       executor, so return from the executor (in C stack).
75351 	 *
75352 	 *    3. There is a calling (ECMAScript) activation in the call
75353 	 *       stack => return to it, in the same executor instance.
75354 	 *
75355 	 *    4. There is no calling activation, and the thread is
75356 	 *       terminated.  There is always a resumer in this case,
75357 	 *       which gets the return value similarly to a 'yield'
75358 	 *       (except that the current thread can no longer be
75359 	 *       resumed).
75360 	 */
75361 
75362 	DUK_ASSERT(thr != NULL);
75363 	DUK_ASSERT(thr->callstack_top >= 1);
75364 
75365 	act = thr->callstack_curr;
75366 	DUK_ASSERT(act != NULL);
75367 
75368 	for (;;) {
75369 		cat = act->cat;
75370 		if (cat == NULL) {
75371 			break;
75372 		}
75373 
75374 		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
75375 		    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
75376 			DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
75377 			duk__handle_finally(thr, thr->valstack_top - 1, DUK_LJ_TYPE_RETURN);
75378 
75379 			DUK_DD(DUK_DDPRINT("-> return caught by 'finally', restart execution"));
75380 			return DUK__RETHAND_RESTART;
75381 		}
75382 
75383 		duk_hthread_catcher_unwind_norz(thr, act);
75384 	}
75385 
75386 	if (act == entry_act) {
75387 		/* Return to the bytecode executor caller who will unwind stacks
75388 		 * and handle constructor post-processing.
75389 		 * Return value is already on the stack top: [ ... retval ].
75390 		 */
75391 
75392 		DUK_DDD(DUK_DDDPRINT("-> return propagated up to entry level, exit bytecode executor"));
75393 		return DUK__RETHAND_FINISHED;
75394 	}
75395 
75396 	if (thr->callstack_top >= 2) {
75397 		/* There is a caller; it MUST be an ECMAScript caller (otherwise it would
75398 		 * match entry_act check).
75399 		 */
75400 		DUK_DDD(DUK_DDDPRINT("return to ECMAScript caller, retval_byteoff=%ld, lj_value1=%!T",
75401 		                     (long) (thr->callstack_curr->parent->retval_byteoff),
75402 		                     (duk_tval *) &thr->heap->lj.value1));
75403 
75404 		DUK_ASSERT(thr->callstack_curr != NULL);
75405 		DUK_ASSERT(thr->callstack_curr->parent != NULL);
75406 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent)));   /* must be ECMAScript */
75407 
75408 #if defined(DUK_USE_ES6_PROXY)
75409 		if (thr->callstack_curr->flags & (DUK_ACT_FLAG_CONSTRUCT | DUK_ACT_FLAG_CONSTRUCT_PROXY)) {
75410 			duk_call_construct_postprocess(thr, thr->callstack_curr->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY);  /* side effects */
75411 		}
75412 #else
75413 		if (thr->callstack_curr->flags & DUK_ACT_FLAG_CONSTRUCT) {
75414 			duk_call_construct_postprocess(thr, 0);  /* side effects */
75415 		}
75416 #endif
75417 
75418 		tv1 = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + thr->callstack_curr->parent->retval_byteoff);
75419 		DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
75420 		tv2 = thr->valstack_top - 1;
75421 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
75422 
75423 		/* Catch stack unwind happens inline in callstack unwind. */
75424 		duk_hthread_activation_unwind_norz(thr);
75425 
75426 		duk__reconfig_valstack_ecma_return(thr);
75427 
75428 		DUK_DD(DUK_DDPRINT("-> return not intercepted, restart execution in caller"));
75429 		return DUK__RETHAND_RESTART;
75430 	}
75431 
75432 #if defined(DUK_USE_COROUTINE_SUPPORT)
75433 	DUK_DD(DUK_DDPRINT("no calling activation, thread finishes (similar to yield)"));
75434 
75435 	DUK_ASSERT(thr->resumer != NULL);
75436 	DUK_ASSERT(thr->resumer->callstack_top >= 2);  /* ECMAScript activation + Duktape.Thread.resume() activation */
75437 	DUK_ASSERT(thr->resumer->callstack_curr != NULL);
75438 	DUK_ASSERT(thr->resumer->callstack_curr->parent != NULL);
75439 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr) != NULL &&
75440 			DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr)) &&
75441 			((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->resumer->callstack_curr))->func == duk_bi_thread_resume);  /* Duktape.Thread.resume() */
75442 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL &&
75443 			DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent)));  /* an ECMAScript function */
75444 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
75445 	DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
75446 
75447 	resumer = thr->resumer;
75448 
75449 	/* Share yield longjmp handler.
75450 	 *
75451 	 * This sequence of steps is a bit fragile (see GH-1845):
75452 	 * - We need the return value from 'thr' (resumed thread) value stack.
75453 	 *   The termination unwinds its value stack, losing the value.
75454 	 * - We need a refcounted reference for 'thr', which may only exist
75455 	 *   in the caller value stack.  We can't unwind or reconfigure the
75456 	 *   caller's value stack without potentially freeing 'thr'.
75457 	 *
75458 	 * Current approach is to capture the 'thr' return value and store
75459 	 * a reference to 'thr' in the caller value stack temporarily.  This
75460 	 * keeps 'thr' reachable until final yield/return handling which
75461 	 * removes the references atomatically.
75462 	 */
75463 
75464 	DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
75465 	duk_hthread_activation_unwind_norz(resumer);  /* May remove last reference to 'thr', but is NORZ. */
75466 	duk_push_tval(resumer, thr->valstack_top - 1);  /* Capture return value, side effect free. */
75467 	duk_push_hthread(resumer, thr);  /* Make 'thr' reachable again, before side effects. */
75468 
75469 	duk_hthread_terminate(thr);  /* Updates thread state, minimizes its allocations. */
75470 	thr->resumer = NULL;
75471 	DUK_HTHREAD_DECREF(thr, resumer);
75472 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
75473 
75474 	resumer->state = DUK_HTHREAD_STATE_RUNNING;
75475 	DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
75476 
75477 	DUK_ASSERT(resumer->valstack_top - 2 >= resumer->valstack_bottom);
75478 	duk__handle_yield(thr, resumer, resumer->valstack_top - 2);
75479 	thr = NULL;  /* 'thr' invalidated by call */
75480 
75481 #if 0
75482 	thr = resumer;  /* not needed */
75483 #endif
75484 
75485 	DUK_DD(DUK_DDPRINT("-> return not caught, thread terminated; handle like yield, restart execution in resumer"));
75486 	return DUK__RETHAND_RESTART;
75487 #else
75488 	/* Without coroutine support this case should never happen. */
75489 	DUK_ERROR_INTERNAL(thr);
75490 	DUK_WO_NORETURN(return 0;);
75491 #endif
75492 }
75493 
75494 /*
75495  *  Executor interrupt handling
75496  *
75497  *  The handler is called whenever the interrupt countdown reaches zero
75498  *  (or below).  The handler must perform whatever checks are activated,
75499  *  e.g. check for cumulative step count to impose an execution step
75500  *  limit or check for breakpoints or other debugger interaction.
75501  *
75502  *  When the actions are done, the handler must reinit the interrupt
75503  *  init and counter values.  The 'init' value must indicate how many
75504  *  bytecode instructions are executed before the next interrupt.  The
75505  *  counter must interface with the bytecode executor loop.  Concretely,
75506  *  the new init value is normally one higher than the new counter value.
75507  *  For instance, to execute exactly one bytecode instruction the init
75508  *  value is set to 1 and the counter to 0.  If an error is thrown by the
75509  *  interrupt handler, the counters are set to the same value (e.g. both
75510  *  to 0 to cause an interrupt when the next bytecode instruction is about
75511  *  to be executed after error handling).
75512  *
75513  *  Maintaining the init/counter value properly is important for accurate
75514  *  behavior.  For instance, executor step limit needs a cumulative step
75515  *  count which is simply computed as a sum of 'init' values.  This must
75516  *  work accurately even when single stepping.
75517  */
75518 
75519 #if defined(DUK_USE_INTERRUPT_COUNTER)
75520 
75521 #define DUK__INT_NOACTION    0    /* no specific action, resume normal execution */
75522 #define DUK__INT_RESTART     1    /* must "goto restart_execution", e.g. breakpoints changed */
75523 
75524 #if defined(DUK_USE_DEBUGGER_SUPPORT)
75525 DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_immediate, duk_small_uint_t *out_interrupt_retval) {
75526 	duk_activation *act;
75527 	duk_breakpoint *bp;
75528 	duk_breakpoint **bp_active;
75529 	duk_uint_fast32_t line = 0;
75530 	duk_bool_t process_messages;
75531 	duk_bool_t processed_messages = 0;
75532 
75533 	DUK_ASSERT(thr->heap->dbg_processing == 0);  /* don't re-enter e.g. during Eval */
75534 
75535 	act = thr->callstack_curr;
75536 	DUK_ASSERT(act != NULL);
75537 
75538 	/* It might seem that replacing 'thr->heap' with just 'heap' below
75539 	 * might be a good idea, but it increases code size slightly
75540 	 * (probably due to unnecessary spilling) at least on x64.
75541 	 */
75542 
75543 	/*
75544 	 *  Single opcode step check
75545 	 */
75546 
75547 	if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE) {
75548 		DUK_D(DUK_DPRINT("PAUSE TRIGGERED by one opcode step"));
75549 		duk_debug_set_paused(thr->heap);
75550 	}
75551 
75552 	/*
75553 	 *  Breakpoint and step state checks
75554 	 */
75555 
75556 	if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
75557 	    (thr->heap->dbg_pause_act == thr->callstack_curr)) {
75558 		line = duk_debug_curr_line(thr);
75559 
75560 		if (act->prev_line != line) {
75561 			/* Stepped?  Step out is handled by callstack unwind. */
75562 			if ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
75563 			    (thr->heap->dbg_pause_act == thr->callstack_curr) &&
75564 			    (line != thr->heap->dbg_pause_startline)) {
75565 				DUK_D(DUK_DPRINT("PAUSE TRIGGERED by line change, at line %ld",
75566 				                 (long) line));
75567 				duk_debug_set_paused(thr->heap);
75568 			}
75569 
75570 			/* Check for breakpoints only on line transition.
75571 			 * Breakpoint is triggered when we enter the target
75572 			 * line from a different line, and the previous line
75573 			 * was within the same function.
75574 			 *
75575 			 * This condition is tricky: the condition used to be
75576 			 * that transition to -or across- the breakpoint line
75577 			 * triggered the breakpoint.  This seems intuitively
75578 			 * better because it handles breakpoints on lines with
75579 			 * no emitted opcodes; but this leads to the issue
75580 			 * described in: https://github.com/svaarala/duktape/issues/263.
75581 			 */
75582 			bp_active = thr->heap->dbg_breakpoints_active;
75583 			for (;;) {
75584 				bp = *bp_active++;
75585 				if (bp == NULL) {
75586 					break;
75587 				}
75588 
75589 				DUK_ASSERT(bp->filename != NULL);
75590 				if (act->prev_line != bp->line && line == bp->line) {
75591 					DUK_D(DUK_DPRINT("PAUSE TRIGGERED by breakpoint at %!O:%ld",
75592 					                 (duk_heaphdr *) bp->filename, (long) bp->line));
75593 					duk_debug_set_paused(thr->heap);
75594 				}
75595 			}
75596 		} else {
75597 			;
75598 		}
75599 
75600 		act->prev_line = (duk_uint32_t) line;
75601 	}
75602 
75603 	/*
75604 	 *  Rate limit check for sending status update or peeking into
75605 	 *  the debug transport.  Both can be expensive operations that
75606 	 *  we don't want to do on every opcode.
75607 	 *
75608 	 *  Making sure the interval remains reasonable on a wide variety
75609 	 *  of targets and bytecode is difficult without a timestamp, so
75610 	 *  we use a Date-provided timestamp for the rate limit check.
75611 	 *  But since it's also expensive to get a timestamp, a bytecode
75612 	 *  counter is used to rate limit getting timestamps.
75613 	 */
75614 
75615 	process_messages = 0;
75616 	if (thr->heap->dbg_state_dirty || DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || thr->heap->dbg_detaching) {
75617 		/* Enter message processing loop for sending Status notifys and
75618 		 * to finish a pending detach.
75619 		 */
75620 		process_messages = 1;
75621 	}
75622 
75623 	/* XXX: remove heap->dbg_exec_counter, use heap->inst_count_interrupt instead? */
75624 	DUK_ASSERT(thr->interrupt_init >= 0);
75625 	thr->heap->dbg_exec_counter += (duk_uint_t) thr->interrupt_init;
75626 	if (thr->heap->dbg_exec_counter - thr->heap->dbg_last_counter >= DUK_HEAP_DBG_RATELIMIT_OPCODES) {
75627 		/* Overflow of the execution counter is fine and doesn't break
75628 		 * anything here.
75629 		 */
75630 
75631 		duk_double_t now, diff_last;
75632 
75633 		thr->heap->dbg_last_counter = thr->heap->dbg_exec_counter;
75634 		now = duk_time_get_monotonic_time(thr);
75635 
75636 		diff_last = now - thr->heap->dbg_last_time;
75637 		if (diff_last < 0.0 || diff_last >= (duk_double_t) DUK_HEAP_DBG_RATELIMIT_MILLISECS) {
75638 			/* Monotonic time should not experience time jumps,
75639 			 * but the provider may be missing and we're actually
75640 			 * using ECMAScript time.  So, tolerate negative values
75641 			 * so that a time jump works reasonably.
75642 			 *
75643 			 * Same interval is now used for status sending and
75644 			 * peeking.
75645 			 */
75646 
75647 			thr->heap->dbg_last_time = now;
75648 			thr->heap->dbg_state_dirty = 1;
75649 			process_messages = 1;
75650 		}
75651 	}
75652 
75653 	/*
75654 	 *  Process messages and send status if necessary.
75655 	 *
75656 	 *  If we're paused, we'll block for new messages.  If we're not
75657 	 *  paused, we'll process anything we can peek but won't block
75658 	 *  for more.  Detach (and re-attach) handling is all localized
75659 	 *  to duk_debug_process_messages() too.
75660 	 *
75661 	 *  Debugger writes outside the message loop may cause debugger
75662 	 *  detach1 phase to run, after which dbg_read_cb == NULL and
75663 	 *  dbg_detaching != 0.  The message loop will finish the detach
75664 	 *  by running detach2 phase, so enter the message loop also when
75665 	 *  detaching.
75666 	 */
75667 
75668 	if (process_messages) {
75669 		DUK_ASSERT(thr->heap->dbg_processing == 0);
75670 		processed_messages = duk_debug_process_messages(thr, 0 /*no_block*/);
75671 		DUK_ASSERT(thr->heap->dbg_processing == 0);
75672 	}
75673 
75674 	/* Continue checked execution if there are breakpoints or we're stepping.
75675 	 * Also use checked execution if paused flag is active - it shouldn't be
75676 	 * because the debug message loop shouldn't terminate if it was.  Step out
75677 	 * is handled by callstack unwind and doesn't need checked execution.
75678 	 * Note that debugger may have detached due to error or explicit request
75679 	 * above, so we must recheck attach status.
75680 	 */
75681 
75682 	if (duk_debug_is_attached(thr->heap)) {
75683 		DUK_ASSERT(act == thr->callstack_curr);
75684 		DUK_ASSERT(act != NULL);
75685 		if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
75686 		    (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE) ||
75687 		    ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
75688 		     thr->heap->dbg_pause_act == thr->callstack_curr) ||
75689 		     DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {
75690 			*out_immediate = 1;
75691 		}
75692 
75693 		/* If we processed any debug messages breakpoints may have
75694 		 * changed; restart execution to re-check active breakpoints.
75695 		 */
75696 		if (processed_messages) {
75697 			DUK_D(DUK_DPRINT("processed debug messages, restart execution to recheck possibly changed breakpoints"));
75698 			*out_interrupt_retval = DUK__INT_RESTART;
75699 		} else {
75700 			if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE) {
75701 				/* Set 'pause after one opcode' active only when we're
75702 				 * actually just about to execute code.
75703 				 */
75704 				thr->heap->dbg_pause_flags |= DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE;
75705 			}
75706 		}
75707 	} else {
75708 		DUK_D(DUK_DPRINT("debugger became detached, resume normal execution"));
75709 	}
75710 }
75711 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
75712 
75713 DUK_LOCAL DUK__NOINLINE_PERF DUK_COLD duk_small_uint_t duk__executor_interrupt(duk_hthread *thr) {
75714 	duk_int_t ctr;
75715 	duk_activation *act;
75716 	duk_hcompfunc *fun;
75717 	duk_bool_t immediate = 0;
75718 	duk_small_uint_t retval;
75719 
75720 	DUK_ASSERT(thr != NULL);
75721 	DUK_ASSERT(thr->heap != NULL);
75722 	DUK_ASSERT(thr->callstack_top > 0);
75723 
75724 #if defined(DUK_USE_DEBUG)
75725 	thr->heap->inst_count_interrupt += thr->interrupt_init;
75726 	DUK_DD(DUK_DDPRINT("execution interrupt, counter=%ld, init=%ld, "
75727 	                   "instruction counts: executor=%ld, interrupt=%ld",
75728 	                   (long) thr->interrupt_counter, (long) thr->interrupt_init,
75729 	                   (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
75730 #endif
75731 
75732 	retval = DUK__INT_NOACTION;
75733 	ctr = DUK_HTHREAD_INTCTR_DEFAULT;
75734 
75735 	/*
75736 	 *  Avoid nested calls.  Concretely this happens during debugging, e.g.
75737 	 *  when we eval() an expression.
75738 	 *
75739 	 *  Also don't interrupt if we're currently doing debug processing
75740 	 *  (which can be initiated outside the bytecode executor) as this
75741 	 *  may cause the debugger to be called recursively.  Check required
75742 	 *  for correct operation of throw intercept and other "exotic" halting
75743 	 * scenarios.
75744 	 */
75745 
75746 #if defined(DUK_USE_DEBUGGER_SUPPORT)
75747 	if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap) || thr->heap->dbg_processing) {
75748 #else
75749 	if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap)) {
75750 #endif
75751 		DUK_DD(DUK_DDPRINT("nested executor interrupt, ignoring"));
75752 
75753 		/* Set a high interrupt counter; the original executor
75754 		 * interrupt invocation will rewrite before exiting.
75755 		 */
75756 		thr->interrupt_init = ctr;
75757 		thr->interrupt_counter = ctr - 1;
75758 		return DUK__INT_NOACTION;
75759 	}
75760 	DUK_HEAP_SET_INTERRUPT_RUNNING(thr->heap);
75761 
75762 	act = thr->callstack_curr;
75763 	DUK_ASSERT(act != NULL);
75764 
75765 	fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
75766 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC((duk_hobject *) fun));
75767 
75768 	DUK_UNREF(fun);
75769 
75770 #if defined(DUK_USE_EXEC_TIMEOUT_CHECK)
75771 	/*
75772 	 *  Execution timeout check
75773 	 */
75774 
75775 	if (DUK_USE_EXEC_TIMEOUT_CHECK(thr->heap->heap_udata)) {
75776 		/* Keep throwing an error whenever we get here.  The unusual values
75777 		 * are set this way because no instruction is ever executed, we just
75778 		 * throw an error until all try/catch/finally and other catchpoints
75779 		 * have been exhausted.  Duktape/C code gets control at each protected
75780 		 * call but whenever it enters back into Duktape the RangeError gets
75781 		 * raised.  User exec timeout check must consistently indicate a timeout
75782 		 * until we've fully bubbled out of Duktape.
75783 		 */
75784 		DUK_D(DUK_DPRINT("execution timeout, throwing a RangeError"));
75785 		thr->interrupt_init = 0;
75786 		thr->interrupt_counter = 0;
75787 		DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);
75788 		DUK_ERROR_RANGE(thr, "execution timeout");
75789 		DUK_WO_NORETURN(return 0;);
75790 	}
75791 #endif  /* DUK_USE_EXEC_TIMEOUT_CHECK */
75792 
75793 #if defined(DUK_USE_DEBUGGER_SUPPORT)
75794 	if (!thr->heap->dbg_processing &&
75795 	    (thr->heap->dbg_read_cb != NULL || thr->heap->dbg_detaching)) {
75796 		/* Avoid recursive re-entry; enter when we're attached or
75797 		 * detaching (to finish off the pending detach).
75798 		 */
75799 		duk__interrupt_handle_debugger(thr, &immediate, &retval);
75800 		DUK_ASSERT(act == thr->callstack_curr);
75801 	}
75802 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
75803 
75804 	/*
75805 	 *  Update the interrupt counter
75806 	 */
75807 
75808 	if (immediate) {
75809 		/* Cause an interrupt after executing one instruction. */
75810 		ctr = 1;
75811 	}
75812 
75813 	/* The counter value is one less than the init value: init value should
75814 	 * indicate how many instructions are executed before interrupt.  To
75815 	 * execute 1 instruction (after interrupt handler return), counter must
75816 	 * be 0.
75817 	 */
75818 	DUK_ASSERT(ctr >= 1);
75819 	thr->interrupt_init = ctr;
75820 	thr->interrupt_counter = ctr - 1;
75821 	DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);
75822 
75823 	return retval;
75824 }
75825 #endif  /* DUK_USE_INTERRUPT_COUNTER */
75826 
75827 /*
75828  *  Debugger handling for executor restart
75829  *
75830  *  Check for breakpoints, stepping, etc, and figure out if we should execute
75831  *  in checked or normal mode.  Note that we can't do this when an activation
75832  *  is created, because breakpoint status (and stepping status) may change
75833  *  later, so we must recheck every time we're executing an activation.
75834  *  This primitive should be side effect free to avoid changes during check.
75835  */
75836 
75837 #if defined(DUK_USE_DEBUGGER_SUPPORT)
75838 DUK_LOCAL void duk__executor_recheck_debugger(duk_hthread *thr, duk_activation *act, duk_hcompfunc *fun) {
75839 	duk_heap *heap;
75840 	duk_tval *tv_tmp;
75841 	duk_hstring *filename;
75842 	duk_small_uint_t bp_idx;
75843 	duk_breakpoint **bp_active;
75844 
75845 	DUK_ASSERT(thr != NULL);
75846 	DUK_ASSERT(act != NULL);
75847 	DUK_ASSERT(fun != NULL);
75848 
75849 	heap = thr->heap;
75850 	bp_active = heap->dbg_breakpoints_active;
75851 	act->flags &= ~DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
75852 
75853 	tv_tmp = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) fun, DUK_STRIDX_FILE_NAME);
75854 	if (tv_tmp && DUK_TVAL_IS_STRING(tv_tmp)) {
75855 		filename = DUK_TVAL_GET_STRING(tv_tmp);
75856 
75857 		/* Figure out all active breakpoints.  A breakpoint is
75858 		 * considered active if the current function's fileName
75859 		 * matches the breakpoint's fileName, AND there is no
75860 		 * inner function that has matching line numbers
75861 		 * (otherwise a breakpoint would be triggered both
75862 		 * inside and outside of the inner function which would
75863 		 * be confusing).  Example:
75864 		 *
75865 		 *     function foo() {
75866 		 *         print('foo');
75867 		 *         function bar() {    <-.  breakpoints in these
75868 		 *             print('bar');     |  lines should not affect
75869 		 *         }                   <-'  foo() execution
75870 		 *         bar();
75871 		 *     }
75872 		 *
75873 		 * We need a few things that are only available when
75874 		 * debugger support is enabled: (1) a line range for
75875 		 * each function, and (2) access to the function
75876 		 * template to access the inner functions (and their
75877 		 * line ranges).
75878 		 *
75879 		 * It's important to have a narrow match for active
75880 		 * breakpoints so that we don't enter checked execution
75881 		 * when that's not necessary.  For instance, if we're
75882 		 * running inside a certain function and there's
75883 		 * breakpoint outside in (after the call site), we
75884 		 * don't want to slow down execution of the function.
75885 		 */
75886 
75887 		for (bp_idx = 0; bp_idx < heap->dbg_breakpoint_count; bp_idx++) {
75888 			duk_breakpoint *bp = heap->dbg_breakpoints + bp_idx;
75889 			duk_hobject **funcs, **funcs_end;
75890 			duk_hcompfunc *inner_fun;
75891 			duk_bool_t bp_match;
75892 
75893 			if (bp->filename == filename &&
75894 			    bp->line >= fun->start_line && bp->line <= fun->end_line) {
75895 				bp_match = 1;
75896 				DUK_DD(DUK_DDPRINT("breakpoint filename and line match: "
75897 				                   "%s:%ld vs. %s (line %ld vs. %ld-%ld)",
75898 				                   DUK_HSTRING_GET_DATA(bp->filename),
75899 				                   (long) bp->line,
75900 				                   DUK_HSTRING_GET_DATA(filename),
75901 				                   (long) bp->line,
75902 				                   (long) fun->start_line,
75903 				                   (long) fun->end_line));
75904 
75905 				funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, fun);
75906 				funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, fun);
75907 				while (funcs != funcs_end) {
75908 					inner_fun = (duk_hcompfunc *) *funcs;
75909 					DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) inner_fun));
75910 					if (bp->line >= inner_fun->start_line && bp->line <= inner_fun->end_line) {
75911 						DUK_DD(DUK_DDPRINT("inner function masks ('captures') breakpoint"));
75912 						bp_match = 0;
75913 						break;
75914 					}
75915 					funcs++;
75916 				}
75917 
75918 				if (bp_match) {
75919 					/* No need to check for size of bp_active list,
75920 					 * it's always larger than maximum number of
75921 					 * breakpoints.
75922 					 */
75923 					act->flags |= DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
75924 					*bp_active = heap->dbg_breakpoints + bp_idx;
75925 					bp_active++;
75926 				}
75927 			}
75928 		}
75929 	}
75930 
75931 	*bp_active = NULL;  /* terminate */
75932 
75933 	DUK_DD(DUK_DDPRINT("ACTIVE BREAKPOINTS: %ld", (long) (bp_active - thr->heap->dbg_breakpoints_active)));
75934 
75935 	/* Force pause if we were doing "step into" in another activation. */
75936 	if ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) &&
75937 	    thr->heap->dbg_pause_act != thr->callstack_curr) {
75938 		DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function entry"));
75939 		duk_debug_set_paused(thr->heap);
75940 	}
75941 
75942 	/* Force interrupt right away if we're paused or in "checked mode".
75943 	 * Step out is handled by callstack unwind.
75944 	 */
75945 	if ((act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE) ||
75946 	    DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ||
75947 	    ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
75948 	     thr->heap->dbg_pause_act == thr->callstack_curr)) {
75949 		/* We'll need to interrupt early so recompute the init
75950 		 * counter to reflect the number of bytecode instructions
75951 		 * executed so that step counts for e.g. debugger rate
75952 		 * limiting are accurate.
75953 		 */
75954 		DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
75955 		thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
75956 		thr->interrupt_counter = 0;
75957 	}
75958 }
75959 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
75960 
75961 /*
75962  *  Opcode handlers for opcodes with a lot of code and which are relatively
75963  *  rare; NOINLINE to reduce amount of code in main bytecode dispatcher.
75964  */
75965 
75966 DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_initset_initget(duk_hthread *thr, duk_uint_fast32_t ins) {
75967 	duk_bool_t is_set = (DUK_DEC_OP(ins) == DUK_OP_INITSET);
75968 	duk_uint_fast_t idx;
75969 	duk_uint_t defprop_flags;
75970 
75971 	/* A -> object register (acts as a source)
75972 	 * BC -> BC+0 contains key, BC+1 closure (value)
75973 	 */
75974 
75975 	/* INITSET/INITGET are only used to initialize object literal keys.
75976 	 * There may be a previous propery in ES2015 because duplicate property
75977 	 * names are allowed.
75978 	 */
75979 
75980 	/* This could be made more optimal by accessing internals directly. */
75981 
75982 	idx = (duk_uint_fast_t) DUK_DEC_BC(ins);
75983 	duk_dup(thr, (duk_idx_t) (idx + 0));  /* key */
75984 	duk_dup(thr, (duk_idx_t) (idx + 1));  /* getter/setter */
75985 	if (is_set) {
75986 	        defprop_flags = DUK_DEFPROP_HAVE_SETTER |
75987 	                        DUK_DEFPROP_FORCE |
75988 	                        DUK_DEFPROP_SET_ENUMERABLE |
75989 	                        DUK_DEFPROP_SET_CONFIGURABLE;
75990 	} else {
75991 	        defprop_flags = DUK_DEFPROP_HAVE_GETTER |
75992 	                        DUK_DEFPROP_FORCE |
75993 	                        DUK_DEFPROP_SET_ENUMERABLE |
75994 	                        DUK_DEFPROP_SET_CONFIGURABLE;
75995 	}
75996 	duk_def_prop(thr, (duk_idx_t) DUK_DEC_A(ins), defprop_flags);
75997 }
75998 
75999 DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_trycatch(duk_hthread *thr, duk_uint_fast32_t ins, duk_instr_t *curr_pc) {
76000 	duk_activation *act;
76001 	duk_catcher *cat;
76002 	duk_tval *tv1;
76003 	duk_small_uint_fast_t a;
76004 	duk_small_uint_fast_t bc;
76005 
76006 	/* A -> flags
76007 	 * BC -> reg_catch; base register for two registers used both during
76008 	 *       trycatch setup and when catch is triggered
76009 	 *
76010 	 *      If DUK_BC_TRYCATCH_FLAG_CATCH_BINDING set:
76011 	 *          reg_catch + 0: catch binding variable name (string).
76012 	 *          Automatic declarative environment is established for
76013 	 *          the duration of the 'catch' clause.
76014 	 *
76015 	 *      If DUK_BC_TRYCATCH_FLAG_WITH_BINDING set:
76016 	 *          reg_catch + 0: with 'target value', which is coerced to
76017 	 *          an object and then used as a bindind object for an
76018 	 *          environment record.  The binding is initialized here, for
76019 	 *          the 'try' clause.
76020 	 *
76021 	 * Note that a TRYCATCH generated for a 'with' statement has no
76022 	 * catch or finally parts.
76023 	 */
76024 
76025 	/* XXX: TRYCATCH handling should be reworked to avoid creating
76026 	 * an explicit scope unless it is actually needed (e.g. function
76027 	 * instances or eval is executed inside the catch block).  This
76028 	 * rework is not trivial because the compiler doesn't have an
76029 	 * intermediate representation.  When the rework is done, the
76030 	 * opcode format can also be made more straightforward.
76031 	 */
76032 
76033 	/* XXX: side effect handling is quite awkward here */
76034 
76035 	DUK_DDD(DUK_DDDPRINT("TRYCATCH: reg_catch=%ld, have_catch=%ld, "
76036 	                     "have_finally=%ld, catch_binding=%ld, with_binding=%ld (flags=0x%02lx)",
76037 	                     (long) DUK_DEC_BC(ins),
76038 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH ? 1 : 0),
76039 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY ? 1 : 0),
76040 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING ? 1 : 0),
76041 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_WITH_BINDING ? 1 : 0),
76042 	                     (unsigned long) DUK_DEC_A(ins)));
76043 
76044 	a = DUK_DEC_A(ins);
76045 	bc = DUK_DEC_BC(ins);
76046 
76047 	/* Registers 'bc' and 'bc + 1' are written in longjmp handling
76048 	 * and if their previous values (which are temporaries) become
76049 	 * unreachable -and- have a finalizer, there'll be a function
76050 	 * call during error handling which is not supported now (GH-287).
76051 	 * Ensure that both 'bc' and 'bc + 1' have primitive values to
76052 	 * guarantee no finalizer calls in error handling.  Scrubbing also
76053 	 * ensures finalizers for the previous values run here rather than
76054 	 * later.  Error handling related values are also written to 'bc'
76055 	 * and 'bc + 1' but those values never become unreachable during
76056 	 * error handling, so there's no side effect problem even if the
76057 	 * error value has a finalizer.
76058 	 */
76059 	duk_dup(thr, (duk_idx_t) bc);  /* Stabilize value. */
76060 	duk_to_undefined(thr, (duk_idx_t) bc);
76061 	duk_to_undefined(thr, (duk_idx_t) (bc + 1));
76062 
76063 	/* Allocate catcher and populate it.  Doesn't have to
76064 	 * be fully atomic, but the catcher must be in a
76065 	 * consistent state if side effects (such as finalizer
76066 	 * calls) occur.
76067 	 */
76068 
76069 	cat = duk_hthread_catcher_alloc(thr);
76070 	DUK_ASSERT(cat != NULL);
76071 
76072 	cat->flags = DUK_CAT_TYPE_TCF;
76073 	cat->h_varname = NULL;
76074 	cat->pc_base = (duk_instr_t *) curr_pc;  /* pre-incremented, points to first jump slot */
76075 	cat->idx_base = (duk_size_t) (thr->valstack_bottom - thr->valstack) + bc;
76076 
76077 	act = thr->callstack_curr;
76078 	DUK_ASSERT(act != NULL);
76079 	cat->parent = act->cat;
76080 	act->cat = cat;
76081 
76082 	if (a & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
76083 		cat->flags |= DUK_CAT_FLAG_CATCH_ENABLED;
76084 	}
76085 	if (a & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
76086 		cat->flags |= DUK_CAT_FLAG_FINALLY_ENABLED;
76087 	}
76088 	if (a & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING) {
76089 		DUK_DDD(DUK_DDDPRINT("catch binding flag set to catcher"));
76090 		cat->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED;
76091 		tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
76092 		DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
76093 
76094 		/* borrowed reference; although 'tv1' comes from a register,
76095 		 * its value was loaded using LDCONST so the constant will
76096 		 * also exist and be reachable.
76097 		 */
76098 		cat->h_varname = DUK_TVAL_GET_STRING(tv1);
76099 	} else if (a & DUK_BC_TRYCATCH_FLAG_WITH_BINDING) {
76100 		duk_hobjenv *env;
76101 		duk_hobject *target;
76102 
76103 		/* Delayed env initialization for activation (if needed). */
76104 		DUK_ASSERT(thr->callstack_top >= 1);
76105 		DUK_ASSERT(act == thr->callstack_curr);
76106 		DUK_ASSERT(act != NULL);
76107 		if (act->lex_env == NULL) {
76108 			DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
76109 			DUK_ASSERT(act->var_env == NULL);
76110 
76111 			duk_js_init_activation_environment_records_delayed(thr, act);
76112 			DUK_ASSERT(act == thr->callstack_curr);
76113 			DUK_UNREF(act);  /* 'act' is no longer accessed, scanbuild fix */
76114 		}
76115 		DUK_ASSERT(act->lex_env != NULL);
76116 		DUK_ASSERT(act->var_env != NULL);
76117 
76118 		/* Coerce 'with' target. */
76119 		target = duk_to_hobject(thr, -1);
76120 		DUK_ASSERT(target != NULL);
76121 
76122 		/* Create an object environment; it is not pushed
76123 		 * so avoid side effects very carefully until it is
76124 		 * referenced.
76125 		 */
76126 		env = duk_hobjenv_alloc(thr,
76127 		                        DUK_HOBJECT_FLAG_EXTENSIBLE |
76128 		                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
76129 		DUK_ASSERT(env != NULL);
76130 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
76131 		env->target = target;  /* always provideThis=true */
76132 		DUK_HOBJECT_INCREF(thr, target);
76133 		env->has_this = 1;
76134 		DUK_HOBJENV_ASSERT_VALID(env);
76135 		DUK_DDD(DUK_DDDPRINT("environment for with binding: %!iO", env));
76136 
76137 		DUK_ASSERT(act == thr->callstack_curr);
76138 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
76139 		DUK_ASSERT(act->lex_env != NULL);
76140 		DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) env, act->lex_env);
76141 		act->lex_env = (duk_hobject *) env;  /* Now reachable. */
76142 		DUK_HOBJECT_INCREF(thr, (duk_hobject *) env);
76143 		/* Net refcount change to act->lex_env is 0: incref for env's
76144 		 * prototype, decref for act->lex_env overwrite.
76145 		 */
76146 
76147 		/* Set catcher lex_env active (affects unwind)
76148 		 * only when the whole setup is complete.
76149 		 */
76150 		cat = act->cat;  /* XXX: better to relookup? not mandatory because 'cat' is stable */
76151 		cat->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE;
76152 	} else {
76153 		;
76154 	}
76155 
76156 	DUK_DDD(DUK_DDDPRINT("TRYCATCH catcher: flags=0x%08lx, pc_base=%ld, "
76157 	                     "idx_base=%ld, h_varname=%!O",
76158 	                     (unsigned long) cat->flags,
76159 	                     (long) cat->pc_base, (long) cat->idx_base, (duk_heaphdr *) cat->h_varname));
76160 
76161 	duk_pop_unsafe(thr);
76162 }
76163 
76164 DUK_LOCAL DUK__NOINLINE_PERF duk_instr_t *duk__handle_op_endtry(duk_hthread *thr, duk_uint_fast32_t ins) {
76165 	duk_activation *act;
76166 	duk_catcher *cat;
76167 	duk_tval *tv1;
76168 	duk_instr_t *pc_base;
76169 
76170 	DUK_UNREF(ins);
76171 
76172 	DUK_ASSERT(thr->callstack_top >= 1);
76173 	act = thr->callstack_curr;
76174 	DUK_ASSERT(act != NULL);
76175 	cat = act->cat;
76176 	DUK_ASSERT(cat != NULL);
76177 	DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);
76178 
76179 	DUK_DDD(DUK_DDDPRINT("ENDTRY: clearing catch active flag (regardless of whether it was set or not)"));
76180 	DUK_CAT_CLEAR_CATCH_ENABLED(cat);
76181 
76182 	pc_base = cat->pc_base;
76183 
76184 	if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
76185 		DUK_DDD(DUK_DDDPRINT("ENDTRY: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
76186 
76187 		tv1 = thr->valstack + cat->idx_base;
76188 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
76189 		DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
76190 		tv1 = NULL;
76191 
76192 		tv1 = thr->valstack + cat->idx_base + 1;
76193 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
76194 		DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL);  /* side effects */
76195 		tv1 = NULL;
76196 
76197 		DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
76198 	} else {
76199 		DUK_DDD(DUK_DDDPRINT("ENDTRY: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
76200 
76201 		duk_hthread_catcher_unwind_norz(thr, act);  /* lexenv may be set for 'with' binding */
76202 		/* no need to unwind callstack */
76203 	}
76204 
76205 	return pc_base + 1;  /* new curr_pc value */
76206 }
76207 
76208 DUK_LOCAL DUK__NOINLINE_PERF duk_instr_t *duk__handle_op_endcatch(duk_hthread *thr, duk_uint_fast32_t ins) {
76209 	duk_activation *act;
76210 	duk_catcher *cat;
76211 	duk_tval *tv1;
76212 	duk_instr_t *pc_base;
76213 
76214 	DUK_UNREF(ins);
76215 
76216 	DUK_ASSERT(thr->callstack_top >= 1);
76217 	act = thr->callstack_curr;
76218 	DUK_ASSERT(act != NULL);
76219 	cat = act->cat;
76220 	DUK_ASSERT(cat != NULL);
76221 	DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));  /* cleared before entering catch part */
76222 
76223 	if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
76224 		duk_hobject *prev_env;
76225 
76226 		/* 'with' binding has no catch clause, so can't be here unless a normal try-catch */
76227 		DUK_ASSERT(DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat));
76228 		DUK_ASSERT(act->lex_env != NULL);
76229 
76230 		DUK_DDD(DUK_DDDPRINT("ENDCATCH: popping catcher part lexical environment"));
76231 
76232 		prev_env = act->lex_env;
76233 		DUK_ASSERT(prev_env != NULL);
76234 		act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, prev_env);
76235 		DUK_CAT_CLEAR_LEXENV_ACTIVE(cat);
76236 		DUK_HOBJECT_INCREF(thr, act->lex_env);
76237 		DUK_HOBJECT_DECREF(thr, prev_env);  /* side effects */
76238 
76239 		DUK_ASSERT(act == thr->callstack_curr);
76240 		DUK_ASSERT(act != NULL);
76241 	}
76242 
76243 	pc_base = cat->pc_base;
76244 
76245 	if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
76246 		DUK_DDD(DUK_DDDPRINT("ENDCATCH: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
76247 
76248 		tv1 = thr->valstack + cat->idx_base;
76249 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
76250 		DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
76251 		tv1 = NULL;
76252 
76253 		tv1 = thr->valstack + cat->idx_base + 1;
76254 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
76255 		DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL);  /* side effects */
76256 		tv1 = NULL;
76257 
76258 		DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
76259 	} else {
76260 		DUK_DDD(DUK_DDDPRINT("ENDCATCH: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
76261 
76262 		duk_hthread_catcher_unwind_norz(thr, act);
76263 		/* no need to unwind callstack */
76264 	}
76265 
76266 	return pc_base + 1;  /* new curr_pc value */
76267 }
76268 
76269 DUK_LOCAL DUK__NOINLINE_PERF duk_small_uint_t duk__handle_op_endfin(duk_hthread *thr, duk_uint_fast32_t ins, duk_activation *entry_act) {
76270 	duk_activation *act;
76271 	duk_tval *tv1;
76272 	duk_uint_t reg_catch;
76273 	duk_small_uint_t cont_type;
76274 	duk_small_uint_t ret_result;
76275 
76276 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
76277 	DUK_ASSERT(thr->callstack_top >= 1);
76278 	act = thr->callstack_curr;
76279 	DUK_ASSERT(act != NULL);
76280 	reg_catch = DUK_DEC_ABC(ins);
76281 
76282 	/* CATCH flag may be enabled or disabled here; it may be enabled if
76283 	 * the statement has a catch block but the try block does not throw
76284 	 * an error.
76285 	 */
76286 
76287 	DUK_DDD(DUK_DDDPRINT("ENDFIN: completion value=%!T, type=%!T",
76288 	                     (duk_tval *) (thr->valstack_bottom + reg_catch + 0),
76289 	                     (duk_tval *) (thr->valstack_bottom + reg_catch + 1)));
76290 
76291 	tv1 = thr->valstack_bottom + reg_catch + 1;  /* type */
76292 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
76293 #if defined(DUK_USE_FASTINT)
76294 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
76295 	cont_type = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);
76296 #else
76297 	cont_type = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
76298 #endif
76299 
76300 	tv1--;  /* value */
76301 
76302 	switch (cont_type) {
76303 	case DUK_LJ_TYPE_NORMAL: {
76304 		DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'normal' (non-abrupt) completion -> "
76305 		                     "dismantle catcher, resume execution after ENDFIN"));
76306 
76307 		duk_hthread_catcher_unwind_norz(thr, act);
76308 		/* no need to unwind callstack */
76309 		return 0;  /* restart execution */
76310 	}
76311 	case DUK_LJ_TYPE_RETURN: {
76312 		DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'return' complation -> dismantle "
76313 		                     "catcher, handle return, lj.value1=%!T", tv1));
76314 
76315 		/* Not necessary to unwind catch stack: return handling will
76316 		 * do it.  The finally flag of 'cat' is no longer set.  The
76317 		 * catch flag may be set, but it's not checked by return handling.
76318 		 */
76319 
76320 		duk_push_tval(thr, tv1);
76321 		ret_result = duk__handle_return(thr, entry_act);
76322 		if (ret_result == DUK__RETHAND_RESTART) {
76323 			return 0;  /* restart execution */
76324 		}
76325 		DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED);
76326 
76327 		DUK_DDD(DUK_DDDPRINT("exiting executor after ENDFIN and RETURN (pseudo) longjmp type"));
76328 		return 1;  /* exit executor */
76329 	}
76330 	case DUK_LJ_TYPE_BREAK:
76331 	case DUK_LJ_TYPE_CONTINUE: {
76332 		duk_uint_t label_id;
76333 		duk_small_uint_t lj_type;
76334 
76335 		/* Not necessary to unwind catch stack: break/continue
76336 		 * handling will do it.  The finally flag of 'cat' is
76337 		 * no longer set.  The catch flag may be set, but it's
76338 		 * not checked by break/continue handling.
76339 		 */
76340 
76341 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
76342 #if defined(DUK_USE_FASTINT)
76343 		DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
76344 		label_id = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);
76345 #else
76346 		label_id = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
76347 #endif
76348 		lj_type = cont_type;
76349 		duk__handle_break_or_continue(thr, label_id, lj_type);
76350 		return 0;  /* restart execution */
76351 	}
76352 	default: {
76353 		DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with abrupt completion, lj_type=%ld -> "
76354 		                     "dismantle catcher, re-throw error",
76355 		                     (long) cont_type));
76356 
76357 		duk_err_setup_ljstate1(thr, (duk_small_uint_t) cont_type, tv1);
76358 		/* No debugger Throw notify check on purpose (rethrow). */
76359 
76360 		DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */
76361 		duk_err_longjmp(thr);
76362 		DUK_UNREACHABLE();
76363 	}
76364 	}
76365 
76366 	DUK_UNREACHABLE();
76367 	return 0;
76368 }
76369 
76370 DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_initenum(duk_hthread *thr, duk_uint_fast32_t ins) {
76371 	duk_small_uint_t b;
76372 	duk_small_uint_t c;
76373 
76374 	/*
76375 	 *  Enumeration semantics come from for-in statement, E5 Section 12.6.4.
76376 	 *  If called with 'null' or 'undefined', this opcode returns 'null' as
76377 	 *  the enumerator, which is special cased in NEXTENUM.  This simplifies
76378 	 *  the compiler part
76379 	 */
76380 
76381 	/* B -> register for writing enumerator object
76382 	 * C -> value to be enumerated (register)
76383 	 */
76384 	b = DUK_DEC_B(ins);
76385 	c = DUK_DEC_C(ins);
76386 
76387 	if (duk_is_null_or_undefined(thr, (duk_idx_t) c)) {
76388 		duk_push_null(thr);
76389 		duk_replace(thr, (duk_idx_t) b);
76390 	} else {
76391 		duk_dup(thr, (duk_idx_t) c);
76392 		duk_to_object(thr, -1);
76393 		duk_hobject_enumerator_create(thr, 0 /*enum_flags*/);  /* [ ... val ] --> [ ... enum ] */
76394 		duk_replace(thr, (duk_idx_t) b);
76395 	}
76396 }
76397 
76398 DUK_LOCAL DUK__NOINLINE_PERF duk_small_uint_t duk__handle_op_nextenum(duk_hthread *thr, duk_uint_fast32_t ins) {
76399 	duk_small_uint_t b;
76400 	duk_small_uint_t c;
76401 	duk_small_uint_t pc_skip = 0;
76402 
76403 	/*
76404 	 *  NEXTENUM checks whether the enumerator still has unenumerated
76405 	 *  keys.  If so, the next key is loaded to the target register
76406 	 *  and the next instruction is skipped.  Otherwise the next instruction
76407 	 *  will be executed, jumping out of the enumeration loop.
76408 	 */
76409 
76410 	/* B -> target register for next key
76411 	 * C -> enum register
76412 	 */
76413 	b = DUK_DEC_B(ins);
76414 	c = DUK_DEC_C(ins);
76415 
76416 	DUK_DDD(DUK_DDDPRINT("NEXTENUM: b->%!T, c->%!T",
76417 	                     (duk_tval *) duk_get_tval(thr, (duk_idx_t) b),
76418 	                     (duk_tval *) duk_get_tval(thr, (duk_idx_t) c)));
76419 
76420 	if (duk_is_object(thr, (duk_idx_t) c)) {
76421 		/* XXX: assert 'c' is an enumerator */
76422 		duk_dup(thr, (duk_idx_t) c);
76423 		if (duk_hobject_enumerator_next(thr, 0 /*get_value*/)) {
76424 			/* [ ... enum ] -> [ ... next_key ] */
76425 			DUK_DDD(DUK_DDDPRINT("enum active, next key is %!T, skip jump slot ",
76426 			                     (duk_tval *) duk_get_tval(thr, -1)));
76427 			pc_skip = 1;
76428 		} else {
76429 			/* [ ... enum ] -> [ ... ] */
76430 			DUK_DDD(DUK_DDDPRINT("enum finished, execute jump slot"));
76431 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */
76432 			thr->valstack_top++;
76433 		}
76434 		duk_replace(thr, (duk_idx_t) b);
76435 	} else {
76436 		/* 'null' enumerator case -> behave as with an empty enumerator */
76437 		DUK_ASSERT(duk_is_null(thr, (duk_idx_t) c));
76438 		DUK_DDD(DUK_DDDPRINT("enum is null, execute jump slot"));
76439 	}
76440 
76441 	return pc_skip;
76442 }
76443 
76444 /*
76445  *  Call handling helpers.
76446  */
76447 
76448 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) {
76449 	duk_bool_t rc;
76450 
76451 	duk_set_top_unsafe(thr, (duk_idx_t) (idx + nargs + 2));   /* [ ... func this arg1 ... argN ] */
76452 
76453 	/* Attempt an Ecma-to-Ecma call setup.  If the call
76454 	 * target is (directly or indirectly) Reflect.construct(),
76455 	 * the call may change into a constructor call on the fly.
76456 	 */
76457 	rc = (duk_bool_t) duk_handle_call_unprotected(thr, idx, call_flags);
76458 	if (rc != 0) {
76459 		/* Ecma-to-ecma call possible, may or may not
76460 		 * be a tail call.  Avoid C recursion by
76461 		 * reusing current executor instance.
76462 		 */
76463 		DUK_DDD(DUK_DDDPRINT("ecma-to-ecma call setup possible, restart execution"));
76464 		/* curr_pc synced by duk_handle_call_unprotected() */
76465 		DUK_ASSERT(thr->ptr_curr_pc == NULL);
76466 		return rc;
76467 	} else {
76468 		/* Call was handled inline. */
76469 	}
76470 	DUK_ASSERT(thr->ptr_curr_pc != NULL);
76471 	return rc;
76472 }
76473 
76474 /*
76475  *  ECMAScript bytecode executor.
76476  *
76477  *  Resume execution for the current thread from its current activation.
76478  *  Returns when execution would return from the entry level activation,
76479  *  leaving a single return value on top of the stack.  Function calls
76480  *  and thread resumptions are handled internally.  If an error occurs,
76481  *  a longjmp() with type DUK_LJ_TYPE_THROW is called on the entry level
76482  *  setjmp() jmpbuf.
76483  *
76484  *  ECMAScript function calls and coroutine resumptions are handled
76485  *  internally (by the outer executor function) without recursive C calls.
76486  *  Other function calls are handled using duk_handle_call(), increasing
76487  *  C recursion depth.
76488  *
76489  *  Abrupt completions (= long control tranfers) are handled either
76490  *  directly by reconfiguring relevant stacks and restarting execution,
76491  *  or via a longjmp.  Longjmp-free handling is preferable for performance
76492  *  (especially Emscripten performance), and is used for: break, continue,
76493  *  and return.
76494  *
76495  *  For more detailed notes, see doc/execution.rst.
76496  *
76497  *  Also see doc/code-issues.rst for discussion of setjmp(), longjmp(),
76498  *  and volatile.
76499  */
76500 
76501 /* Presence of 'fun' is config based, there's a marginal performance
76502  * difference and the best option is architecture dependent.
76503  */
76504 #if defined(DUK_USE_EXEC_FUN_LOCAL)
76505 #define DUK__FUN()          fun
76506 #else
76507 #define DUK__FUN()          ((duk_hcompfunc *) DUK_ACT_GET_FUNC((thr)->callstack_curr))
76508 #endif
76509 
76510 /* Strict flag. */
76511 #define DUK__STRICT()       ((duk_small_uint_t) DUK_HOBJECT_HAS_STRICT((duk_hobject *) DUK__FUN()))
76512 
76513 /* Reg/const access macros: these are very footprint and performance sensitive
76514  * so modify with care.  Arguments are sometimes evaluated multiple times which
76515  * is not ideal.
76516  */
76517 #define DUK__REG(x)         (*(thr->valstack_bottom + (x)))
76518 #define DUK__REGP(x)        (thr->valstack_bottom + (x))
76519 #define DUK__CONST(x)       (*(consts + (x)))
76520 #define DUK__CONSTP(x)      (consts + (x))
76521 
76522 /* Reg/const access macros which take the 32-bit instruction and avoid an
76523  * explicit field decoding step by using shifts and masks.  These must be
76524  * kept in sync with duk_js_bytecode.h.  The shift/mask values are chosen
76525  * so that 'ins' can be shifted and masked and used as a -byte- offset
76526  * instead of a duk_tval offset which needs further shifting (which is an
76527  * issue on some, but not all, CPUs).
76528  */
76529 #define DUK__RCBIT_B           DUK_BC_REGCONST_B
76530 #define DUK__RCBIT_C           DUK_BC_REGCONST_C
76531 #if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)
76532 #if defined(DUK_USE_PACKED_TVAL)
76533 #define DUK__TVAL_SHIFT        3  /* sizeof(duk_tval) == 8 */
76534 #else
76535 #define DUK__TVAL_SHIFT        4  /* sizeof(duk_tval) == 16; not always the case so also asserted for */
76536 #endif
76537 #define DUK__SHIFT_A           (DUK_BC_SHIFT_A - DUK__TVAL_SHIFT)
76538 #define DUK__SHIFT_B           (DUK_BC_SHIFT_B - DUK__TVAL_SHIFT)
76539 #define DUK__SHIFT_C           (DUK_BC_SHIFT_C - DUK__TVAL_SHIFT)
76540 #define DUK__SHIFT_BC          (DUK_BC_SHIFT_BC - DUK__TVAL_SHIFT)
76541 #define DUK__MASK_A            (DUK_BC_UNSHIFTED_MASK_A << DUK__TVAL_SHIFT)
76542 #define DUK__MASK_B            (DUK_BC_UNSHIFTED_MASK_B << DUK__TVAL_SHIFT)
76543 #define DUK__MASK_C            (DUK_BC_UNSHIFTED_MASK_C << DUK__TVAL_SHIFT)
76544 #define DUK__MASK_BC           (DUK_BC_UNSHIFTED_MASK_BC << DUK__TVAL_SHIFT)
76545 #define DUK__BYTEOFF_A(ins)    (((ins) >> DUK__SHIFT_A) & DUK__MASK_A)
76546 #define DUK__BYTEOFF_B(ins)    (((ins) >> DUK__SHIFT_B) & DUK__MASK_B)
76547 #define DUK__BYTEOFF_C(ins)    (((ins) >> DUK__SHIFT_C) & DUK__MASK_C)
76548 #define DUK__BYTEOFF_BC(ins)   (((ins) >> DUK__SHIFT_BC) & DUK__MASK_BC)
76549 
76550 #define DUK__REGP_A(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_A((ins))))
76551 #define DUK__REGP_B(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_B((ins))))
76552 #define DUK__REGP_C(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_C((ins))))
76553 #define DUK__REGP_BC(ins)      ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_BC((ins))))
76554 #define DUK__CONSTP_A(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_A((ins))))
76555 #define DUK__CONSTP_B(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_B((ins))))
76556 #define DUK__CONSTP_C(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_C((ins))))
76557 #define DUK__CONSTP_BC(ins)    ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_BC((ins))))
76558 #define DUK__REGCONSTP_B(ins)  ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) & DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_B((ins))))
76559 #define DUK__REGCONSTP_C(ins)  ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) & DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_C((ins))))
76560 #else  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
76561 /* Safe alternatives, no assumption about duk_tval size. */
76562 #define DUK__REGP_A(ins)       DUK__REGP(DUK_DEC_A((ins)))
76563 #define DUK__REGP_B(ins)       DUK__REGP(DUK_DEC_B((ins)))
76564 #define DUK__REGP_C(ins)       DUK__REGP(DUK_DEC_C((ins)))
76565 #define DUK__REGP_BC(ins)      DUK__REGP(DUK_DEC_BC((ins)))
76566 #define DUK__CONSTP_A(ins)     DUK__CONSTP(DUK_DEC_A((ins)))
76567 #define DUK__CONSTP_B(ins)     DUK__CONSTP(DUK_DEC_B((ins)))
76568 #define DUK__CONSTP_C(ins)     DUK__CONSTP(DUK_DEC_C((ins)))
76569 #define DUK__CONSTP_BC(ins)    DUK__CONSTP(DUK_DEC_BC((ins)))
76570 #define DUK__REGCONSTP_B(ins)  ((((ins) & DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK_DEC_B((ins)))
76571 #define DUK__REGCONSTP_C(ins)  ((((ins) & DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK_DEC_C((ins)))
76572 #endif  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
76573 
76574 #if defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)
76575 #define DUK__INTERNAL_ERROR(msg)  do { \
76576 		DUK_ERROR_ERROR(thr, (msg)); \
76577 		DUK_WO_NORETURN(return;); \
76578 	} while (0)
76579 #else
76580 #define DUK__INTERNAL_ERROR(msg)  do { \
76581 		goto internal_error; \
76582 	} while (0)
76583 #endif
76584 
76585 #define DUK__SYNC_CURR_PC()  do { \
76586 		duk_activation *duk__act; \
76587 		duk__act = thr->callstack_curr; \
76588 		duk__act->curr_pc = curr_pc; \
76589 	} while (0)
76590 #define DUK__SYNC_AND_NULL_CURR_PC()  do { \
76591 		duk_activation *duk__act; \
76592 		duk__act = thr->callstack_curr; \
76593 		duk__act->curr_pc = curr_pc; \
76594 		thr->ptr_curr_pc = NULL; \
76595 	} while (0)
76596 
76597 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76598 #define DUK__LOOKUP_INDIRECT(idx) do { \
76599 		(idx) = (duk_uint_fast_t) duk_get_uint(thr, (duk_idx_t) (idx)); \
76600 	} while (0)
76601 #elif defined(DUK_USE_FASTINT)
76602 #define DUK__LOOKUP_INDIRECT(idx) do { \
76603 		duk_tval *tv_ind; \
76604 		tv_ind = DUK__REGP((idx)); \
76605 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \
76606 		DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_ind));  /* compiler guarantees */ \
76607 		(idx) = (duk_uint_fast_t) DUK_TVAL_GET_FASTINT_U32(tv_ind); \
76608 	} while (0)
76609 #else
76610 #define DUK__LOOKUP_INDIRECT(idx) do { \
76611 		duk_tval *tv_ind; \
76612 		tv_ind = DUK__REGP(idx); \
76613 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \
76614 		idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind); \
76615 	} while (0)
76616 #endif
76617 
76618 DUK_LOCAL void duk__handle_executor_error(duk_heap *heap,
76619                                           duk_activation *entry_act,
76620                                           duk_int_t entry_call_recursion_depth,
76621                                           duk_jmpbuf *entry_jmpbuf_ptr,
76622                                           volatile duk_bool_t *out_delayed_catch_setup) {
76623 	duk_small_uint_t lj_ret;
76624 
76625 	/* Longjmp callers are required to sync-and-null thr->ptr_curr_pc
76626 	 * before longjmp.
76627 	 */
76628 	DUK_ASSERT(heap->curr_thread != NULL);
76629 	DUK_ASSERT(heap->curr_thread->ptr_curr_pc == NULL);
76630 
76631 	/* XXX: signalling the need to shrink check (only if unwound) */
76632 
76633 	/* Must be restored here to handle e.g. yields properly. */
76634 	heap->call_recursion_depth = entry_call_recursion_depth;
76635 
76636 	/* Switch to caller's setjmp() catcher so that if an error occurs
76637 	 * during error handling, it is always propagated outwards instead
76638 	 * of causing an infinite loop in our own handler.
76639 	 */
76640 	heap->lj.jmpbuf_ptr = (duk_jmpbuf *) entry_jmpbuf_ptr;
76641 
76642 	lj_ret = duk__handle_longjmp(heap->curr_thread, entry_act, out_delayed_catch_setup);
76643 
76644 	/* Error handling complete, remove side effect protections.
76645 	 */
76646 #if defined(DUK_USE_ASSERTIONS)
76647 	DUK_ASSERT(heap->error_not_allowed == 1);
76648 	heap->error_not_allowed = 0;
76649 #endif
76650 	DUK_ASSERT(heap->pf_prevent_count > 0);
76651 	heap->pf_prevent_count--;
76652 	DUK_DD(DUK_DDPRINT("executor error handled, pf_prevent_count updated to %ld", (long) heap->pf_prevent_count));
76653 
76654 	if (lj_ret == DUK__LONGJMP_RESTART) {
76655 		/* Restart bytecode execution, possibly with a changed thread. */
76656 		DUK_REFZERO_CHECK_SLOW(heap->curr_thread);
76657 	} else {
76658 		/* If an error is propagated, don't run refzero checks here.
76659 		 * The next catcher will deal with that.  Pf_prevent_count
76660 		 * will be re-bumped by the longjmp.
76661 		 */
76662 
76663 		DUK_ASSERT(lj_ret == DUK__LONGJMP_RETHROW);  /* Rethrow error to calling state. */
76664 		DUK_ASSERT(heap->lj.jmpbuf_ptr == entry_jmpbuf_ptr);  /* Longjmp handling has restored jmpbuf_ptr. */
76665 
76666 		/* Thread may have changed, e.g. YIELD converted to THROW. */
76667 		duk_err_longjmp(heap->curr_thread);
76668 		DUK_UNREACHABLE();
76669 	}
76670 }
76671 
76672 /* Outer executor with setjmp/longjmp handling. */
76673 DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) {
76674 	/* Entry level info. */
76675 	duk_hthread *entry_thread;
76676 	duk_activation *entry_act;
76677 	duk_int_t entry_call_recursion_depth;
76678 	duk_jmpbuf *entry_jmpbuf_ptr;
76679 	duk_jmpbuf our_jmpbuf;
76680 	duk_heap *heap;
76681 	volatile duk_bool_t delayed_catch_setup = 0;
76682 
76683 	DUK_ASSERT(exec_thr != NULL);
76684 	DUK_ASSERT(exec_thr->heap != NULL);
76685 	DUK_ASSERT(exec_thr->heap->curr_thread != NULL);
76686 	DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR((duk_heaphdr *) exec_thr);
76687 	DUK_ASSERT(exec_thr->callstack_top >= 1);  /* at least one activation, ours */
76688 	DUK_ASSERT(exec_thr->callstack_curr != NULL);
76689 	DUK_ASSERT(DUK_ACT_GET_FUNC(exec_thr->callstack_curr) != NULL);
76690 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(exec_thr->callstack_curr)));
76691 
76692 	DUK_GC_TORTURE(exec_thr->heap);
76693 
76694 	entry_thread = exec_thr;
76695 	heap = entry_thread->heap;
76696 	entry_act = entry_thread->callstack_curr;
76697 	DUK_ASSERT(entry_act != NULL);
76698 	entry_call_recursion_depth = entry_thread->heap->call_recursion_depth;
76699 	entry_jmpbuf_ptr = entry_thread->heap->lj.jmpbuf_ptr;
76700 
76701 	/*
76702 	 *  Note: we currently assume that the setjmp() catchpoint is
76703 	 *  not re-entrant (longjmp() cannot be called more than once
76704 	 *  for a single setjmp()).
76705 	 *
76706 	 *  See doc/code-issues.rst for notes on variable assignment
76707 	 *  before and after setjmp().
76708 	 */
76709 
76710 	for (;;) {
76711 		heap->lj.jmpbuf_ptr = &our_jmpbuf;
76712 		DUK_ASSERT(heap->lj.jmpbuf_ptr != NULL);
76713 
76714 #if defined(DUK_USE_CPP_EXCEPTIONS)
76715 		try {
76716 #else
76717 		DUK_ASSERT(heap->lj.jmpbuf_ptr == &our_jmpbuf);
76718 		if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
76719 #endif
76720 			DUK_DDD(DUK_DDDPRINT("after setjmp, delayed catch setup: %ld\n", (long) delayed_catch_setup));
76721 
76722 			if (DUK_UNLIKELY(delayed_catch_setup != 0)) {
76723 				duk_hthread *thr = entry_thread->heap->curr_thread;
76724 
76725 				delayed_catch_setup = 0;
76726 				duk__handle_catch_part2(thr);
76727 				DUK_ASSERT(delayed_catch_setup == 0);
76728 				DUK_DDD(DUK_DDDPRINT("top after delayed catch setup: %ld", (long) duk_get_top(entry_thread)));
76729 			}
76730 
76731 			/* Execute bytecode until returned or longjmp(). */
76732 			duk__js_execute_bytecode_inner(entry_thread, entry_act);
76733 
76734 			/* Successful return: restore jmpbuf and return to caller. */
76735 			heap->lj.jmpbuf_ptr = entry_jmpbuf_ptr;
76736 
76737 			return;
76738 #if defined(DUK_USE_CPP_EXCEPTIONS)
76739 		} catch (duk_internal_exception &exc) {
76740 #else
76741 		} else {
76742 #endif
76743 #if defined(DUK_USE_CPP_EXCEPTIONS)
76744 			DUK_UNREF(exc);
76745 #endif
76746 			DUK_DDD(DUK_DDDPRINT("longjmp caught by bytecode executor"));
76747 			DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
76748 
76749 			duk__handle_executor_error(heap,
76750 			                           entry_act,
76751 			                           entry_call_recursion_depth,
76752 			                           entry_jmpbuf_ptr,
76753 						   &delayed_catch_setup);
76754 		}
76755 #if defined(DUK_USE_CPP_EXCEPTIONS)
76756 		catch (duk_fatal_exception &exc) {
76757 			DUK_D(DUK_DPRINT("rethrow duk_fatal_exception"));
76758 			throw;
76759 		} catch (std::exception &exc) {
76760 			const char *what = exc.what();
76761 			if (!what) {
76762 				what = "unknown";
76763 			}
76764 			DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
76765 			DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
76766 			try {
76767 				DUK_ASSERT(heap->curr_thread != NULL);
76768 				DUK_ERROR_FMT1(heap->curr_thread, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
76769 				DUK_WO_NORETURN(return;);
76770 			} catch (duk_internal_exception exc) {
76771 				DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
76772 				DUK_UNREF(exc);
76773 				duk__handle_executor_error(heap,
76774 				                           entry_act,
76775 				                           entry_call_recursion_depth,
76776 				                           entry_jmpbuf_ptr,
76777 							   &delayed_catch_setup);
76778 			}
76779 		} catch (...) {
76780 			DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
76781 			DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
76782 			try {
76783 				DUK_ASSERT(heap->curr_thread != NULL);
76784 				DUK_ERROR_TYPE(heap->curr_thread, "caught invalid c++ exception (perhaps thrown by user code)");
76785 				DUK_WO_NORETURN(return;);
76786 			} catch (duk_internal_exception exc) {
76787 				DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
76788 				DUK_UNREF(exc);
76789 				duk__handle_executor_error(heap,
76790 				                           entry_act,
76791 				                           entry_call_recursion_depth,
76792 				                           entry_jmpbuf_ptr,
76793 							   &delayed_catch_setup);
76794 			}
76795 		}
76796 #endif
76797 	}
76798 
76799 	DUK_WO_NORETURN(return;);
76800 }
76801 
76802 /* Inner executor, performance critical. */
76803 DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_activation *entry_act) {
76804 	/* Current PC, accessed by other functions through thr->ptr_to_curr_pc.
76805 	 * Critical for performance.  It would be safest to make this volatile,
76806 	 * but that eliminates performance benefits; aliasing guarantees
76807 	 * should be enough though.
76808 	 */
76809 	duk_instr_t *curr_pc;         /* bytecode has a stable pointer */
76810 
76811 	/* Hot variables for interpretation.  Critical for performance,
76812 	 * but must add sparingly to minimize register shuffling.
76813 	 */
76814 	duk_hthread *thr;             /* stable */
76815 	duk_tval *consts;             /* stable */
76816 	duk_uint_fast32_t ins;
76817 	/* 'funcs' is quite rarely used, so no local for it */
76818 #if defined(DUK_USE_EXEC_FUN_LOCAL)
76819 	duk_hcompfunc *fun;
76820 #else
76821 	/* 'fun' is quite rarely used, so no local for it */
76822 #endif
76823 
76824 #if defined(DUK_USE_INTERRUPT_COUNTER)
76825 	duk_int_t int_ctr;
76826 #endif
76827 
76828 #if defined(DUK_USE_ASSERTIONS)
76829 	duk_size_t valstack_top_base;    /* valstack top, should match before interpreting each op (no leftovers) */
76830 #endif
76831 
76832 	/* Optimized reg/const access macros assume sizeof(duk_tval) to be
76833 	 * either 8 or 16.  Heap allocation checks this even without asserts
76834 	 * enabled now because it can't be autodetected in duk_config.h.
76835 	 */
76836 #if 1
76837 #if defined(DUK_USE_PACKED_TVAL)
76838 	DUK_ASSERT(sizeof(duk_tval) == 8);
76839 #else
76840 	DUK_ASSERT(sizeof(duk_tval) == 16);
76841 #endif
76842 #endif
76843 
76844 	DUK_GC_TORTURE(entry_thread->heap);
76845 
76846 	/*
76847 	 *  Restart execution by reloading thread state.
76848 	 *
76849 	 *  Note that 'thr' and any thread configuration may have changed,
76850 	 *  so all local variables are suspect and we need to reinitialize.
76851 	 *
76852 	 *  The number of local variables should be kept to a minimum: if
76853 	 *  the variables are spilled, they will need to be loaded from
76854 	 *  memory anyway.
76855 	 *
76856 	 *  Any 'goto restart_execution;' code path in opcode dispatch must
76857 	 *  ensure 'curr_pc' is synced back to act->curr_pc before the goto
76858 	 *  takes place.
76859 	 *
76860 	 *  The interpreter must be very careful with memory pointers, as
76861 	 *  many pointers are not guaranteed to be 'stable' and may be
76862 	 *  reallocated and relocated on-the-fly quite easily (e.g. by a
76863 	 *  memory allocation or a property access).
76864 	 *
76865 	 *  The following are assumed to have stable pointers:
76866 	 *    - the current thread
76867 	 *    - the current function
76868 	 *    - the bytecode, constant table, inner function table of the
76869 	 *      current function (as they are a part of the function allocation)
76870 	 *
76871 	 *  The following are assumed to have semi-stable pointers:
76872 	 *    - the current activation entry: stable as long as callstack
76873 	 *      is not changed (reallocated by growing or shrinking), or
76874 	 *      by any garbage collection invocation (through finalizers)
76875 	 *    - Note in particular that ANY DECREF can invalidate the
76876 	 *      activation pointer, so for the most part a fresh lookup
76877 	 *      is required
76878 	 *
76879 	 *  The following are not assumed to have stable pointers at all:
76880 	 *    - the value stack (registers) of the current thread
76881 	 *
76882 	 *  See execution.rst for discussion.
76883 	 */
76884 
76885  restart_execution:
76886 
76887 	/* Lookup current thread; use the stable 'entry_thread' for this to
76888 	 * avoid clobber warnings.  Any valid, reachable 'thr' value would be
76889 	 * fine for this, so using 'entry_thread' is just to silence warnings.
76890 	 */
76891 	thr = entry_thread->heap->curr_thread;
76892 	DUK_ASSERT(thr != NULL);
76893 	DUK_ASSERT(thr->callstack_top >= 1);
76894 	DUK_ASSERT(thr->callstack_curr != NULL);
76895 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
76896 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
76897 
76898 	DUK_GC_TORTURE(thr->heap);
76899 
76900 	thr->ptr_curr_pc = &curr_pc;
76901 
76902 	/* Relookup and initialize dispatch loop variables.  Debugger check. */
76903 	{
76904 		duk_activation *act;
76905 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
76906 		duk_hcompfunc *fun;
76907 #endif
76908 
76909 		/* Assume interrupt init/counter are properly initialized here. */
76910 		/* Assume that thr->valstack_bottom has been set-up before getting here. */
76911 
76912 		act = thr->callstack_curr;
76913 		DUK_ASSERT(act != NULL);
76914 		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
76915 		DUK_ASSERT(fun != NULL);
76916 		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == fun->nregs);
76917 		consts = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, fun);
76918 		DUK_ASSERT(consts != NULL);
76919 
76920 #if defined(DUK_USE_DEBUGGER_SUPPORT)
76921 		if (DUK_UNLIKELY(duk_debug_is_attached(thr->heap) && !thr->heap->dbg_processing)) {
76922 			duk__executor_recheck_debugger(thr, act, fun);
76923 			DUK_ASSERT(act == thr->callstack_curr);
76924 			DUK_ASSERT(act != NULL);
76925 		}
76926 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
76927 
76928 #if defined(DUK_USE_ASSERTIONS)
76929 		valstack_top_base = (duk_size_t) (thr->valstack_top - thr->valstack);
76930 #endif
76931 
76932 		/* Set up curr_pc for opcode dispatch. */
76933 		curr_pc = act->curr_pc;
76934 	}
76935 
76936 	DUK_DD(DUK_DDPRINT("restarting execution, thr %p, act idx %ld, fun %p,"
76937 	                   "consts %p, funcs %p, lev %ld, regbot %ld, regtop %ld, "
76938 	                   "preventcount=%ld",
76939 	                   (void *) thr,
76940 	                   (long) (thr->callstack_top - 1),
76941 	                   (void *) DUK__FUN(),
76942 	                   (void *) DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, DUK__FUN()),
76943 	                   (void *) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, DUK__FUN()),
76944 	                   (long) (thr->callstack_top - 1),
76945 	                   (long) (thr->valstack_bottom - thr->valstack),
76946 	                   (long) (thr->valstack_top - thr->valstack),
76947 	                   (long) thr->callstack_preventcount));
76948 
76949 	/* Dispatch loop. */
76950 
76951 	for (;;) {
76952 		duk_uint8_t op;
76953 
76954 		DUK_ASSERT(thr->callstack_top >= 1);
76955 		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == DUK__FUN()->nregs);
76956 		DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) == valstack_top_base);
76957 
76958 		/* Executor interrupt counter check, used to implement breakpoints,
76959 		 * debugging interface, execution timeouts, etc.  The counter is heap
76960 		 * specific but is maintained in the current thread to make the check
76961 		 * as fast as possible.  The counter is copied back to the heap struct
76962 		 * whenever a thread switch occurs by the DUK_HEAP_SWITCH_THREAD() macro.
76963 		 */
76964 #if defined(DUK_USE_INTERRUPT_COUNTER)
76965 		int_ctr = thr->interrupt_counter;
76966 		if (DUK_LIKELY(int_ctr > 0)) {
76967 			thr->interrupt_counter = int_ctr - 1;
76968 		} else {
76969 			/* Trigger at zero or below */
76970 			duk_small_uint_t exec_int_ret;
76971 
76972 			DUK_STATS_INC(thr->heap, stats_exec_interrupt);
76973 
76974 			/* Write curr_pc back for the debugger. */
76975 			{
76976 				duk_activation *act;
76977 				DUK_ASSERT(thr->callstack_top > 0);
76978 				act = thr->callstack_curr;
76979 				DUK_ASSERT(act != NULL);
76980 				act->curr_pc = (duk_instr_t *) curr_pc;
76981 			}
76982 
76983 			/* Forced restart caused by a function return; must recheck
76984 			 * debugger breakpoints before checking line transitions,
76985 			 * see GH-303.  Restart and then handle interrupt_counter
76986 			 * zero again.
76987 			 */
76988 #if defined(DUK_USE_DEBUGGER_SUPPORT)
76989 			if (thr->heap->dbg_force_restart) {
76990 				DUK_DD(DUK_DDPRINT("dbg_force_restart flag forced restart execution"));  /* GH-303 */
76991 				thr->heap->dbg_force_restart = 0;
76992 				goto restart_execution;
76993 			}
76994 #endif
76995 
76996 			exec_int_ret = duk__executor_interrupt(thr);
76997 			if (exec_int_ret == DUK__INT_RESTART) {
76998 				/* curr_pc synced back above */
76999 				goto restart_execution;
77000 			}
77001 		}
77002 #endif  /* DUK_USE_INTERRUPT_COUNTER */
77003 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
77004 		/* For cross-checking during development: ensure dispatch count
77005 		 * matches cumulative interrupt counter init value sums.
77006 		 */
77007 		thr->heap->inst_count_exec++;
77008 #endif
77009 
77010 #if defined(DUK_USE_ASSERTIONS) || defined(DUK_USE_DEBUG)
77011 		{
77012 			duk_activation *act;
77013 			act = thr->callstack_curr;
77014 			DUK_ASSERT(curr_pc >= DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN()));
77015 			DUK_ASSERT(curr_pc < DUK_HCOMPFUNC_GET_CODE_END(thr->heap, DUK__FUN()));
77016 			DUK_UNREF(act);  /* if debugging disabled */
77017 
77018 			DUK_DDD(DUK_DDDPRINT("executing bytecode: pc=%ld, ins=0x%08lx, op=%ld, valstack_top=%ld/%ld, nregs=%ld  -->  %!I",
77019 			                     (long) (curr_pc - DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN())),
77020 			                     (unsigned long) *curr_pc,
77021 			                     (long) DUK_DEC_OP(*curr_pc),
77022 			                     (long) (thr->valstack_top - thr->valstack),
77023 			                     (long) (thr->valstack_end - thr->valstack),
77024 			                     (long) (DUK__FUN() ? DUK__FUN()->nregs : -1),
77025 			                     (duk_instr_t) *curr_pc));
77026 		}
77027 #endif
77028 
77029 #if defined(DUK_USE_ASSERTIONS)
77030 		/* Quite heavy assert: check valstack policy.  Improper
77031 		 * shuffle instructions can write beyond valstack_top/end
77032 		 * so this check catches them in the act.
77033 		 */
77034 		{
77035 			duk_tval *tv;
77036 			tv = thr->valstack_top;
77037 			while (tv != thr->valstack_end) {
77038 				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
77039 				tv++;
77040 			}
77041 		}
77042 #endif
77043 
77044 		ins = *curr_pc++;
77045 		DUK_STATS_INC(thr->heap, stats_exec_opcodes);
77046 
77047 		/* Typing: use duk_small_(u)int_fast_t when decoding small
77048 		 * opcode fields (op, A, B, C, BC) which fit into 16 bits
77049 		 * and duk_(u)int_fast_t when decoding larger fields (e.g.
77050 		 * ABC).  Use unsigned variant by default, signed when the
77051 		 * value is used in signed arithmetic.  Using variable names
77052 		 * such as 'a', 'b', 'c', 'bc', etc makes it easier to spot
77053 		 * typing mismatches.
77054 		 */
77055 
77056 		/* Switch based on opcode.  Cast to 8-bit unsigned value and
77057 		 * use a fully populated case clauses so that the compiler
77058 		 * will (at least usually) omit a bounds check.
77059 		 */
77060 		op = (duk_uint8_t) DUK_DEC_OP(ins);
77061 		switch (op) {
77062 
77063 		/* Some useful macros.  These access inner executor variables
77064 		 * directly so they only apply within the executor.
77065 		 */
77066 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77067 #define DUK__REPLACE_TOP_A_BREAK() { goto replace_top_a; }
77068 #define DUK__REPLACE_TOP_BC_BREAK() { goto replace_top_bc; }
77069 #define DUK__REPLACE_BOOL_A_BREAK(bval) { \
77070 		duk_bool_t duk__bval; \
77071 		duk__bval = (bval); \
77072 		DUK_ASSERT(duk__bval == 0 || duk__bval == 1); \
77073 		duk_push_boolean(thr, duk__bval); \
77074 		DUK__REPLACE_TOP_A_BREAK(); \
77075 	}
77076 #else
77077 #define DUK__REPLACE_TOP_A_BREAK() { DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins)); break; }
77078 #define DUK__REPLACE_TOP_BC_BREAK() { DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins)); break; }
77079 #define DUK__REPLACE_BOOL_A_BREAK(bval) { \
77080 		duk_bool_t duk__bval; \
77081 		duk_tval *duk__tvdst; \
77082 		duk__bval = (bval); \
77083 		DUK_ASSERT(duk__bval == 0 || duk__bval == 1); \
77084 		duk__tvdst = DUK__REGP_A(ins); \
77085 		DUK_TVAL_SET_BOOLEAN_UPDREF(thr, duk__tvdst, duk__bval); \
77086 		break; \
77087 	}
77088 #endif
77089 
77090 		/* XXX: 12 + 12 bit variant might make sense too, for both reg and
77091 		 * const loads.
77092 		 */
77093 
77094 		/* For LDREG, STREG, LDCONST footprint optimized variants would just
77095 		 * duk_dup() + duk_replace(), but because they're used quite a lot
77096 		 * they're currently intentionally not size optimized.
77097 		 */
77098 		case DUK_OP_LDREG: {
77099 			duk_tval *tv1, *tv2;
77100 
77101 			tv1 = DUK__REGP_A(ins);
77102 			tv2 = DUK__REGP_BC(ins);
77103 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
77104 			break;
77105 		}
77106 
77107 		case DUK_OP_STREG: {
77108 			duk_tval *tv1, *tv2;
77109 
77110 			tv1 = DUK__REGP_A(ins);
77111 			tv2 = DUK__REGP_BC(ins);
77112 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv2, tv1);  /* side effects */
77113 			break;
77114 		}
77115 
77116 		case DUK_OP_LDCONST: {
77117 			duk_tval *tv1, *tv2;
77118 
77119 			tv1 = DUK__REGP_A(ins);
77120 			tv2 = DUK__CONSTP_BC(ins);
77121 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
77122 			break;
77123 		}
77124 
77125 		/* LDINT and LDINTX are intended to load an arbitrary signed
77126 		 * 32-bit value.  Only an LDINT+LDINTX sequence is supported.
77127 		 * This also guarantees all values remain fastints.
77128 		 */
77129 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77130 		case DUK_OP_LDINT: {
77131 			duk_int32_t val;
77132 
77133 			val = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;
77134 			duk_push_int(thr, val);
77135 			DUK__REPLACE_TOP_A_BREAK();
77136 		}
77137 		case DUK_OP_LDINTX: {
77138 			duk_int32_t val;
77139 
77140 			val = (duk_int32_t) duk_get_int(thr, DUK_DEC_A(ins));
77141 			val = (val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins);  /* no bias */
77142 			duk_push_int(thr, val);
77143 			DUK__REPLACE_TOP_A_BREAK();
77144 		}
77145 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77146 		case DUK_OP_LDINT: {
77147 			duk_tval *tv1;
77148 			duk_int32_t val;
77149 
77150 			val = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;
77151 			tv1 = DUK__REGP_A(ins);
77152 			DUK_TVAL_SET_I32_UPDREF(thr, tv1, val);  /* side effects */
77153 			break;
77154 		}
77155 		case DUK_OP_LDINTX: {
77156 			duk_tval *tv1;
77157 			duk_int32_t val;
77158 
77159 			tv1 = DUK__REGP_A(ins);
77160 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
77161 #if defined(DUK_USE_FASTINT)
77162 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
77163 			val = DUK_TVAL_GET_FASTINT_I32(tv1);
77164 #else
77165 			/* XXX: fast double-to-int conversion, we know number is integer in [-0x80000000,0xffffffff]. */
77166 			val = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv1);
77167 #endif
77168 			val = (duk_int32_t) ((duk_uint32_t) val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins);  /* no bias */
77169 			DUK_TVAL_SET_I32_UPDREF(thr, tv1, val);  /* side effects */
77170 			break;
77171 		}
77172 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77173 
77174 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77175 		case DUK_OP_LDTHIS: {
77176 			duk_push_this(thr);
77177 			DUK__REPLACE_TOP_BC_BREAK();
77178 		}
77179 		case DUK_OP_LDUNDEF: {
77180 			duk_to_undefined(thr, (duk_idx_t) DUK_DEC_BC(ins));
77181 			break;
77182 		}
77183 		case DUK_OP_LDNULL: {
77184 			duk_to_null(thr, (duk_idx_t) DUK_DEC_BC(ins));
77185 			break;
77186 		}
77187 		case DUK_OP_LDTRUE: {
77188 			duk_push_true(thr);
77189 			DUK__REPLACE_TOP_BC_BREAK();
77190 		}
77191 		case DUK_OP_LDFALSE: {
77192 			duk_push_false(thr);
77193 			DUK__REPLACE_TOP_BC_BREAK();
77194 		}
77195 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77196 		case DUK_OP_LDTHIS: {
77197 			/* Note: 'this' may be bound to any value, not just an object */
77198 			duk_tval *tv1, *tv2;
77199 
77200 			tv1 = DUK__REGP_BC(ins);
77201 			tv2 = thr->valstack_bottom - 1;  /* 'this binding' is just under bottom */
77202 			DUK_ASSERT(tv2 >= thr->valstack);
77203 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
77204 			break;
77205 		}
77206 		case DUK_OP_LDUNDEF: {
77207 			duk_tval *tv1;
77208 
77209 			tv1 = DUK__REGP_BC(ins);
77210 			DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
77211 			break;
77212 		}
77213 		case DUK_OP_LDNULL: {
77214 			duk_tval *tv1;
77215 
77216 			tv1 = DUK__REGP_BC(ins);
77217 			DUK_TVAL_SET_NULL_UPDREF(thr, tv1);  /* side effects */
77218 			break;
77219 		}
77220 		case DUK_OP_LDTRUE: {
77221 			duk_tval *tv1;
77222 
77223 			tv1 = DUK__REGP_BC(ins);
77224 			DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 1);  /* side effects */
77225 			break;
77226 		}
77227 		case DUK_OP_LDFALSE: {
77228 			duk_tval *tv1;
77229 
77230 			tv1 = DUK__REGP_BC(ins);
77231 			DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 0);  /* side effects */
77232 			break;
77233 		}
77234 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77235 
77236 		case DUK_OP_BNOT: {
77237 			duk__vm_bitwise_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));
77238 			break;
77239 		}
77240 
77241 		case DUK_OP_LNOT: {
77242 			duk__vm_logical_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));
77243 			break;
77244 		}
77245 
77246 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77247 		case DUK_OP_UNM:
77248 		case DUK_OP_UNP: {
77249 			duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), op);
77250 			break;
77251 		}
77252 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77253 		case DUK_OP_UNM: {
77254 			duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), DUK_OP_UNM);
77255 			break;
77256 		}
77257 		case DUK_OP_UNP: {
77258 			duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), DUK_OP_UNP);
77259 			break;
77260 		}
77261 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77262 
77263 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77264 		case DUK_OP_TYPEOF: {
77265 			duk_small_uint_t stridx;
77266 
77267 			stridx = duk_js_typeof_stridx(DUK__REGP_BC(ins));
77268 			DUK_ASSERT_STRIDX_VALID(stridx);
77269 			duk_push_hstring_stridx(thr, stridx);
77270 			DUK__REPLACE_TOP_A_BREAK();
77271 		}
77272 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77273 		case DUK_OP_TYPEOF: {
77274 			duk_tval *tv;
77275 			duk_small_uint_t stridx;
77276 			duk_hstring *h_str;
77277 
77278 			tv = DUK__REGP_BC(ins);
77279 			stridx = duk_js_typeof_stridx(tv);
77280 			DUK_ASSERT_STRIDX_VALID(stridx);
77281 			h_str = DUK_HTHREAD_GET_STRING(thr, stridx);
77282 			tv = DUK__REGP_A(ins);
77283 			DUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);
77284 			break;
77285 		}
77286 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77287 
77288 		case DUK_OP_TYPEOFID: {
77289 			duk_small_uint_t stridx;
77290 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
77291 			duk_hstring *h_str;
77292 #endif
77293 			duk_activation *act;
77294 			duk_hstring *name;
77295 			duk_tval *tv;
77296 
77297 			/* A -> target register
77298 			 * BC -> constant index of identifier name
77299 			 */
77300 
77301 			tv = DUK__CONSTP_BC(ins);
77302 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv));
77303 			name = DUK_TVAL_GET_STRING(tv);
77304 			tv = NULL;  /* lookup has side effects */
77305 			act = thr->callstack_curr;
77306 			if (duk_js_getvar_activation(thr, act, name, 0 /*throw*/)) {
77307 				/* -> [... val this] */
77308 				tv = DUK_GET_TVAL_NEGIDX(thr, -2);
77309 				stridx = duk_js_typeof_stridx(tv);
77310 				tv = NULL;  /* no longer needed */
77311 				duk_pop_2_unsafe(thr);
77312 			} else {
77313 				/* unresolvable, no stack changes */
77314 				stridx = DUK_STRIDX_LC_UNDEFINED;
77315 			}
77316 			DUK_ASSERT_STRIDX_VALID(stridx);
77317 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77318 			duk_push_hstring_stridx(thr, stridx);
77319 			DUK__REPLACE_TOP_A_BREAK();
77320 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77321 			h_str = DUK_HTHREAD_GET_STRING(thr, stridx);
77322 			tv = DUK__REGP_A(ins);
77323 			DUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);
77324 			break;
77325 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77326 		}
77327 
77328 		/* Equality: E5 Sections 11.9.1, 11.9.3 */
77329 
77330 #define DUK__EQ_BODY(barg,carg) { \
77331 		duk_bool_t tmp; \
77332 		tmp = duk_js_equals(thr, (barg), (carg)); \
77333 		DUK_ASSERT(tmp == 0 || tmp == 1); \
77334 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
77335 	}
77336 #define DUK__NEQ_BODY(barg,carg) { \
77337 		duk_bool_t tmp; \
77338 		tmp = duk_js_equals(thr, (barg), (carg)); \
77339 		DUK_ASSERT(tmp == 0 || tmp == 1); \
77340 		tmp ^= 1; \
77341 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
77342 	}
77343 #define DUK__SEQ_BODY(barg,carg) { \
77344 		duk_bool_t tmp; \
77345 		tmp = duk_js_strict_equals((barg), (carg)); \
77346 		DUK_ASSERT(tmp == 0 || tmp == 1); \
77347 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
77348 	}
77349 #define DUK__SNEQ_BODY(barg,carg) { \
77350 		duk_bool_t tmp; \
77351 		tmp = duk_js_strict_equals((barg), (carg)); \
77352 		DUK_ASSERT(tmp == 0 || tmp == 1); \
77353 		tmp ^= 1; \
77354 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
77355 	}
77356 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77357 		case DUK_OP_EQ_RR:
77358 		case DUK_OP_EQ_CR:
77359 		case DUK_OP_EQ_RC:
77360 		case DUK_OP_EQ_CC:
77361 			DUK__EQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77362 		case DUK_OP_NEQ_RR:
77363 		case DUK_OP_NEQ_CR:
77364 		case DUK_OP_NEQ_RC:
77365 		case DUK_OP_NEQ_CC:
77366 			DUK__NEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77367 		case DUK_OP_SEQ_RR:
77368 		case DUK_OP_SEQ_CR:
77369 		case DUK_OP_SEQ_RC:
77370 		case DUK_OP_SEQ_CC:
77371 			DUK__SEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77372 		case DUK_OP_SNEQ_RR:
77373 		case DUK_OP_SNEQ_CR:
77374 		case DUK_OP_SNEQ_RC:
77375 		case DUK_OP_SNEQ_CC:
77376 			DUK__SNEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77377 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77378 		case DUK_OP_EQ_RR:
77379 			DUK__EQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77380 		case DUK_OP_EQ_CR:
77381 			DUK__EQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77382 		case DUK_OP_EQ_RC:
77383 			DUK__EQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77384 		case DUK_OP_EQ_CC:
77385 			DUK__EQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77386 		case DUK_OP_NEQ_RR:
77387 			DUK__NEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77388 		case DUK_OP_NEQ_CR:
77389 			DUK__NEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77390 		case DUK_OP_NEQ_RC:
77391 			DUK__NEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77392 		case DUK_OP_NEQ_CC:
77393 			DUK__NEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77394 		case DUK_OP_SEQ_RR:
77395 			DUK__SEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77396 		case DUK_OP_SEQ_CR:
77397 			DUK__SEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77398 		case DUK_OP_SEQ_RC:
77399 			DUK__SEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77400 		case DUK_OP_SEQ_CC:
77401 			DUK__SEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77402 		case DUK_OP_SNEQ_RR:
77403 			DUK__SNEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77404 		case DUK_OP_SNEQ_CR:
77405 			DUK__SNEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77406 		case DUK_OP_SNEQ_RC:
77407 			DUK__SNEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77408 		case DUK_OP_SNEQ_CC:
77409 			DUK__SNEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77410 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77411 
77412 #define DUK__COMPARE_BODY(arg1,arg2,flags) { \
77413 		duk_bool_t tmp; \
77414 		tmp = duk_js_compare_helper(thr, (arg1), (arg2), (flags)); \
77415 		DUK_ASSERT(tmp == 0 || tmp == 1); \
77416 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
77417 	}
77418 #define DUK__GT_BODY(barg,carg) DUK__COMPARE_BODY((carg), (barg), 0)
77419 #define DUK__GE_BODY(barg,carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
77420 #define DUK__LT_BODY(barg,carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
77421 #define DUK__LE_BODY(barg,carg) DUK__COMPARE_BODY((carg), (barg), DUK_COMPARE_FLAG_NEGATE)
77422 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77423 		case DUK_OP_GT_RR:
77424 		case DUK_OP_GT_CR:
77425 		case DUK_OP_GT_RC:
77426 		case DUK_OP_GT_CC:
77427 			DUK__GT_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77428 		case DUK_OP_GE_RR:
77429 		case DUK_OP_GE_CR:
77430 		case DUK_OP_GE_RC:
77431 		case DUK_OP_GE_CC:
77432 			DUK__GE_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77433 		case DUK_OP_LT_RR:
77434 		case DUK_OP_LT_CR:
77435 		case DUK_OP_LT_RC:
77436 		case DUK_OP_LT_CC:
77437 			DUK__LT_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77438 		case DUK_OP_LE_RR:
77439 		case DUK_OP_LE_CR:
77440 		case DUK_OP_LE_RC:
77441 		case DUK_OP_LE_CC:
77442 			DUK__LE_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77443 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77444 		case DUK_OP_GT_RR:
77445 			DUK__GT_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77446 		case DUK_OP_GT_CR:
77447 			DUK__GT_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77448 		case DUK_OP_GT_RC:
77449 			DUK__GT_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77450 		case DUK_OP_GT_CC:
77451 			DUK__GT_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77452 		case DUK_OP_GE_RR:
77453 			DUK__GE_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77454 		case DUK_OP_GE_CR:
77455 			DUK__GE_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77456 		case DUK_OP_GE_RC:
77457 			DUK__GE_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77458 		case DUK_OP_GE_CC:
77459 			DUK__GE_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77460 		case DUK_OP_LT_RR:
77461 			DUK__LT_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77462 		case DUK_OP_LT_CR:
77463 			DUK__LT_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77464 		case DUK_OP_LT_RC:
77465 			DUK__LT_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77466 		case DUK_OP_LT_CC:
77467 			DUK__LT_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77468 		case DUK_OP_LE_RR:
77469 			DUK__LE_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77470 		case DUK_OP_LE_CR:
77471 			DUK__LE_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77472 		case DUK_OP_LE_RC:
77473 			DUK__LE_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77474 		case DUK_OP_LE_CC:
77475 			DUK__LE_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77476 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77477 
77478 		/* No size optimized variant at present for IF. */
77479 		case DUK_OP_IFTRUE_R: {
77480 			if (duk_js_toboolean(DUK__REGP_BC(ins)) != 0) {
77481 				curr_pc++;
77482 			}
77483 			break;
77484 		}
77485 		case DUK_OP_IFTRUE_C: {
77486 			if (duk_js_toboolean(DUK__CONSTP_BC(ins)) != 0) {
77487 				curr_pc++;
77488 			}
77489 			break;
77490 		}
77491 		case DUK_OP_IFFALSE_R: {
77492 			if (duk_js_toboolean(DUK__REGP_BC(ins)) == 0) {
77493 				curr_pc++;
77494 			}
77495 			break;
77496 		}
77497 		case DUK_OP_IFFALSE_C: {
77498 			if (duk_js_toboolean(DUK__CONSTP_BC(ins)) == 0) {
77499 				curr_pc++;
77500 			}
77501 			break;
77502 		}
77503 
77504 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77505 		case DUK_OP_ADD_RR:
77506 		case DUK_OP_ADD_CR:
77507 		case DUK_OP_ADD_RC:
77508 		case DUK_OP_ADD_CC: {
77509 			/* XXX: could leave value on stack top and goto replace_top_a; */
77510 			duk__vm_arith_add(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins));
77511 			break;
77512 		}
77513 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77514 		case DUK_OP_ADD_RR: {
77515 			duk__vm_arith_add(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins));
77516 			break;
77517 		}
77518 		case DUK_OP_ADD_CR: {
77519 			duk__vm_arith_add(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins));
77520 			break;
77521 		}
77522 		case DUK_OP_ADD_RC: {
77523 			duk__vm_arith_add(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins));
77524 			break;
77525 		}
77526 		case DUK_OP_ADD_CC: {
77527 			duk__vm_arith_add(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins));
77528 			break;
77529 		}
77530 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77531 
77532 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77533 		case DUK_OP_SUB_RR:
77534 		case DUK_OP_SUB_CR:
77535 		case DUK_OP_SUB_RC:
77536 		case DUK_OP_SUB_CC:
77537 		case DUK_OP_MUL_RR:
77538 		case DUK_OP_MUL_CR:
77539 		case DUK_OP_MUL_RC:
77540 		case DUK_OP_MUL_CC:
77541 		case DUK_OP_DIV_RR:
77542 		case DUK_OP_DIV_CR:
77543 		case DUK_OP_DIV_RC:
77544 		case DUK_OP_DIV_CC:
77545 		case DUK_OP_MOD_RR:
77546 		case DUK_OP_MOD_CR:
77547 		case DUK_OP_MOD_RC:
77548 		case DUK_OP_MOD_CC:
77549 #if defined(DUK_USE_ES7_EXP_OPERATOR)
77550 		case DUK_OP_EXP_RR:
77551 		case DUK_OP_EXP_CR:
77552 		case DUK_OP_EXP_RC:
77553 		case DUK_OP_EXP_CC:
77554 #endif  /* DUK_USE_ES7_EXP_OPERATOR */
77555 		{
77556 			/* XXX: could leave value on stack top and goto replace_top_a; */
77557 			duk__vm_arith_binary_op(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins), op);
77558 			break;
77559 		}
77560 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77561 		case DUK_OP_SUB_RR: {
77562 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
77563 			break;
77564 		}
77565 		case DUK_OP_SUB_CR: {
77566 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
77567 			break;
77568 		}
77569 		case DUK_OP_SUB_RC: {
77570 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
77571 			break;
77572 		}
77573 		case DUK_OP_SUB_CC: {
77574 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
77575 			break;
77576 		}
77577 		case DUK_OP_MUL_RR: {
77578 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
77579 			break;
77580 		}
77581 		case DUK_OP_MUL_CR: {
77582 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
77583 			break;
77584 		}
77585 		case DUK_OP_MUL_RC: {
77586 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
77587 			break;
77588 		}
77589 		case DUK_OP_MUL_CC: {
77590 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
77591 			break;
77592 		}
77593 		case DUK_OP_DIV_RR: {
77594 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
77595 			break;
77596 		}
77597 		case DUK_OP_DIV_CR: {
77598 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
77599 			break;
77600 		}
77601 		case DUK_OP_DIV_RC: {
77602 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
77603 			break;
77604 		}
77605 		case DUK_OP_DIV_CC: {
77606 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
77607 			break;
77608 		}
77609 		case DUK_OP_MOD_RR: {
77610 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
77611 			break;
77612 		}
77613 		case DUK_OP_MOD_CR: {
77614 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
77615 			break;
77616 		}
77617 		case DUK_OP_MOD_RC: {
77618 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
77619 			break;
77620 		}
77621 		case DUK_OP_MOD_CC: {
77622 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
77623 			break;
77624 		}
77625 #if defined(DUK_USE_ES7_EXP_OPERATOR)
77626 		case DUK_OP_EXP_RR: {
77627 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
77628 			break;
77629 		}
77630 		case DUK_OP_EXP_CR: {
77631 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
77632 			break;
77633 		}
77634 		case DUK_OP_EXP_RC: {
77635 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
77636 			break;
77637 		}
77638 		case DUK_OP_EXP_CC: {
77639 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
77640 			break;
77641 		}
77642 #endif  /* DUK_USE_ES7_EXP_OPERATOR */
77643 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77644 
77645 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77646 		case DUK_OP_BAND_RR:
77647 		case DUK_OP_BAND_CR:
77648 		case DUK_OP_BAND_RC:
77649 		case DUK_OP_BAND_CC:
77650 		case DUK_OP_BOR_RR:
77651 		case DUK_OP_BOR_CR:
77652 		case DUK_OP_BOR_RC:
77653 		case DUK_OP_BOR_CC:
77654 		case DUK_OP_BXOR_RR:
77655 		case DUK_OP_BXOR_CR:
77656 		case DUK_OP_BXOR_RC:
77657 		case DUK_OP_BXOR_CC:
77658 		case DUK_OP_BASL_RR:
77659 		case DUK_OP_BASL_CR:
77660 		case DUK_OP_BASL_RC:
77661 		case DUK_OP_BASL_CC:
77662 		case DUK_OP_BLSR_RR:
77663 		case DUK_OP_BLSR_CR:
77664 		case DUK_OP_BLSR_RC:
77665 		case DUK_OP_BLSR_CC:
77666 		case DUK_OP_BASR_RR:
77667 		case DUK_OP_BASR_CR:
77668 		case DUK_OP_BASR_RC:
77669 		case DUK_OP_BASR_CC: {
77670 			/* XXX: could leave value on stack top and goto replace_top_a; */
77671 			duk__vm_bitwise_binary_op(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins), op);
77672 			break;
77673 		}
77674 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77675 		case DUK_OP_BAND_RR: {
77676 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
77677 			break;
77678 		}
77679 		case DUK_OP_BAND_CR: {
77680 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
77681 			break;
77682 		}
77683 		case DUK_OP_BAND_RC: {
77684 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
77685 			break;
77686 		}
77687 		case DUK_OP_BAND_CC: {
77688 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
77689 			break;
77690 		}
77691 		case DUK_OP_BOR_RR: {
77692 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
77693 			break;
77694 		}
77695 		case DUK_OP_BOR_CR: {
77696 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
77697 			break;
77698 		}
77699 		case DUK_OP_BOR_RC: {
77700 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
77701 			break;
77702 		}
77703 		case DUK_OP_BOR_CC: {
77704 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
77705 			break;
77706 		}
77707 		case DUK_OP_BXOR_RR: {
77708 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
77709 			break;
77710 		}
77711 		case DUK_OP_BXOR_CR: {
77712 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
77713 			break;
77714 		}
77715 		case DUK_OP_BXOR_RC: {
77716 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
77717 			break;
77718 		}
77719 		case DUK_OP_BXOR_CC: {
77720 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
77721 			break;
77722 		}
77723 		case DUK_OP_BASL_RR: {
77724 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
77725 			break;
77726 		}
77727 		case DUK_OP_BASL_CR: {
77728 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
77729 			break;
77730 		}
77731 		case DUK_OP_BASL_RC: {
77732 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
77733 			break;
77734 		}
77735 		case DUK_OP_BASL_CC: {
77736 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
77737 			break;
77738 		}
77739 		case DUK_OP_BLSR_RR: {
77740 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
77741 			break;
77742 		}
77743 		case DUK_OP_BLSR_CR: {
77744 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
77745 			break;
77746 		}
77747 		case DUK_OP_BLSR_RC: {
77748 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
77749 			break;
77750 		}
77751 		case DUK_OP_BLSR_CC: {
77752 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
77753 			break;
77754 		}
77755 		case DUK_OP_BASR_RR: {
77756 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
77757 			break;
77758 		}
77759 		case DUK_OP_BASR_CR: {
77760 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
77761 			break;
77762 		}
77763 		case DUK_OP_BASR_RC: {
77764 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
77765 			break;
77766 		}
77767 		case DUK_OP_BASR_CC: {
77768 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
77769 			break;
77770 		}
77771 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77772 
77773 		/* For INSTOF and IN, B is always a register. */
77774 #define DUK__INSTOF_BODY(barg,carg) { \
77775 		duk_bool_t tmp; \
77776 		tmp = duk_js_instanceof(thr, (barg), (carg)); \
77777 		DUK_ASSERT(tmp == 0 || tmp == 1); \
77778 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
77779 	}
77780 #define DUK__IN_BODY(barg,carg) { \
77781 		duk_bool_t tmp; \
77782 		tmp = duk_js_in(thr, (barg), (carg)); \
77783 		DUK_ASSERT(tmp == 0 || tmp == 1); \
77784 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
77785 	}
77786 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77787 		case DUK_OP_INSTOF_RR:
77788 		case DUK_OP_INSTOF_CR:
77789 		case DUK_OP_INSTOF_RC:
77790 		case DUK_OP_INSTOF_CC:
77791 			DUK__INSTOF_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77792 		case DUK_OP_IN_RR:
77793 		case DUK_OP_IN_CR:
77794 		case DUK_OP_IN_RC:
77795 		case DUK_OP_IN_CC:
77796 			DUK__IN_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77797 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77798 		case DUK_OP_INSTOF_RR:
77799 			DUK__INSTOF_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77800 		case DUK_OP_INSTOF_CR:
77801 			DUK__INSTOF_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77802 		case DUK_OP_INSTOF_RC:
77803 			DUK__INSTOF_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77804 		case DUK_OP_INSTOF_CC:
77805 			DUK__INSTOF_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77806 		case DUK_OP_IN_RR:
77807 			DUK__IN_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77808 		case DUK_OP_IN_CR:
77809 			DUK__IN_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77810 		case DUK_OP_IN_RC:
77811 			DUK__IN_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77812 		case DUK_OP_IN_CC:
77813 			DUK__IN_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77814 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77815 
77816 		/* Pre/post inc/dec for register variables, important for loops. */
77817 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77818 		case DUK_OP_PREINCR:
77819 		case DUK_OP_PREDECR:
77820 		case DUK_OP_POSTINCR:
77821 		case DUK_OP_POSTDECR: {
77822 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), op);
77823 			break;
77824 		}
77825 		case DUK_OP_PREINCV:
77826 		case DUK_OP_PREDECV:
77827 		case DUK_OP_POSTINCV:
77828 		case DUK_OP_POSTDECV: {
77829 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), op, DUK__STRICT());
77830 			break;
77831 		}
77832 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77833 		case DUK_OP_PREINCR: {
77834 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_PREINCR);
77835 			break;
77836 		}
77837 		case DUK_OP_PREDECR: {
77838 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_PREDECR);
77839 			break;
77840 		}
77841 		case DUK_OP_POSTINCR: {
77842 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_POSTINCR);
77843 			break;
77844 		}
77845 		case DUK_OP_POSTDECR: {
77846 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_POSTDECR);
77847 			break;
77848 		}
77849 		case DUK_OP_PREINCV: {
77850 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_PREINCV, DUK__STRICT());
77851 			break;
77852 		}
77853 		case DUK_OP_PREDECV: {
77854 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_PREDECV, DUK__STRICT());
77855 			break;
77856 		}
77857 		case DUK_OP_POSTINCV: {
77858 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_POSTINCV, DUK__STRICT());
77859 			break;
77860 		}
77861 		case DUK_OP_POSTDECV: {
77862 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_POSTDECV, DUK__STRICT());
77863 			break;
77864 		}
77865 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77866 
77867 		/* XXX: Move to separate helper, optimize for perf/size separately. */
77868 		/* Preinc/predec for object properties. */
77869 		case DUK_OP_PREINCP_RR:
77870 		case DUK_OP_PREINCP_CR:
77871 		case DUK_OP_PREINCP_RC:
77872 		case DUK_OP_PREINCP_CC:
77873 		case DUK_OP_PREDECP_RR:
77874 		case DUK_OP_PREDECP_CR:
77875 		case DUK_OP_PREDECP_RC:
77876 		case DUK_OP_PREDECP_CC:
77877 		case DUK_OP_POSTINCP_RR:
77878 		case DUK_OP_POSTINCP_CR:
77879 		case DUK_OP_POSTINCP_RC:
77880 		case DUK_OP_POSTINCP_CC:
77881 		case DUK_OP_POSTDECP_RR:
77882 		case DUK_OP_POSTDECP_CR:
77883 		case DUK_OP_POSTDECP_RC:
77884 		case DUK_OP_POSTDECP_CC: {
77885 			duk_tval *tv_obj;
77886 			duk_tval *tv_key;
77887 			duk_tval *tv_val;
77888 			duk_bool_t rc;
77889 			duk_double_t x, y, z;
77890 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
77891 			duk_tval *tv_dst;
77892 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77893 
77894 			/* A -> target reg
77895 			 * B -> object reg/const (may be const e.g. in "'foo'[1]")
77896 			 * C -> key reg/const
77897 			 */
77898 
77899 			/* Opcode bits 0-1 are used to distinguish reg/const variants.
77900 			 * Opcode bits 2-3 are used to distinguish inc/dec variants:
77901 			 * Bit 2 = inc(0)/dec(1), bit 3 = pre(0)/post(1).
77902 			 */
77903 			DUK_ASSERT((DUK_OP_PREINCP_RR & 0x0c) == 0x00);
77904 			DUK_ASSERT((DUK_OP_PREDECP_RR & 0x0c) == 0x04);
77905 			DUK_ASSERT((DUK_OP_POSTINCP_RR & 0x0c) == 0x08);
77906 			DUK_ASSERT((DUK_OP_POSTDECP_RR & 0x0c) == 0x0c);
77907 
77908 			tv_obj = DUK__REGCONSTP_B(ins);
77909 			tv_key = DUK__REGCONSTP_C(ins);
77910 			rc = duk_hobject_getprop(thr, tv_obj, tv_key);  /* -> [val] */
77911 			DUK_UNREF(rc);  /* ignore */
77912 			tv_obj = NULL;  /* invalidated */
77913 			tv_key = NULL;  /* invalidated */
77914 
77915 			/* XXX: Fastint fast path would be useful here.  Also fastints
77916 			 * now lose their fastint status in current handling which is
77917 			 * not intuitive.
77918 			 */
77919 
77920 			x = duk_to_number_m1(thr);
77921 			duk_pop_unsafe(thr);
77922 			if (ins & DUK_BC_INCDECP_FLAG_DEC) {
77923 				y = x - 1.0;
77924 			} else {
77925 				y = x + 1.0;
77926 			}
77927 
77928 			duk_push_number(thr, y);
77929 			tv_val = DUK_GET_TVAL_NEGIDX(thr, -1);
77930 			DUK_ASSERT(tv_val != NULL);
77931 			tv_obj = DUK__REGCONSTP_B(ins);
77932 			tv_key = DUK__REGCONSTP_C(ins);
77933 			rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT());
77934 			DUK_UNREF(rc);  /* ignore */
77935 			tv_obj = NULL;  /* invalidated */
77936 			tv_key = NULL;  /* invalidated */
77937 			duk_pop_unsafe(thr);
77938 
77939 			z = (ins & DUK_BC_INCDECP_FLAG_POST) ? x : y;
77940 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77941 			duk_push_number(thr, z);
77942 			DUK__REPLACE_TOP_A_BREAK();
77943 #else
77944 			tv_dst = DUK__REGP_A(ins);
77945 			DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z);
77946 			break;
77947 #endif
77948 		}
77949 
77950 		/* XXX: GETPROP where object is 'this', GETPROPT?
77951 		 * Occurs relatively often in object oriented code.
77952 		 */
77953 
77954 #define DUK__GETPROP_BODY(barg,carg) { \
77955 		/* A -> target reg \
77956 		 * B -> object reg/const (may be const e.g. in "'foo'[1]") \
77957 		 * C -> key reg/const \
77958 		 */ \
77959 		(void) duk_hobject_getprop(thr, (barg), (carg)); \
77960 		DUK__REPLACE_TOP_A_BREAK(); \
77961 	}
77962 #define DUK__GETPROPC_BODY(barg,carg) { \
77963 		/* Same as GETPROP but callability check for property-based calls. */ \
77964 		duk_tval *tv__targ; \
77965 		(void) duk_hobject_getprop(thr, (barg), (carg)); \
77966 		DUK_GC_TORTURE(thr->heap); \
77967 		tv__targ = DUK_GET_TVAL_NEGIDX(thr, -1); \
77968 		if (DUK_UNLIKELY(!duk_is_callable_tval(thr, tv__targ))) { \
77969 			/* Here we intentionally re-evaluate the macro \
77970 			 * arguments to deal with potentially changed \
77971 			 * valstack base pointer! \
77972 			 */ \
77973 			duk_call_setup_propcall_error(thr, (barg), (carg)); \
77974 		} \
77975 		DUK__REPLACE_TOP_A_BREAK(); \
77976 	}
77977 #define DUK__PUTPROP_BODY(aarg,barg,carg) { \
77978 		/* A -> object reg \
77979 		 * B -> key reg/const \
77980 		 * C -> value reg/const \
77981 		 * \
77982 		 * Note: intentional difference to register arrangement \
77983 		 * of e.g. GETPROP; 'A' must contain a register-only value. \
77984 		 */ \
77985 		(void) duk_hobject_putprop(thr, (aarg), (barg), (carg), DUK__STRICT()); \
77986 		break; \
77987 	}
77988 #define DUK__DELPROP_BODY(barg,carg) { \
77989 		/* A -> result reg \
77990 		 * B -> object reg \
77991 		 * C -> key reg/const \
77992 		 */ \
77993 		duk_bool_t rc; \
77994 		rc = duk_hobject_delprop(thr, (barg), (carg), DUK__STRICT()); \
77995 		DUK_ASSERT(rc == 0 || rc == 1); \
77996 		DUK__REPLACE_BOOL_A_BREAK(rc); \
77997 	}
77998 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77999 		case DUK_OP_GETPROP_RR:
78000 		case DUK_OP_GETPROP_CR:
78001 		case DUK_OP_GETPROP_RC:
78002 		case DUK_OP_GETPROP_CC:
78003 			DUK__GETPROP_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
78004 #if defined(DUK_USE_VERBOSE_ERRORS)
78005 		case DUK_OP_GETPROPC_RR:
78006 		case DUK_OP_GETPROPC_CR:
78007 		case DUK_OP_GETPROPC_RC:
78008 		case DUK_OP_GETPROPC_CC:
78009 			DUK__GETPROPC_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
78010 #endif
78011 		case DUK_OP_PUTPROP_RR:
78012 		case DUK_OP_PUTPROP_CR:
78013 		case DUK_OP_PUTPROP_RC:
78014 		case DUK_OP_PUTPROP_CC:
78015 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
78016 		case DUK_OP_DELPROP_RR:
78017 		case DUK_OP_DELPROP_RC:  /* B is always reg */
78018 			DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__REGCONSTP_C(ins));
78019 #else  /* DUK_USE_EXEC_PREFER_SIZE */
78020 		case DUK_OP_GETPROP_RR:
78021 			DUK__GETPROP_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
78022 		case DUK_OP_GETPROP_CR:
78023 			DUK__GETPROP_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
78024 		case DUK_OP_GETPROP_RC:
78025 			DUK__GETPROP_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
78026 		case DUK_OP_GETPROP_CC:
78027 			DUK__GETPROP_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
78028 #if defined(DUK_USE_VERBOSE_ERRORS)
78029 		case DUK_OP_GETPROPC_RR:
78030 			DUK__GETPROPC_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
78031 		case DUK_OP_GETPROPC_CR:
78032 			DUK__GETPROPC_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
78033 		case DUK_OP_GETPROPC_RC:
78034 			DUK__GETPROPC_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
78035 		case DUK_OP_GETPROPC_CC:
78036 			DUK__GETPROPC_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
78037 #endif
78038 		case DUK_OP_PUTPROP_RR:
78039 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGP_B(ins), DUK__REGP_C(ins));
78040 		case DUK_OP_PUTPROP_CR:
78041 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__CONSTP_B(ins), DUK__REGP_C(ins));
78042 		case DUK_OP_PUTPROP_RC:
78043 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGP_B(ins), DUK__CONSTP_C(ins));
78044 		case DUK_OP_PUTPROP_CC:
78045 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
78046 		case DUK_OP_DELPROP_RR:  /* B is always reg */
78047 			DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
78048 		case DUK_OP_DELPROP_RC:
78049 			DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
78050 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
78051 
78052 		/* No fast path for DECLVAR now, it's quite a rare instruction. */
78053 		case DUK_OP_DECLVAR_RR:
78054 		case DUK_OP_DECLVAR_CR:
78055 		case DUK_OP_DECLVAR_RC:
78056 		case DUK_OP_DECLVAR_CC: {
78057 			duk_activation *act;
78058 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
78059 			duk_tval *tv1;
78060 			duk_hstring *name;
78061 			duk_small_uint_t prop_flags;
78062 			duk_bool_t is_func_decl;
78063 
78064 			tv1 = DUK__REGCONSTP_B(ins);
78065 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
78066 			name = DUK_TVAL_GET_STRING(tv1);
78067 			DUK_ASSERT(name != NULL);
78068 
78069 			is_func_decl = ((a & DUK_BC_DECLVAR_FLAG_FUNC_DECL) != 0);
78070 
78071 			/* XXX: declvar takes an duk_tval pointer, which is awkward and
78072 			 * should be reworked.
78073 			 */
78074 
78075 			/* Compiler is responsible for selecting property flags (configurability,
78076 			 * writability, etc).
78077 			 */
78078 			prop_flags = a & DUK_PROPDESC_FLAGS_MASK;
78079 
78080 			if (is_func_decl) {
78081 				duk_push_tval(thr, DUK__REGCONSTP_C(ins));
78082 			} else {
78083 				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */
78084 				thr->valstack_top++;
78085 			}
78086 			tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
78087 
78088 			act = thr->callstack_curr;
78089 			if (duk_js_declvar_activation(thr, act, name, tv1, prop_flags, is_func_decl)) {
78090 				if (is_func_decl) {
78091 					/* Already declared, update value. */
78092 					tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
78093 					duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
78094 				} else {
78095 					/* Already declared but no initializer value
78096 					 * (e.g. 'var xyz;'), no-op.
78097 					 */
78098 				}
78099 			}
78100 
78101 			duk_pop_unsafe(thr);
78102 			break;
78103 		}
78104 
78105 #if defined(DUK_USE_REGEXP_SUPPORT)
78106 		/* The compiler should never emit DUK_OP_REGEXP if there is no
78107 		 * regexp support.
78108 		 */
78109 		case DUK_OP_REGEXP_RR:
78110 		case DUK_OP_REGEXP_CR:
78111 		case DUK_OP_REGEXP_RC:
78112 		case DUK_OP_REGEXP_CC: {
78113 			/* A -> target register
78114 			 * B -> bytecode (also contains flags)
78115 			 * C -> escaped source
78116 			 */
78117 
78118 			duk_push_tval(thr, DUK__REGCONSTP_C(ins));
78119 			duk_push_tval(thr, DUK__REGCONSTP_B(ins));  /* -> [ ... escaped_source bytecode ] */
78120 			duk_regexp_create_instance(thr);   /* -> [ ... regexp_instance ] */
78121 			DUK__REPLACE_TOP_A_BREAK();
78122 		}
78123 #endif  /* DUK_USE_REGEXP_SUPPORT */
78124 
78125 		/* XXX: 'c' is unused, use whole BC, etc. */
78126 		case DUK_OP_CSVAR_RR:
78127 		case DUK_OP_CSVAR_CR:
78128 		case DUK_OP_CSVAR_RC:
78129 		case DUK_OP_CSVAR_CC: {
78130 			/* The speciality of calling through a variable binding is that the
78131 			 * 'this' value may be provided by the variable lookup: E5 Section 6.b.i.
78132 			 *
78133 			 * The only (standard) case where the 'this' binding is non-null is when
78134 			 *   (1) the variable is found in an object environment record, and
78135 			 *   (2) that object environment record is a 'with' block.
78136 			 */
78137 
78138 			duk_activation *act;
78139 			duk_uint_fast_t idx;
78140 			duk_tval *tv1;
78141 			duk_hstring *name;
78142 
78143 			/* A -> target registers (A, A + 1) for call setup
78144 			 * B -> identifier name, usually constant but can be a register due to shuffling
78145 			 */
78146 
78147 			tv1 = DUK__REGCONSTP_B(ins);
78148 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
78149 			name = DUK_TVAL_GET_STRING(tv1);
78150 			DUK_ASSERT(name != NULL);
78151 			act = thr->callstack_curr;
78152 			(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */
78153 
78154 			idx = (duk_uint_fast_t) DUK_DEC_A(ins);
78155 
78156 			/* Could add direct value stack handling. */
78157 			duk_replace(thr, (duk_idx_t) (idx + 1));  /* 'this' binding */
78158 			duk_replace(thr, (duk_idx_t) idx);        /* variable value (function, we hope, not checked here) */
78159 			break;
78160 		}
78161 
78162 		case DUK_OP_CLOSURE: {
78163 			duk_activation *act;
78164 			duk_hcompfunc *fun_act;
78165 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
78166 			duk_hobject *fun_temp;
78167 
78168 			/* A -> target reg
78169 			 * BC -> inner function index
78170 			 */
78171 
78172 			DUK_DDD(DUK_DDDPRINT("CLOSURE to target register %ld, fnum %ld (count %ld)",
78173 			                     (long) DUK_DEC_A(ins), (long) DUK_DEC_BC(ins), (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN())));
78174 
78175 			DUK_ASSERT_DISABLE(bc >= 0); /* unsigned */
78176 			DUK_ASSERT((duk_uint_t) bc < (duk_uint_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN()));
78177 
78178 			act = thr->callstack_curr;
78179 			fun_act = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
78180 			fun_temp = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, fun_act)[bc];
78181 			DUK_ASSERT(fun_temp != NULL);
78182 			DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(fun_temp));
78183 
78184 			DUK_DDD(DUK_DDDPRINT("CLOSURE: function template is: %p -> %!O",
78185 			                     (void *) fun_temp, (duk_heaphdr *) fun_temp));
78186 
78187 			if (act->lex_env == NULL) {
78188 				DUK_ASSERT(act->var_env == NULL);
78189 				duk_js_init_activation_environment_records_delayed(thr, act);
78190 				act = thr->callstack_curr;
78191 			}
78192 			DUK_ASSERT(act->lex_env != NULL);
78193 			DUK_ASSERT(act->var_env != NULL);
78194 
78195 			/* functions always have a NEWENV flag, i.e. they get a
78196 			 * new variable declaration environment, so only lex_env
78197 			 * matters here.
78198 			 */
78199 			duk_js_push_closure(thr,
78200 			                    (duk_hcompfunc *) fun_temp,
78201 			                    act->var_env,
78202 			                    act->lex_env,
78203 			                    1 /*add_auto_proto*/);
78204 			DUK__REPLACE_TOP_A_BREAK();
78205 		}
78206 
78207 		case DUK_OP_GETVAR: {
78208 			duk_activation *act;
78209 			duk_tval *tv1;
78210 			duk_hstring *name;
78211 
78212 			tv1 = DUK__CONSTP_BC(ins);
78213 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
78214 			name = DUK_TVAL_GET_STRING(tv1);
78215 			DUK_ASSERT(name != NULL);
78216 			act = thr->callstack_curr;
78217 			DUK_ASSERT(act != NULL);
78218 			(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */
78219 			duk_pop_unsafe(thr);  /* 'this' binding is not needed here */
78220 			DUK__REPLACE_TOP_A_BREAK();
78221 		}
78222 
78223 		case DUK_OP_PUTVAR: {
78224 			duk_activation *act;
78225 			duk_tval *tv1;
78226 			duk_hstring *name;
78227 
78228 			tv1 = DUK__CONSTP_BC(ins);
78229 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
78230 			name = DUK_TVAL_GET_STRING(tv1);
78231 			DUK_ASSERT(name != NULL);
78232 
78233 			/* XXX: putvar takes a duk_tval pointer, which is awkward and
78234 			 * should be reworked.
78235 			 */
78236 
78237 			tv1 = DUK__REGP_A(ins);  /* val */
78238 			act = thr->callstack_curr;
78239 			duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
78240 			break;
78241 		}
78242 
78243 		case DUK_OP_DELVAR: {
78244 			duk_activation *act;
78245 			duk_tval *tv1;
78246 			duk_hstring *name;
78247 			duk_bool_t rc;
78248 
78249 			tv1 = DUK__CONSTP_BC(ins);
78250 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
78251 			name = DUK_TVAL_GET_STRING(tv1);
78252 			DUK_ASSERT(name != NULL);
78253 			act = thr->callstack_curr;
78254 			rc = duk_js_delvar_activation(thr, act, name);
78255 			DUK__REPLACE_BOOL_A_BREAK(rc);
78256 		}
78257 
78258 		case DUK_OP_JUMP: {
78259 			/* Note: without explicit cast to signed, MSVC will
78260 			 * apparently generate a large positive jump when the
78261 			 * bias-corrected value would normally be negative.
78262 			 */
78263 			curr_pc += (duk_int_fast_t) DUK_DEC_ABC(ins) - (duk_int_fast_t) DUK_BC_JUMP_BIAS;
78264 			break;
78265 		}
78266 
78267 #define DUK__RETURN_SHARED() do { \
78268 		duk_small_uint_t ret_result; \
78269 		/* duk__handle_return() is guaranteed never to throw, except \
78270 		 * for potential out-of-memory situations which will then \
78271 		 * propagate out of the executor longjmp handler. \
78272 		 */ \
78273 		DUK_ASSERT(thr->ptr_curr_pc == NULL); \
78274 		ret_result = duk__handle_return(thr, entry_act); \
78275 		if (ret_result == DUK__RETHAND_RESTART) { \
78276 			goto restart_execution; \
78277 		} \
78278 		DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED); \
78279 		return; \
78280 	} while (0)
78281 #if defined(DUK_USE_EXEC_PREFER_SIZE)
78282 		case DUK_OP_RETREG:
78283 		case DUK_OP_RETCONST:
78284 		case DUK_OP_RETCONSTN:
78285 		case DUK_OP_RETUNDEF: {
78286 			 /* BC -> return value reg/const */
78287 
78288 			DUK__SYNC_AND_NULL_CURR_PC();
78289 
78290 			if (op == DUK_OP_RETREG) {
78291 				duk_push_tval(thr, DUK__REGP_BC(ins));
78292 			} else if (op == DUK_OP_RETUNDEF) {
78293 				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */
78294 				thr->valstack_top++;
78295 			} else {
78296 				DUK_ASSERT(op == DUK_OP_RETCONST || op == DUK_OP_RETCONSTN);
78297 				duk_push_tval(thr, DUK__CONSTP_BC(ins));
78298 			}
78299 
78300 			DUK__RETURN_SHARED();
78301 		}
78302 #else  /* DUK_USE_EXEC_PREFER_SIZE */
78303 		case DUK_OP_RETREG: {
78304 			duk_tval *tv;
78305 
78306 			DUK__SYNC_AND_NULL_CURR_PC();
78307 			tv = DUK__REGP_BC(ins);
78308 			DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
78309 			DUK_TVAL_INCREF(thr, tv);
78310 			thr->valstack_top++;
78311 			DUK__RETURN_SHARED();
78312 		}
78313 		/* This will be unused without refcounting. */
78314 		case DUK_OP_RETCONST: {
78315 			duk_tval *tv;
78316 
78317 			DUK__SYNC_AND_NULL_CURR_PC();
78318 			tv = DUK__CONSTP_BC(ins);
78319 			DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
78320 			DUK_TVAL_INCREF(thr, tv);
78321 			thr->valstack_top++;
78322 			DUK__RETURN_SHARED();
78323 		}
78324 		case DUK_OP_RETCONSTN: {
78325 			duk_tval *tv;
78326 
78327 			DUK__SYNC_AND_NULL_CURR_PC();
78328 			tv = DUK__CONSTP_BC(ins);
78329 			DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
78330 #if defined(DUK_USE_REFERENCE_COUNTING)
78331 			/* Without refcounting only RETCONSTN is used. */
78332 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv));  /* no INCREF for this constant */
78333 #endif
78334 			thr->valstack_top++;
78335 			DUK__RETURN_SHARED();
78336 		}
78337 		case DUK_OP_RETUNDEF: {
78338 			DUK__SYNC_AND_NULL_CURR_PC();
78339 			thr->valstack_top++;  /* value at valstack top is already undefined by valstack policy */
78340 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
78341 			DUK__RETURN_SHARED();
78342 		}
78343 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
78344 
78345 		case DUK_OP_LABEL: {
78346 			duk_activation *act;
78347 			duk_catcher *cat;
78348 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
78349 
78350 			/* Allocate catcher and populate it (must be atomic). */
78351 
78352 			cat = duk_hthread_catcher_alloc(thr);
78353 			DUK_ASSERT(cat != NULL);
78354 
78355 			cat->flags = (duk_uint32_t) (DUK_CAT_TYPE_LABEL | (bc << DUK_CAT_LABEL_SHIFT));
78356 			cat->pc_base = (duk_instr_t *) curr_pc;  /* pre-incremented, points to first jump slot */
78357 			cat->idx_base = 0;  /* unused for label */
78358 			cat->h_varname = NULL;
78359 
78360 			act = thr->callstack_curr;
78361 			DUK_ASSERT(act != NULL);
78362 			cat->parent = act->cat;
78363 			act->cat = cat;
78364 
78365 			DUK_DDD(DUK_DDDPRINT("LABEL catcher: flags=0x%08lx, pc_base=%ld, "
78366 			                     "idx_base=%ld, h_varname=%!O, label_id=%ld",
78367 			                     (long) cat->flags, (long) cat->pc_base,
78368 			                     (long) cat->idx_base, (duk_heaphdr *) cat->h_varname, (long) DUK_CAT_GET_LABEL(cat)));
78369 
78370 			curr_pc += 2;  /* skip jump slots */
78371 			break;
78372 		}
78373 
78374 		case DUK_OP_ENDLABEL: {
78375 			duk_activation *act;
78376 #if (defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)) || defined(DUK_USE_ASSERTIONS)
78377 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
78378 #endif
78379 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
78380 			DUK_DDD(DUK_DDDPRINT("ENDLABEL %ld", (long) bc));
78381 #endif
78382 
78383 			act = thr->callstack_curr;
78384 			DUK_ASSERT(act->cat != NULL);
78385 			DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_LABEL);
78386 			DUK_ASSERT((duk_uint_fast_t) DUK_CAT_GET_LABEL(act->cat) == bc);
78387 			duk_hthread_catcher_unwind_nolexenv_norz(thr, act);
78388 
78389 			/* no need to unwind callstack */
78390 			break;
78391 		}
78392 
78393 		case DUK_OP_BREAK: {
78394 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
78395 
78396 			DUK__SYNC_AND_NULL_CURR_PC();
78397 			duk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_BREAK);
78398 			goto restart_execution;
78399 		}
78400 
78401 		case DUK_OP_CONTINUE: {
78402 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
78403 
78404 			DUK__SYNC_AND_NULL_CURR_PC();
78405 			duk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_CONTINUE);
78406 			goto restart_execution;
78407 		}
78408 
78409 		/* XXX: move to helper, too large to be inline here */
78410 		case DUK_OP_TRYCATCH: {
78411 			duk__handle_op_trycatch(thr, ins, curr_pc);
78412 			curr_pc += 2;  /* skip jump slots */
78413 			break;
78414 		}
78415 
78416 		case DUK_OP_ENDTRY: {
78417 			curr_pc = duk__handle_op_endtry(thr, ins);
78418 			break;
78419 		}
78420 
78421 		case DUK_OP_ENDCATCH: {
78422 			duk__handle_op_endcatch(thr, ins);
78423 			break;
78424 		}
78425 
78426 		case DUK_OP_ENDFIN: {
78427 			/* Sync and NULL early. */
78428 			DUK__SYNC_AND_NULL_CURR_PC();
78429 
78430 			if (duk__handle_op_endfin(thr, ins, entry_act) != 0) {
78431 				return;
78432 			}
78433 
78434 			/* Must restart because we NULLed out curr_pc. */
78435 			goto restart_execution;
78436 		}
78437 
78438 		case DUK_OP_THROW: {
78439 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
78440 
78441 			/* Note: errors are augmented when they are created, not
78442 			 * when they are thrown.  So, don't augment here, it would
78443 			 * break re-throwing for instance.
78444 			 */
78445 
78446 			/* Sync so that augmentation sees up-to-date activations, NULL
78447 			 * thr->ptr_curr_pc so that it's not used if side effects occur
78448 			 * in augmentation or longjmp handling.
78449 			 */
78450 			DUK__SYNC_AND_NULL_CURR_PC();
78451 
78452 			duk_dup(thr, (duk_idx_t) bc);
78453 			DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (before throw augment)",
78454 			                     (duk_tval *) duk_get_tval(thr, -1)));
78455 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
78456 			duk_err_augment_error_throw(thr);
78457 			DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (after throw augment)",
78458 			                     (duk_tval *) duk_get_tval(thr, -1)));
78459 #endif
78460 
78461 			duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, DUK_GET_TVAL_NEGIDX(thr, -1));
78462 #if defined(DUK_USE_DEBUGGER_SUPPORT)
78463 			duk_err_check_debugger_integration(thr);
78464 #endif
78465 
78466 			DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */
78467 			duk_err_longjmp(thr);
78468 			DUK_UNREACHABLE();
78469 			break;
78470 		}
78471 
78472 		case DUK_OP_CSREG: {
78473 			/*
78474 			 *  Assuming a register binds to a variable declared within this
78475 			 *  function (a declarative binding), the 'this' for the call
78476 			 *  setup is always 'undefined'.  E5 Section 10.2.1.1.6.
78477 			 */
78478 
78479 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
78480 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
78481 
78482 			/* A -> register containing target function (not type checked here)
78483 			 * BC -> target registers (BC, BC + 1) for call setup
78484 			 */
78485 
78486 #if defined(DUK_USE_PREFER_SIZE)
78487 			duk_dup(thr, (duk_idx_t) a);
78488 			duk_replace(thr, (duk_idx_t) bc);
78489 			duk_to_undefined(thr, (duk_idx_t) (bc + 1));
78490 #else
78491 			duk_tval *tv1;
78492 			duk_tval *tv2;
78493 			duk_tval *tv3;
78494 			duk_tval tv_tmp1;
78495 			duk_tval tv_tmp2;
78496 
78497 			tv1 = DUK__REGP(bc);
78498 			tv2 = tv1 + 1;
78499 			DUK_TVAL_SET_TVAL(&tv_tmp1, tv1);
78500 			DUK_TVAL_SET_TVAL(&tv_tmp2, tv2);
78501 			tv3 = DUK__REGP(a);
78502 			DUK_TVAL_SET_TVAL(tv1, tv3);
78503 			DUK_TVAL_INCREF(thr, tv1);  /* no side effects */
78504 			DUK_TVAL_SET_UNDEFINED(tv2);  /* no need for incref */
78505 			DUK_TVAL_DECREF(thr, &tv_tmp1);
78506 			DUK_TVAL_DECREF(thr, &tv_tmp2);
78507 #endif
78508 			break;
78509 		}
78510 
78511 
78512 		/* XXX: in some cases it's faster NOT to reuse the value
78513 		 * stack but rather copy the arguments on top of the stack
78514 		 * (mainly when the calling value stack is large and the value
78515 		 * stack resize would be large).
78516 		 */
78517 
78518 		case DUK_OP_CALL0:
78519 		case DUK_OP_CALL1:
78520 		case DUK_OP_CALL2:
78521 		case DUK_OP_CALL3:
78522 		case DUK_OP_CALL4:
78523 		case DUK_OP_CALL5:
78524 		case DUK_OP_CALL6:
78525 		case DUK_OP_CALL7: {
78526 			/* Opcode packs 4 flag bits: 1 for indirect, 3 map
78527 			 * 1:1 to three lowest call handling flags.
78528 			 *
78529 			 * A -> nargs or register with nargs (indirect)
78530 			 * BC -> base register for call (base -> func, base+1 -> this, base+2 -> arg1 ... base+2+N-1 -> argN)
78531 			 */
78532 
78533 			duk_idx_t nargs;
78534 			duk_idx_t idx;
78535 			duk_small_uint_t call_flags;
78536 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
78537 			duk_hcompfunc *fun;
78538 #endif
78539 
78540 			DUK_ASSERT((DUK_OP_CALL0 & 0x0fU) == 0);
78541 			DUK_ASSERT((ins & DUK_BC_CALL_FLAG_INDIRECT) == 0);
78542 
78543 			nargs = (duk_idx_t) DUK_DEC_A(ins);
78544 			call_flags = (ins & 0x07U) | DUK_CALL_FLAG_ALLOW_ECMATOECMA;
78545 			idx = (duk_idx_t) DUK_DEC_BC(ins);
78546 
78547 			if (duk__executor_handle_call(thr, idx, nargs, call_flags)) {
78548 				/* curr_pc synced by duk_handle_call_unprotected() */
78549 				DUK_ASSERT(thr->ptr_curr_pc == NULL);
78550 				goto restart_execution;
78551 			}
78552 			DUK_ASSERT(thr->ptr_curr_pc != NULL);
78553 
78554 			/* duk_js_call.c is required to restore the stack reserve
78555 			 * so we only need to reset the top.
78556 			 */
78557 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
78558 			fun = DUK__FUN();
78559 #endif
78560 			duk_set_top_unsafe(thr, (duk_idx_t) fun->nregs);
78561 
78562 			/* No need to reinit setjmp() catchpoint, as call handling
78563 			 * will store and restore our state.
78564 			 *
78565 			 * When debugger is enabled, we need to recheck the activation
78566 			 * status after returning.  This is now handled by call handling
78567 			 * and heap->dbg_force_restart.
78568 			 */
78569 			break;
78570 		}
78571 
78572 		case DUK_OP_CALL8:
78573 		case DUK_OP_CALL9:
78574 		case DUK_OP_CALL10:
78575 		case DUK_OP_CALL11:
78576 		case DUK_OP_CALL12:
78577 		case DUK_OP_CALL13:
78578 		case DUK_OP_CALL14:
78579 		case DUK_OP_CALL15: {
78580 			/* Indirect variant. */
78581 			duk_uint_fast_t nargs;
78582 			duk_idx_t idx;
78583 			duk_small_uint_t call_flags;
78584 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
78585 			duk_hcompfunc *fun;
78586 #endif
78587 
78588 			DUK_ASSERT((DUK_OP_CALL0 & 0x0fU) == 0);
78589 			DUK_ASSERT((ins & DUK_BC_CALL_FLAG_INDIRECT) != 0);
78590 
78591 			nargs = (duk_uint_fast_t) DUK_DEC_A(ins);
78592 			DUK__LOOKUP_INDIRECT(nargs);
78593 			call_flags = (ins & 0x07U) | DUK_CALL_FLAG_ALLOW_ECMATOECMA;
78594 			idx = (duk_idx_t) DUK_DEC_BC(ins);
78595 
78596 			if (duk__executor_handle_call(thr, idx, (duk_idx_t) nargs, call_flags)) {
78597 				DUK_ASSERT(thr->ptr_curr_pc == NULL);
78598 				goto restart_execution;
78599 			}
78600 			DUK_ASSERT(thr->ptr_curr_pc != NULL);
78601 
78602 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
78603 			fun = DUK__FUN();
78604 #endif
78605 			duk_set_top_unsafe(thr, (duk_idx_t) fun->nregs);
78606 			break;
78607 		}
78608 
78609 		case DUK_OP_NEWOBJ: {
78610 			duk_push_object(thr);
78611 #if defined(DUK_USE_ASSERTIONS)
78612 			{
78613 				duk_hobject *h;
78614 				h = duk_require_hobject(thr, -1);
78615 				DUK_ASSERT(DUK_HOBJECT_GET_ESIZE(h) == 0);
78616 				DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(h) == 0);
78617 				DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0);
78618 				DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(h) == 0);
78619 			}
78620 #endif
78621 #if !defined(DUK_USE_PREFER_SIZE)
78622 			/* XXX: could do a direct props realloc, but need hash size */
78623 			duk_hobject_resize_entrypart(thr, duk_known_hobject(thr, -1), DUK_DEC_A(ins));
78624 #endif
78625 			DUK__REPLACE_TOP_BC_BREAK();
78626 		}
78627 
78628 		case DUK_OP_NEWARR: {
78629 			duk_push_array(thr);
78630 #if defined(DUK_USE_ASSERTIONS)
78631 			{
78632 				duk_hobject *h;
78633 				h = duk_require_hobject(thr, -1);
78634 				DUK_ASSERT(DUK_HOBJECT_GET_ESIZE(h) == 0);
78635 				DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(h) == 0);
78636 				DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0);
78637 				DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(h) == 0);
78638 				DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(h));
78639 			}
78640 #endif
78641 #if !defined(DUK_USE_PREFER_SIZE)
78642 			duk_hobject_realloc_props(thr,
78643 			                          duk_known_hobject(thr, -1),
78644 			                          0 /*new_e_size*/,
78645 			                          DUK_DEC_A(ins) /*new_a_size*/,
78646 			                          0 /*new_h_size*/,
78647 			                          0 /*abandon_array*/);
78648 #if 0
78649 			duk_hobject_resize_arraypart(thr, duk_known_hobject(thr, -1), DUK_DEC_A(ins));
78650 #endif
78651 #endif
78652 			DUK__REPLACE_TOP_BC_BREAK();
78653 		}
78654 
78655 		case DUK_OP_MPUTOBJ:
78656 		case DUK_OP_MPUTOBJI: {
78657 			duk_idx_t obj_idx;
78658 			duk_uint_fast_t idx, idx_end;
78659 			duk_small_uint_fast_t count;
78660 
78661 			/* A -> register of target object
78662 			 * B -> first register of key/value pair list
78663 			 *      or register containing first register number if indirect
78664 			 * C -> number of key/value pairs * 2
78665 			 *      (= number of value stack indices used starting from 'B')
78666 			 */
78667 
78668 			obj_idx = DUK_DEC_A(ins);
78669 			DUK_ASSERT(duk_is_object(thr, obj_idx));
78670 
78671 			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
78672 			if (DUK_DEC_OP(ins) == DUK_OP_MPUTOBJI) {
78673 				DUK__LOOKUP_INDIRECT(idx);
78674 			}
78675 
78676 			count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
78677 			DUK_ASSERT(count > 0);  /* compiler guarantees */
78678 			idx_end = idx + count;
78679 
78680 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
78681 			if (DUK_UNLIKELY(idx_end > (duk_uint_fast_t) duk_get_top(thr))) {
78682 				/* XXX: use duk_is_valid_index() instead? */
78683 				/* XXX: improve check; check against nregs, not against top */
78684 				DUK__INTERNAL_ERROR("MPUTOBJ out of bounds");
78685 			}
78686 #endif
78687 
78688 			/* Use 'force' flag to duk_def_prop() to ensure that any
78689 			 * inherited properties don't prevent the operation.
78690 			 * With ES2015 duplicate properties are allowed, so that we
78691 			 * must overwrite any previous data or accessor property.
78692 			 *
78693 			 * With ES2015 computed property names the literal keys
78694 			 * may be arbitrary values and need to be ToPropertyKey()
78695 			 * coerced at runtime.
78696 			 */
78697 			do {
78698 				/* XXX: faster initialization (direct access or better primitives) */
78699 				duk_dup(thr, (duk_idx_t) idx);
78700 				duk_dup(thr, (duk_idx_t) (idx + 1));
78701 				duk_def_prop(thr, obj_idx, DUK_DEFPROP_HAVE_VALUE |
78702 				                           DUK_DEFPROP_FORCE |
78703 				                           DUK_DEFPROP_SET_WRITABLE |
78704 				                           DUK_DEFPROP_SET_ENUMERABLE |
78705 				                           DUK_DEFPROP_SET_CONFIGURABLE);
78706 				idx += 2;
78707 			} while (idx < idx_end);
78708 			break;
78709 		}
78710 
78711 		case DUK_OP_INITSET:
78712 		case DUK_OP_INITGET: {
78713 			duk__handle_op_initset_initget(thr, ins);
78714 			break;
78715 		}
78716 
78717 		case DUK_OP_MPUTARR:
78718 		case DUK_OP_MPUTARRI: {
78719 			duk_idx_t obj_idx;
78720 			duk_uint_fast_t idx, idx_end;
78721 			duk_small_uint_fast_t count;
78722 			duk_tval *tv1;
78723 			duk_uint32_t arr_idx;
78724 
78725 			/* A -> register of target object
78726 			 * B -> first register of value data (start_index, value1, value2, ..., valueN)
78727 			 *      or register containing first register number if indirect
78728 			 * C -> number of key/value pairs (N)
78729 			 */
78730 
78731 			obj_idx = DUK_DEC_A(ins);
78732 			DUK_ASSERT(duk_is_object(thr, obj_idx));
78733 
78734 			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
78735 			if (DUK_DEC_OP(ins) == DUK_OP_MPUTARRI) {
78736 				DUK__LOOKUP_INDIRECT(idx);
78737 			}
78738 
78739 			count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
78740 			DUK_ASSERT(count > 0 + 1);  /* compiler guarantees */
78741 			idx_end = idx + count;
78742 
78743 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
78744 			if (idx_end > (duk_uint_fast_t) duk_get_top(thr)) {
78745 				/* XXX: use duk_is_valid_index() instead? */
78746 				/* XXX: improve check; check against nregs, not against top */
78747 				DUK__INTERNAL_ERROR("MPUTARR out of bounds");
78748 			}
78749 #endif
78750 
78751 			tv1 = DUK__REGP(idx);
78752 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
78753 #if defined(DUK_USE_FASTINT)
78754 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
78755 			arr_idx = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv1);
78756 #else
78757 			arr_idx = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
78758 #endif
78759 			idx++;
78760 
78761 			do {
78762 				/* duk_xdef_prop() will define an own property without any array
78763 				 * special behaviors.  We'll need to set the array length explicitly
78764 				 * in the end.  For arrays with elisions, the compiler will emit an
78765 				 * explicit SETALEN which will update the length.
78766 				 */
78767 
78768 				/* XXX: because we're dealing with 'own' properties of a fresh array,
78769 				 * the array initializer should just ensure that the array has a large
78770 				 * enough array part and write the values directly into array part,
78771 				 * and finally set 'length' manually in the end (as already happens now).
78772 				 */
78773 
78774 				duk_dup(thr, (duk_idx_t) idx);
78775 				duk_xdef_prop_index_wec(thr, obj_idx, arr_idx);
78776 
78777 				idx++;
78778 				arr_idx++;
78779 			} while (idx < idx_end);
78780 
78781 			/* XXX: E5.1 Section 11.1.4 coerces the final length through
78782 			 * ToUint32() which is odd but happens now as a side effect of
78783 			 * 'arr_idx' type.
78784 			 */
78785 			duk_set_length(thr, obj_idx, (duk_size_t) (duk_uarridx_t) arr_idx);
78786 			break;
78787 		}
78788 
78789 		case DUK_OP_SETALEN: {
78790 			duk_tval *tv1;
78791 			duk_hobject *h;
78792 			duk_uint32_t len;
78793 
78794 			tv1 = DUK__REGP_A(ins);
78795 			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
78796 			h = DUK_TVAL_GET_OBJECT(tv1);
78797 			DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(h));
78798 
78799 			tv1 = DUK__REGP_BC(ins);
78800 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
78801 #if defined(DUK_USE_FASTINT)
78802 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
78803 			len = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv1);
78804 #else
78805 			len = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
78806 #endif
78807 			((duk_harray *) h)->length = len;
78808 			break;
78809 		}
78810 
78811 		case DUK_OP_INITENUM: {
78812 			duk__handle_op_initenum(thr, ins);
78813 			break;
78814 		}
78815 
78816 		case DUK_OP_NEXTENUM: {
78817 			curr_pc += duk__handle_op_nextenum(thr, ins);
78818 			break;
78819 		}
78820 
78821 		case DUK_OP_INVLHS: {
78822 			DUK_ERROR_REFERENCE(thr, DUK_STR_INVALID_LVALUE);
78823 			DUK_WO_NORETURN(return;);
78824 			break;
78825 		}
78826 
78827 		case DUK_OP_DEBUGGER: {
78828 			/* Opcode only emitted by compiler when debugger
78829 			 * support is enabled.  Ignore it silently without
78830 			 * debugger support, in case it has been loaded
78831 			 * from precompiled bytecode.
78832 			 */
78833 #if defined(DUK_USE_DEBUGGER_SUPPORT)
78834 			if (duk_debug_is_attached(thr->heap)) {
78835 				DUK_D(DUK_DPRINT("DEBUGGER statement encountered, halt execution"));
78836 				DUK__SYNC_AND_NULL_CURR_PC();
78837 				duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
78838 				DUK_D(DUK_DPRINT("DEBUGGER statement finished, resume execution"));
78839 				goto restart_execution;
78840 			} else {
78841 				DUK_D(DUK_DPRINT("DEBUGGER statement ignored, debugger not attached"));
78842 			}
78843 #else
78844 			DUK_D(DUK_DPRINT("DEBUGGER statement ignored, no debugger support"));
78845 #endif
78846 			break;
78847 		}
78848 
78849 		case DUK_OP_NOP: {
78850 			/* Nop, ignored, but ABC fields may carry a value e.g.
78851 			 * for indirect opcode handling.
78852 			 */
78853 			break;
78854 		}
78855 
78856 		case DUK_OP_INVALID: {
78857 			DUK_ERROR_FMT1(thr, DUK_ERR_ERROR, "INVALID opcode (%ld)", (long) DUK_DEC_ABC(ins));
78858 			DUK_WO_NORETURN(return;);
78859 			break;
78860 		}
78861 
78862 #if defined(DUK_USE_ES6)
78863 		case DUK_OP_NEWTARGET: {
78864 			duk_push_new_target(thr);
78865 			DUK__REPLACE_TOP_BC_BREAK();
78866 		}
78867 #endif  /* DUK_USE_ES6 */
78868 
78869 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
78870 #if !defined(DUK_USE_ES7_EXP_OPERATOR)
78871 		case DUK_OP_EXP_RR:
78872 		case DUK_OP_EXP_CR:
78873 		case DUK_OP_EXP_RC:
78874 		case DUK_OP_EXP_CC:
78875 #endif
78876 #if !defined(DUK_USE_ES6)
78877 		case DUK_OP_NEWTARGET:
78878 #endif
78879 #if !defined(DUK_USE_VERBOSE_ERRORS)
78880 		case DUK_OP_GETPROPC_RR:
78881 		case DUK_OP_GETPROPC_CR:
78882 		case DUK_OP_GETPROPC_RC:
78883 		case DUK_OP_GETPROPC_CC:
78884 #endif
78885 		case DUK_OP_UNUSED207:
78886 		case DUK_OP_UNUSED212:
78887 		case DUK_OP_UNUSED213:
78888 		case DUK_OP_UNUSED214:
78889 		case DUK_OP_UNUSED215:
78890 		case DUK_OP_UNUSED216:
78891 		case DUK_OP_UNUSED217:
78892 		case DUK_OP_UNUSED218:
78893 		case DUK_OP_UNUSED219:
78894 		case DUK_OP_UNUSED220:
78895 		case DUK_OP_UNUSED221:
78896 		case DUK_OP_UNUSED222:
78897 		case DUK_OP_UNUSED223:
78898 		case DUK_OP_UNUSED224:
78899 		case DUK_OP_UNUSED225:
78900 		case DUK_OP_UNUSED226:
78901 		case DUK_OP_UNUSED227:
78902 		case DUK_OP_UNUSED228:
78903 		case DUK_OP_UNUSED229:
78904 		case DUK_OP_UNUSED230:
78905 		case DUK_OP_UNUSED231:
78906 		case DUK_OP_UNUSED232:
78907 		case DUK_OP_UNUSED233:
78908 		case DUK_OP_UNUSED234:
78909 		case DUK_OP_UNUSED235:
78910 		case DUK_OP_UNUSED236:
78911 		case DUK_OP_UNUSED237:
78912 		case DUK_OP_UNUSED238:
78913 		case DUK_OP_UNUSED239:
78914 		case DUK_OP_UNUSED240:
78915 		case DUK_OP_UNUSED241:
78916 		case DUK_OP_UNUSED242:
78917 		case DUK_OP_UNUSED243:
78918 		case DUK_OP_UNUSED244:
78919 		case DUK_OP_UNUSED245:
78920 		case DUK_OP_UNUSED246:
78921 		case DUK_OP_UNUSED247:
78922 		case DUK_OP_UNUSED248:
78923 		case DUK_OP_UNUSED249:
78924 		case DUK_OP_UNUSED250:
78925 		case DUK_OP_UNUSED251:
78926 		case DUK_OP_UNUSED252:
78927 		case DUK_OP_UNUSED253:
78928 		case DUK_OP_UNUSED254:
78929 		case DUK_OP_UNUSED255:
78930 		/* Force all case clauses to map to an actual handler
78931 		 * so that the compiler can emit a jump without a bounds
78932 		 * check: the switch argument is a duk_uint8_t so that
78933 		 * the compiler may be able to figure it out.  This is
78934 		 * a small detail and obviously compiler dependent.
78935 		 */
78936 		/* default: clause omitted on purpose */
78937 #else  /* DUK_USE_EXEC_PREFER_SIZE */
78938 		default:
78939 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
78940 		{
78941 			/* Default case catches invalid/unsupported opcodes. */
78942 			DUK_D(DUK_DPRINT("invalid opcode: %ld - %!I", (long) op, ins));
78943 			DUK__INTERNAL_ERROR("invalid opcode");
78944 			break;
78945 		}
78946 
78947 		}  /* end switch */
78948 
78949 		continue;
78950 
78951 		/* Some shared exit paths for opcode handling below.  These
78952 		 * are mostly useful to reduce code footprint when multiple
78953 		 * opcodes have a similar epilogue (like replacing stack top
78954 		 * with index 'a').
78955 		 */
78956 
78957 #if defined(DUK_USE_EXEC_PREFER_SIZE)
78958 	 replace_top_a:
78959 		DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins));
78960 		continue;
78961 	 replace_top_bc:
78962 		DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins));
78963 		continue;
78964 #endif
78965 	}
78966 	DUK_WO_NORETURN(return;);
78967 
78968 #if !defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)
78969  internal_error:
78970 	DUK_ERROR_INTERNAL(thr);
78971 	DUK_WO_NORETURN(return;);
78972 #endif
78973 }
78974 
78975 /* automatic undefs */
78976 #undef DUK__BYTEOFF_A
78977 #undef DUK__BYTEOFF_B
78978 #undef DUK__BYTEOFF_BC
78979 #undef DUK__BYTEOFF_C
78980 #undef DUK__COMPARE_BODY
78981 #undef DUK__CONST
78982 #undef DUK__CONSTP
78983 #undef DUK__CONSTP_A
78984 #undef DUK__CONSTP_B
78985 #undef DUK__CONSTP_BC
78986 #undef DUK__CONSTP_C
78987 #undef DUK__DELPROP_BODY
78988 #undef DUK__EQ_BODY
78989 #undef DUK__FUN
78990 #undef DUK__GETPROPC_BODY
78991 #undef DUK__GETPROP_BODY
78992 #undef DUK__GE_BODY
78993 #undef DUK__GT_BODY
78994 #undef DUK__INLINE_PERF
78995 #undef DUK__INSTOF_BODY
78996 #undef DUK__INTERNAL_ERROR
78997 #undef DUK__INT_NOACTION
78998 #undef DUK__INT_RESTART
78999 #undef DUK__IN_BODY
79000 #undef DUK__LE_BODY
79001 #undef DUK__LONGJMP_RESTART
79002 #undef DUK__LONGJMP_RETHROW
79003 #undef DUK__LOOKUP_INDIRECT
79004 #undef DUK__LT_BODY
79005 #undef DUK__MASK_A
79006 #undef DUK__MASK_B
79007 #undef DUK__MASK_BC
79008 #undef DUK__MASK_C
79009 #undef DUK__NEQ_BODY
79010 #undef DUK__NOINLINE_PERF
79011 #undef DUK__PUTPROP_BODY
79012 #undef DUK__RCBIT_B
79013 #undef DUK__RCBIT_C
79014 #undef DUK__REG
79015 #undef DUK__REGCONSTP_B
79016 #undef DUK__REGCONSTP_C
79017 #undef DUK__REGP
79018 #undef DUK__REGP_A
79019 #undef DUK__REGP_B
79020 #undef DUK__REGP_BC
79021 #undef DUK__REGP_C
79022 #undef DUK__REPLACE_BOOL_A_BREAK
79023 #undef DUK__REPLACE_TOP_A_BREAK
79024 #undef DUK__REPLACE_TOP_BC_BREAK
79025 #undef DUK__REPLACE_TO_TVPTR
79026 #undef DUK__RETHAND_FINISHED
79027 #undef DUK__RETHAND_RESTART
79028 #undef DUK__RETURN_SHARED
79029 #undef DUK__SEQ_BODY
79030 #undef DUK__SHIFT_A
79031 #undef DUK__SHIFT_B
79032 #undef DUK__SHIFT_BC
79033 #undef DUK__SHIFT_C
79034 #undef DUK__SNEQ_BODY
79035 #undef DUK__STRICT
79036 #undef DUK__SYNC_AND_NULL_CURR_PC
79037 #undef DUK__SYNC_CURR_PC
79038 #undef DUK__TVAL_SHIFT
79039 /*
79040  *  ECMAScript specification algorithm and conversion helpers.
79041  *
79042  *  These helpers encapsulate the primitive ECMAScript operation semantics,
79043  *  and are used by the bytecode executor and the API (among other places).
79044  *  Some primitives are only implemented as part of the API and have no
79045  *  "internal" helper.  This is the case when an internal helper would not
79046  *  really be useful; e.g. the operation is rare, uses value stack heavily,
79047  *  etc.
79048  *
79049  *  The operation arguments depend on what is required to implement
79050  *  the operation:
79051  *
79052  *    - If an operation is simple and stateless, and has no side
79053  *      effects, it won't take an duk_hthread argument and its
79054  *      arguments may be duk_tval pointers (which are safe as long
79055  *      as no side effects take place).
79056  *
79057  *    - If complex coercions are required (e.g. a "ToNumber" coercion)
79058  *      or errors may be thrown, the operation takes an duk_hthread
79059  *      argument.  This also implies that the operation may have
79060  *      arbitrary side effects, invalidating any duk_tval pointers.
79061  *
79062  *    - For operations with potential side effects, arguments can be
79063  *      taken in several ways:
79064  *
79065  *      a) as duk_tval pointers, which makes sense if the "common case"
79066  *         can be resolved without side effects (e.g. coercion); the
79067  *         arguments are pushed to the valstack for coercion if
79068  *         necessary
79069  *
79070  *      b) as duk_tval values
79071  *
79072  *      c) implicitly on value stack top
79073  *
79074  *      d) as indices to the value stack
79075  *
79076  *  Future work:
79077  *
79078  *     - Argument styles may not be the most sensible in every case now.
79079  *
79080  *     - In-place coercions might be useful for several operations, if
79081  *       in-place coercion is OK for the bytecode executor and the API.
79082  */
79083 
79084 /* #include duk_internal.h -> already included */
79085 
79086 /*
79087  *  ToPrimitive()  (E5 Section 9.1)
79088  *
79089  *  ==> implemented in the API.
79090  */
79091 
79092 /*
79093  *  ToBoolean()  (E5 Section 9.2)
79094  */
79095 
79096 DUK_INTERNAL duk_bool_t duk_js_toboolean(duk_tval *tv) {
79097 	switch (DUK_TVAL_GET_TAG(tv)) {
79098 	case DUK_TAG_UNDEFINED:
79099 	case DUK_TAG_NULL:
79100 		return 0;
79101 	case DUK_TAG_BOOLEAN:
79102 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 || DUK_TVAL_GET_BOOLEAN(tv) == 1);
79103 		return DUK_TVAL_GET_BOOLEAN(tv);
79104 	case DUK_TAG_STRING: {
79105 		/* Symbols ToBoolean() coerce to true, regardless of their
79106 		 * description.  This happens with no explicit check because
79107 		 * of the symbol representation byte prefix.
79108 		 */
79109 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
79110 		DUK_ASSERT(h != NULL);
79111 		return (DUK_HSTRING_GET_BYTELEN(h) > 0 ? 1 : 0);
79112 	}
79113 	case DUK_TAG_OBJECT: {
79114 		return 1;
79115 	}
79116 	case DUK_TAG_BUFFER: {
79117 		/* Mimic Uint8Array semantics: objects coerce true, regardless
79118 		 * of buffer length (zero or not) or context.
79119 		 */
79120 		return 1;
79121 	}
79122 	case DUK_TAG_POINTER: {
79123 		void *p = DUK_TVAL_GET_POINTER(tv);
79124 		return (p != NULL ? 1 : 0);
79125 	}
79126 	case DUK_TAG_LIGHTFUNC: {
79127 		return 1;
79128 	}
79129 #if defined(DUK_USE_FASTINT)
79130 	case DUK_TAG_FASTINT:
79131 		if (DUK_TVAL_GET_FASTINT(tv) != 0) {
79132 			return 1;
79133 		} else {
79134 			return 0;
79135 		}
79136 #endif
79137 	default: {
79138 		/* number */
79139 		duk_double_t d;
79140 #if defined(DUK_USE_PREFER_SIZE)
79141 		int c;
79142 #endif
79143 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
79144 		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
79145 		d = DUK_TVAL_GET_DOUBLE(tv);
79146 #if defined(DUK_USE_PREFER_SIZE)
79147 		c = DUK_FPCLASSIFY((double) d);
79148 		if (c == DUK_FP_ZERO || c == DUK_FP_NAN) {
79149 			return 0;
79150 		} else {
79151 			return 1;
79152 		}
79153 #else
79154 		DUK_ASSERT(duk_double_is_nan_or_zero(d) == 0 || duk_double_is_nan_or_zero(d) == 1);
79155 		return duk_double_is_nan_or_zero(d) ^ 1;
79156 #endif
79157 	}
79158 	}
79159 	DUK_UNREACHABLE();
79160 }
79161 
79162 /*
79163  *  ToNumber()  (E5 Section 9.3)
79164  *
79165  *  Value to convert must be on stack top, and is popped before exit.
79166  *
79167  *  See: http://www.cs.indiana.edu/~burger/FP-Printing-PLDI96.pdf
79168  *       http://www.cs.indiana.edu/~burger/fp/index.html
79169  *
79170  *  Notes on the conversion:
79171  *
79172  *    - There are specific requirements on the accuracy of the conversion
79173  *      through a "Mathematical Value" (MV), so this conversion is not
79174  *      trivial.
79175  *
79176  *    - Quick rejects (e.g. based on first char) are difficult because
79177  *      the grammar allows leading and trailing white space.
79178  *
79179  *    - Quick reject based on string length is difficult even after
79180  *      accounting for white space; there may be arbitrarily many
79181  *      decimal digits.
79182  *
79183  *    - Standard grammar allows decimal values ("123"), hex values
79184  *      ("0x123") and infinities
79185  *
79186  *    - Unlike source code literals, ToNumber() coerces empty strings
79187  *      and strings with only whitespace to zero (not NaN).  However,
79188  *      while '' coerces to 0, '+' and '-' coerce to NaN.
79189  */
79190 
79191 /* E5 Section 9.3.1 */
79192 DUK_LOCAL duk_double_t duk__tonumber_string_raw(duk_hthread *thr) {
79193 	duk_small_uint_t s2n_flags;
79194 	duk_double_t d;
79195 
79196 	DUK_ASSERT(duk_is_string(thr, -1));
79197 
79198 	/* Quite lenient, e.g. allow empty as zero, but don't allow trailing
79199 	 * garbage.
79200 	 */
79201 	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
79202 	            DUK_S2N_FLAG_ALLOW_EXP |
79203 	            DUK_S2N_FLAG_ALLOW_PLUS |
79204 	            DUK_S2N_FLAG_ALLOW_MINUS |
79205 	            DUK_S2N_FLAG_ALLOW_INF |
79206 	            DUK_S2N_FLAG_ALLOW_FRAC |
79207 	            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
79208 	            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
79209 	            DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO |
79210 	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
79211 	            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT |
79212 	            DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT |
79213 	            DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT;
79214 
79215 	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
79216 
79217 #if defined(DUK_USE_PREFER_SIZE)
79218 	d = duk_get_number(thr, -1);
79219 	duk_pop_unsafe(thr);
79220 #else
79221 	thr->valstack_top--;
79222 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(thr->valstack_top));
79223 	DUK_ASSERT(DUK_TVAL_IS_DOUBLE(thr->valstack_top));  /* no fastint conversion in numconv now */
79224 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(thr->valstack_top));
79225 	d = DUK_TVAL_GET_DOUBLE(thr->valstack_top);  /* assumes not a fastint */
79226 	DUK_TVAL_SET_UNDEFINED(thr->valstack_top);
79227 #endif
79228 
79229 	return d;
79230 }
79231 
79232 DUK_INTERNAL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv) {
79233 	DUK_ASSERT(thr != NULL);
79234 	DUK_ASSERT(tv != NULL);
79235 
79236 	switch (DUK_TVAL_GET_TAG(tv)) {
79237 	case DUK_TAG_UNDEFINED: {
79238 		/* return a specific NaN (although not strictly necessary) */
79239 		duk_double_union du;
79240 		DUK_DBLUNION_SET_NAN(&du);
79241 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
79242 		return du.d;
79243 	}
79244 	case DUK_TAG_NULL: {
79245 		/* +0.0 */
79246 		return 0.0;
79247 	}
79248 	case DUK_TAG_BOOLEAN: {
79249 		if (DUK_TVAL_IS_BOOLEAN_TRUE(tv)) {
79250 			return 1.0;
79251 		}
79252 		return 0.0;
79253 	}
79254 	case DUK_TAG_STRING: {
79255 		/* For Symbols ToNumber() is always a TypeError. */
79256 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
79257 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
79258 			DUK_ERROR_TYPE(thr, DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL);
79259 			DUK_WO_NORETURN(return 0.0;);
79260 		}
79261 		duk_push_hstring(thr, h);
79262 		return duk__tonumber_string_raw(thr);
79263 	}
79264 	case DUK_TAG_BUFFER:  /* plain buffer treated like object */
79265 	case DUK_TAG_OBJECT: {
79266 		duk_double_t d;
79267 		duk_push_tval(thr, tv);
79268 		duk_to_primitive(thr, -1, DUK_HINT_NUMBER);  /* 'tv' becomes invalid */
79269 
79270 		/* recursive call for a primitive value (guaranteed not to cause second
79271 		 * recursion).
79272 		 */
79273 		DUK_ASSERT(duk_get_tval(thr, -1) != NULL);
79274 		d = duk_js_tonumber(thr, duk_get_tval(thr, -1));
79275 
79276 		duk_pop_unsafe(thr);
79277 		return d;
79278 	}
79279 	case DUK_TAG_POINTER: {
79280 		/* Coerce like boolean */
79281 		void *p = DUK_TVAL_GET_POINTER(tv);
79282 		return (p != NULL ? 1.0 : 0.0);
79283 	}
79284 	case DUK_TAG_LIGHTFUNC: {
79285 		/* +(function(){}) -> NaN */
79286 		return DUK_DOUBLE_NAN;
79287 	}
79288 #if defined(DUK_USE_FASTINT)
79289 	case DUK_TAG_FASTINT:
79290 		return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
79291 #endif
79292 	default: {
79293 		/* number */
79294 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
79295 		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
79296 		return DUK_TVAL_GET_DOUBLE(tv);
79297 	}
79298 	}
79299 
79300 	DUK_UNREACHABLE();
79301 }
79302 
79303 /*
79304  *  ToInteger()  (E5 Section 9.4)
79305  */
79306 
79307 /* exposed, used by e.g. duk_bi_date.c */
79308 DUK_INTERNAL duk_double_t duk_js_tointeger_number(duk_double_t x) {
79309 #if defined(DUK_USE_PREFER_SIZE)
79310 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
79311 
79312 	if (DUK_UNLIKELY(c == DUK_FP_NAN)) {
79313 		return 0.0;
79314 	} else if (DUK_UNLIKELY(c == DUK_FP_INFINITE)) {
79315 		return x;
79316 	} else {
79317 		/* Finite, including neg/pos zero.  Neg zero sign must be
79318 		 * preserved.
79319 		 */
79320 		return duk_double_trunc_towards_zero(x);
79321 	}
79322 #else  /* DUK_USE_PREFER_SIZE */
79323 	/* NaN and Infinity have the same exponent so it's a cheap
79324 	 * initial check for the rare path.
79325 	 */
79326 	if (DUK_UNLIKELY(duk_double_is_nan_or_inf(x) != 0U)) {
79327 		if (duk_double_is_nan(x)) {
79328 			return 0.0;
79329 		} else {
79330 			return x;
79331 		}
79332 	} else {
79333 		return duk_double_trunc_towards_zero(x);
79334 	}
79335 #endif  /* DUK_USE_PREFER_SIZE */
79336 }
79337 
79338 DUK_INTERNAL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv) {
79339 	/* XXX: fastint */
79340 	duk_double_t d = duk_js_tonumber(thr, tv);  /* invalidates tv */
79341 	return duk_js_tointeger_number(d);
79342 }
79343 
79344 /*
79345  *  ToInt32(), ToUint32(), ToUint16()  (E5 Sections 9.5, 9.6, 9.7)
79346  */
79347 
79348 /* combined algorithm matching E5 Sections 9.5 and 9.6 */
79349 DUK_LOCAL duk_double_t duk__toint32_touint32_helper(duk_double_t x, duk_bool_t is_toint32) {
79350 #if defined (DUK_USE_PREFER_SIZE)
79351 	duk_small_int_t c;
79352 #endif
79353 
79354 #if defined (DUK_USE_PREFER_SIZE)
79355 	c = (duk_small_int_t) DUK_FPCLASSIFY(x);
79356 	if (c == DUK_FP_NAN || c == DUK_FP_ZERO || c == DUK_FP_INFINITE) {
79357 		return 0.0;
79358 	}
79359 #else
79360 	if (duk_double_is_nan_zero_inf(x)) {
79361 		return 0.0;
79362 	}
79363 #endif
79364 
79365 	/* x = sign(x) * floor(abs(x)), i.e. truncate towards zero, keep sign */
79366 	x = duk_double_trunc_towards_zero(x);
79367 
79368 	/* NOTE: fmod(x) result sign is same as sign of x, which
79369 	 * differs from what Javascript wants (see Section 9.6).
79370 	 */
79371 
79372 	x = DUK_FMOD(x, DUK_DOUBLE_2TO32);    /* -> x in ]-2**32, 2**32[ */
79373 
79374 	if (x < 0.0) {
79375 		x += DUK_DOUBLE_2TO32;
79376 	}
79377 	DUK_ASSERT(x >= 0 && x < DUK_DOUBLE_2TO32);  /* -> x in [0, 2**32[ */
79378 
79379 	if (is_toint32) {
79380 		if (x >= DUK_DOUBLE_2TO31) {
79381 			/* x in [2**31, 2**32[ */
79382 
79383 			x -= DUK_DOUBLE_2TO32;  /* -> x in [-2**31,2**31[ */
79384 		}
79385 	}
79386 
79387 	return x;
79388 }
79389 
79390 DUK_INTERNAL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv) {
79391 	duk_double_t d;
79392 
79393 #if defined(DUK_USE_FASTINT)
79394 	if (DUK_TVAL_IS_FASTINT(tv)) {
79395 		return DUK_TVAL_GET_FASTINT_I32(tv);
79396 	}
79397 #endif
79398 
79399 	d = duk_js_tonumber(thr, tv);  /* invalidates tv */
79400 	d = duk__toint32_touint32_helper(d, 1);
79401 	DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
79402 	DUK_ASSERT(d >= -2147483648.0 && d <= 2147483647.0);  /* [-0x80000000,0x7fffffff] */
79403 	DUK_ASSERT(d == ((duk_double_t) ((duk_int32_t) d)));  /* whole, won't clip */
79404 	return (duk_int32_t) d;
79405 }
79406 
79407 
79408 DUK_INTERNAL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv) {
79409 	duk_double_t d;
79410 
79411 #if defined(DUK_USE_FASTINT)
79412 	if (DUK_TVAL_IS_FASTINT(tv)) {
79413 		return DUK_TVAL_GET_FASTINT_U32(tv);
79414 	}
79415 #endif
79416 
79417 	d = duk_js_tonumber(thr, tv);  /* invalidates tv */
79418 	d = duk__toint32_touint32_helper(d, 0);
79419 	DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
79420 	DUK_ASSERT(d >= 0.0 && d <= 4294967295.0);  /* [0x00000000, 0xffffffff] */
79421 	DUK_ASSERT(d == ((duk_double_t) ((duk_uint32_t) d)));  /* whole, won't clip */
79422 	return (duk_uint32_t) d;
79423 
79424 }
79425 
79426 DUK_INTERNAL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv) {
79427 	/* should be a safe way to compute this */
79428 	return (duk_uint16_t) (duk_js_touint32(thr, tv) & 0x0000ffffU);
79429 }
79430 
79431 /*
79432  *  ToString()  (E5 Section 9.8)
79433  *  ToObject()  (E5 Section 9.9)
79434  *  CheckObjectCoercible()  (E5 Section 9.10)
79435  *  IsCallable()  (E5 Section 9.11)
79436  *
79437  *  ==> implemented in the API.
79438  */
79439 
79440 /*
79441  *  Loose equality, strict equality, and SameValue (E5 Sections 11.9.1, 11.9.4,
79442  *  9.12).  These have much in common so they can share some helpers.
79443  *
79444  *  Future work notes:
79445  *
79446  *    - Current implementation (and spec definition) has recursion; this should
79447  *      be fixed if possible.
79448  *
79449  *    - String-to-number coercion should be possible without going through the
79450  *      value stack (and be more compact) if a shared helper is invoked.
79451  */
79452 
79453 /* Note that this is the same operation for strict and loose equality:
79454  *  - E5 Section 11.9.3, step 1.c (loose)
79455  *  - E5 Section 11.9.6, step 4 (strict)
79456  */
79457 
79458 DUK_LOCAL duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y) {
79459 #if defined(DUK_USE_PARANOID_MATH)
79460 	/* Straightforward algorithm, makes fewer compiler assumptions. */
79461 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
79462 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
79463 	if (cx == DUK_FP_NAN || cy == DUK_FP_NAN) {
79464 		return 0;
79465 	}
79466 	if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
79467 		return 1;
79468 	}
79469 	if (x == y) {
79470 		return 1;
79471 	}
79472 	return 0;
79473 #else  /* DUK_USE_PARANOID_MATH */
79474 	/* Better equivalent algorithm.  If the compiler is compliant, C and
79475 	 * ECMAScript semantics are identical for this particular comparison.
79476 	 * In particular, NaNs must never compare equal and zeroes must compare
79477 	 * equal regardless of sign.  Could also use a macro, but this inlines
79478 	 * already nicely (no difference on gcc, for instance).
79479 	 */
79480 	if (x == y) {
79481 		/* IEEE requires that NaNs compare false */
79482 		DUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);
79483 		DUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);
79484 		return 1;
79485 	} else {
79486 		/* IEEE requires that zeros compare the same regardless
79487 		 * of their signed, so if both x and y are zeroes, they
79488 		 * are caught above.
79489 		 */
79490 		DUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));
79491 		return 0;
79492 	}
79493 #endif  /* DUK_USE_PARANOID_MATH */
79494 }
79495 
79496 DUK_LOCAL duk_bool_t duk__js_samevalue_number(duk_double_t x, duk_double_t y) {
79497 #if defined(DUK_USE_PARANOID_MATH)
79498 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
79499 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
79500 
79501 	if (cx == DUK_FP_NAN && cy == DUK_FP_NAN) {
79502 		/* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
79503 		return 1;
79504 	}
79505 	if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
79506 		/* Note: cannot assume that a non-zero return value of signbit() would
79507 		 * always be the same -- hence cannot (portably) use something like:
79508 		 *
79509 		 *     signbit(x) == signbit(y)
79510 		 */
79511 		duk_small_int_t sx = DUK_SIGNBIT(x) ? 1 : 0;
79512 		duk_small_int_t sy = DUK_SIGNBIT(y) ? 1 : 0;
79513 		return (sx == sy);
79514 	}
79515 
79516 	/* normal comparison; known:
79517 	 *   - both x and y are not NaNs (but one of them can be)
79518 	 *   - both x and y are not zero (but one of them can be)
79519 	 *   - x and y may be denormal or infinite
79520 	 */
79521 
79522 	return (x == y);
79523 #else  /* DUK_USE_PARANOID_MATH */
79524 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
79525 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
79526 
79527 	if (x == y) {
79528 		/* IEEE requires that NaNs compare false */
79529 		DUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);
79530 		DUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);
79531 
79532 		/* Using classification has smaller footprint than direct comparison. */
79533 		if (DUK_UNLIKELY(cx == DUK_FP_ZERO && cy == DUK_FP_ZERO)) {
79534 			/* Note: cannot assume that a non-zero return value of signbit() would
79535 			 * always be the same -- hence cannot (portably) use something like:
79536 			 *
79537 			 *     signbit(x) == signbit(y)
79538 			 */
79539 			return duk_double_same_sign(x, y);
79540 		}
79541 		return 1;
79542 	} else {
79543 		/* IEEE requires that zeros compare the same regardless
79544 		 * of their sign, so if both x and y are zeroes, they
79545 		 * are caught above.
79546 		 */
79547 		DUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));
79548 
79549 		/* Difference to non-strict/strict comparison is that NaNs compare
79550 		 * equal and signed zero signs matter.
79551 		 */
79552 		if (DUK_UNLIKELY(cx == DUK_FP_NAN && cy == DUK_FP_NAN)) {
79553 			/* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
79554 			return 1;
79555 		}
79556 		return 0;
79557 	}
79558 #endif  /* DUK_USE_PARANOID_MATH */
79559 }
79560 
79561 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) {
79562 	duk_uint_t type_mask_x;
79563 	duk_uint_t type_mask_y;
79564 
79565 	/* If flags != 0 (strict or SameValue), thr can be NULL.  For loose
79566 	 * equals comparison it must be != NULL.
79567 	 */
79568 	DUK_ASSERT(flags != 0 || thr != NULL);
79569 
79570 	/*
79571 	 *  Same type?
79572 	 *
79573 	 *  Note: since number values have no explicit tag in the 8-byte
79574 	 *  representation, need the awkward if + switch.
79575 	 */
79576 
79577 #if defined(DUK_USE_FASTINT)
79578 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
79579 		if (DUK_TVAL_GET_FASTINT(tv_x) == DUK_TVAL_GET_FASTINT(tv_y)) {
79580 			return 1;
79581 		} else {
79582 			return 0;
79583 		}
79584 	}
79585 	else
79586 #endif
79587 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
79588 		duk_double_t d1, d2;
79589 
79590 		/* Catches both doubles and cases where only one argument is
79591 		 * a fastint so can't assume a double.
79592 		 */
79593 		d1 = DUK_TVAL_GET_NUMBER(tv_x);
79594 		d2 = DUK_TVAL_GET_NUMBER(tv_y);
79595 		if (DUK_UNLIKELY((flags & DUK_EQUALS_FLAG_SAMEVALUE) != 0)) {
79596 			/* SameValue */
79597 			return duk__js_samevalue_number(d1, d2);
79598 		} else {
79599 			/* equals and strict equals */
79600 			return duk__js_equals_number(d1, d2);
79601 		}
79602 	} else if (DUK_TVAL_GET_TAG(tv_x) == DUK_TVAL_GET_TAG(tv_y)) {
79603 		switch (DUK_TVAL_GET_TAG(tv_x)) {
79604 		case DUK_TAG_UNDEFINED:
79605 		case DUK_TAG_NULL: {
79606 			return 1;
79607 		}
79608 		case DUK_TAG_BOOLEAN: {
79609 			return DUK_TVAL_GET_BOOLEAN(tv_x) == DUK_TVAL_GET_BOOLEAN(tv_y);
79610 		}
79611 		case DUK_TAG_POINTER: {
79612 			return DUK_TVAL_GET_POINTER(tv_x) == DUK_TVAL_GET_POINTER(tv_y);
79613 		}
79614 		case DUK_TAG_STRING:
79615 		case DUK_TAG_OBJECT: {
79616 			/* Heap pointer comparison suffices for strings and objects.
79617 			 * Symbols compare equal if they have the same internal
79618 			 * representation; again heap pointer comparison suffices.
79619 			 */
79620 			return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
79621 		}
79622 		case DUK_TAG_BUFFER: {
79623 			/* In Duktape 2.x plain buffers mimic Uint8Array objects
79624 			 * so always compare by heap pointer.  In Duktape 1.x
79625 			 * strict comparison would compare heap pointers and
79626 			 * non-strict would compare contents.
79627 			 */
79628 			return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
79629 		}
79630 		case DUK_TAG_LIGHTFUNC: {
79631 			/* At least 'magic' has a significant impact on function
79632 			 * identity.
79633 			 */
79634 			duk_small_uint_t lf_flags_x;
79635 			duk_small_uint_t lf_flags_y;
79636 			duk_c_function func_x;
79637 			duk_c_function func_y;
79638 
79639 			DUK_TVAL_GET_LIGHTFUNC(tv_x, func_x, lf_flags_x);
79640 			DUK_TVAL_GET_LIGHTFUNC(tv_y, func_y, lf_flags_y);
79641 			return ((func_x == func_y) && (lf_flags_x == lf_flags_y)) ? 1 : 0;
79642 		}
79643 #if defined(DUK_USE_FASTINT)
79644 		case DUK_TAG_FASTINT:
79645 #endif
79646 		default: {
79647 			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));
79648 			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_y));
79649 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
79650 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_y));
79651 			DUK_UNREACHABLE();
79652 			return 0;
79653 		}
79654 		}
79655 	}
79656 
79657 	if ((flags & (DUK_EQUALS_FLAG_STRICT | DUK_EQUALS_FLAG_SAMEVALUE)) != 0) {
79658 		return 0;
79659 	}
79660 
79661 	DUK_ASSERT(flags == 0);  /* non-strict equality from here on */
79662 
79663 	/*
79664 	 *  Types are different; various cases for non-strict comparison
79665 	 *
79666 	 *  Since comparison is symmetric, we use a "swap trick" to reduce
79667 	 *  code size.
79668 	 */
79669 
79670 	type_mask_x = duk_get_type_mask_tval(tv_x);
79671 	type_mask_y = duk_get_type_mask_tval(tv_y);
79672 
79673 	/* Undefined/null are considered equal (e.g. "null == undefined" -> true). */
79674 	if ((type_mask_x & (DUK_TYPE_MASK_UNDEFINED | DUK_TYPE_MASK_NULL)) &&
79675 	    (type_mask_y & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED))) {
79676 		return 1;
79677 	}
79678 
79679 	/* Number/string -> coerce string to number (e.g. "'1.5' == 1.5" -> true). */
79680 	if ((type_mask_x & DUK_TYPE_MASK_NUMBER) && (type_mask_y & DUK_TYPE_MASK_STRING)) {
79681 		if (!DUK_TVAL_STRING_IS_SYMBOL(tv_y)) {
79682 			duk_double_t d1, d2;
79683 			d1 = DUK_TVAL_GET_NUMBER(tv_x);
79684 			d2 = duk_to_number_tval(thr, tv_y);
79685 			return duk__js_equals_number(d1, d2);
79686 		}
79687 	}
79688 	if ((type_mask_x & DUK_TYPE_MASK_STRING) && (type_mask_y & DUK_TYPE_MASK_NUMBER)) {
79689 		if (!DUK_TVAL_STRING_IS_SYMBOL(tv_x)) {
79690 			duk_double_t d1, d2;
79691 			d1 = DUK_TVAL_GET_NUMBER(tv_y);
79692 			d2 = duk_to_number_tval(thr, tv_x);
79693 			return duk__js_equals_number(d1, d2);
79694 		}
79695 	}
79696 
79697 	/* Boolean/any -> coerce boolean to number and try again.  If boolean is
79698 	 * compared to a pointer, the final comparison after coercion now always
79699 	 * yields false (as pointer vs. number compares to false), but this is
79700 	 * not special cased.
79701 	 *
79702 	 * ToNumber(bool) is +1.0 or 0.0.  Tagged boolean value is always 0 or 1.
79703 	 */
79704 	if (type_mask_x & DUK_TYPE_MASK_BOOLEAN) {
79705 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_x) == 0 || DUK_TVAL_GET_BOOLEAN(tv_x) == 1);
79706 		duk_push_uint(thr, DUK_TVAL_GET_BOOLEAN(tv_x));
79707 		duk_push_tval(thr, tv_y);
79708 		goto recursive_call;
79709 	}
79710 	if (type_mask_y & DUK_TYPE_MASK_BOOLEAN) {
79711 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_y) == 0 || DUK_TVAL_GET_BOOLEAN(tv_y) == 1);
79712 		duk_push_tval(thr, tv_x);
79713 		duk_push_uint(thr, DUK_TVAL_GET_BOOLEAN(tv_y));
79714 		goto recursive_call;
79715 	}
79716 
79717 	/* String-number-symbol/object -> coerce object to primitive (apparently without hint), then try again. */
79718 	if ((type_mask_x & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER)) &&
79719 	    (type_mask_y & DUK_TYPE_MASK_OBJECT)) {
79720 		/* No symbol check needed because symbols and strings are accepted. */
79721 		duk_push_tval(thr, tv_x);
79722 		duk_push_tval(thr, tv_y);
79723 		duk_to_primitive(thr, -1, DUK_HINT_NONE);  /* apparently no hint? */
79724 		goto recursive_call;
79725 	}
79726 	if ((type_mask_x & DUK_TYPE_MASK_OBJECT) &&
79727 	    (type_mask_y & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER))) {
79728 		/* No symbol check needed because symbols and strings are accepted. */
79729 		duk_push_tval(thr, tv_x);
79730 		duk_push_tval(thr, tv_y);
79731 		duk_to_primitive(thr, -2, DUK_HINT_NONE);  /* apparently no hint? */
79732 		goto recursive_call;
79733 	}
79734 
79735 	/* Nothing worked -> not equal. */
79736 	return 0;
79737 
79738  recursive_call:
79739 	/* Shared code path to call the helper again with arguments on stack top. */
79740 	{
79741 		duk_bool_t rc;
79742 		rc = duk_js_equals_helper(thr,
79743 		                          DUK_GET_TVAL_NEGIDX(thr, -2),
79744 		                          DUK_GET_TVAL_NEGIDX(thr, -1),
79745 		                          0 /*flags:nonstrict*/);
79746 		duk_pop_2_unsafe(thr);
79747 		return rc;
79748 	}
79749 }
79750 
79751 /*
79752  *  Comparisons (x >= y, x > y, x <= y, x < y)
79753  *
79754  *  E5 Section 11.8.5: implement 'x < y' and then use negate and eval_left_first
79755  *  flags to get the rest.
79756  */
79757 
79758 /* XXX: this should probably just operate on the stack top, because it
79759  * needs to push stuff on the stack anyway...
79760  */
79761 
79762 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) {
79763 	duk_size_t prefix_len;
79764 	duk_small_int_t rc;
79765 
79766 	prefix_len = (len1 <= len2 ? len1 : len2);
79767 
79768 	/* duk_memcmp() is guaranteed to return zero (equal) for zero length
79769 	 * inputs.
79770 	 */
79771 	rc = duk_memcmp_unsafe((const void *) buf1,
79772 	                       (const void *) buf2,
79773 	                       (size_t) prefix_len);
79774 
79775 	if (rc < 0) {
79776 		return -1;
79777 	} else if (rc > 0) {
79778 		return 1;
79779 	}
79780 
79781 	/* prefix matches, lengths matter now */
79782 	if (len1 < len2) {
79783 		/* e.g. "x" < "xx" */
79784 		return -1;
79785 	} else if (len1 > len2) {
79786 		return 1;
79787 	}
79788 
79789 	return 0;
79790 }
79791 
79792 DUK_INTERNAL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2) {
79793 	/*
79794 	 *  String comparison (E5 Section 11.8.5, step 4), which
79795 	 *  needs to compare codepoint by codepoint.
79796 	 *
79797 	 *  However, UTF-8 allows us to use strcmp directly: the shared
79798 	 *  prefix will be encoded identically (UTF-8 has unique encoding)
79799 	 *  and the first differing character can be compared with a simple
79800 	 *  unsigned byte comparison (which strcmp does).
79801 	 *
79802 	 *  This will not work properly for non-xutf-8 strings, but this
79803 	 *  is not an issue for compliance.
79804 	 */
79805 
79806 	DUK_ASSERT(h1 != NULL);
79807 	DUK_ASSERT(h2 != NULL);
79808 
79809 	return duk_js_data_compare((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h1),
79810 	                           (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h2),
79811 	                           (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1),
79812 	                           (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2));
79813 }
79814 
79815 #if 0  /* unused */
79816 DUK_INTERNAL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2) {
79817 	/* Similar to String comparison. */
79818 
79819 	DUK_ASSERT(h1 != NULL);
79820 	DUK_ASSERT(h2 != NULL);
79821 	DUK_UNREF(heap);
79822 
79823 	return duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h1),
79824 	                           (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h2),
79825 	                           (duk_size_t) DUK_HBUFFER_GET_SIZE(h1),
79826 	                           (duk_size_t) DUK_HBUFFER_GET_SIZE(h2));
79827 }
79828 #endif
79829 
79830 #if defined(DUK_USE_FASTINT)
79831 DUK_LOCAL duk_bool_t duk__compare_fastint(duk_bool_t retval, duk_int64_t v1, duk_int64_t v2) {
79832 	DUK_ASSERT(retval == 0 || retval == 1);
79833 	if (v1 < v2) {
79834 		return retval ^ 1;
79835 	} else {
79836 		return retval;
79837 	}
79838 }
79839 #endif
79840 
79841 #if defined(DUK_USE_PARANOID_MATH)
79842 DUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk_double_t d2) {
79843 	duk_small_int_t c1, s1, c2, s2;
79844 
79845 	DUK_ASSERT(retval == 0 || retval == 1);
79846 	c1 = (duk_small_int_t) DUK_FPCLASSIFY(d1);
79847 	s1 = (duk_small_int_t) DUK_SIGNBIT(d1);
79848 	c2 = (duk_small_int_t) DUK_FPCLASSIFY(d2);
79849 	s2 = (duk_small_int_t) DUK_SIGNBIT(d2);
79850 
79851 	if (c1 == DUK_FP_NAN || c2 == DUK_FP_NAN) {
79852 		return 0;  /* Always false, regardless of negation. */
79853 	}
79854 
79855 	if (c1 == DUK_FP_ZERO && c2 == DUK_FP_ZERO) {
79856 		/* For all combinations: +0 < +0, +0 < -0, -0 < +0, -0 < -0,
79857 		 * steps e, f, and g.
79858 		 */
79859 		return retval;  /* false */
79860 	}
79861 
79862 	if (d1 == d2) {
79863 		return retval;  /* false */
79864 	}
79865 
79866 	if (c1 == DUK_FP_INFINITE && s1 == 0) {
79867 		/* x == +Infinity */
79868 		return retval;  /* false */
79869 	}
79870 
79871 	if (c2 == DUK_FP_INFINITE && s2 == 0) {
79872 		/* y == +Infinity */
79873 		return retval ^ 1;  /* true */
79874 	}
79875 
79876 	if (c2 == DUK_FP_INFINITE && s2 != 0) {
79877 		/* y == -Infinity */
79878 		return retval;  /* false */
79879 	}
79880 
79881 	if (c1 == DUK_FP_INFINITE && s1 != 0) {
79882 		/* x == -Infinity */
79883 		return retval ^ 1;  /* true */
79884 	}
79885 
79886 	if (d1 < d2) {
79887 		return retval ^ 1;  /* true */
79888 	}
79889 
79890 	return retval;  /* false */
79891 }
79892 #else  /* DUK_USE_PARANOID_MATH */
79893 DUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk_double_t d2) {
79894 	/* This comparison tree relies doesn't match the exact steps in
79895 	 * E5 Section 11.8.5 but should produce the same results.  The
79896 	 * steps rely on exact IEEE semantics for NaNs, etc.
79897 	 */
79898 
79899 	DUK_ASSERT(retval == 0 || retval == 1);
79900 	if (d1 < d2) {
79901 		/* In no case should both (d1 < d2) and (d2 < d1) be true.
79902 		 * It's possible that neither is true though, and that's
79903 		 * handled below.
79904 		 */
79905 		DUK_ASSERT(!(d2 < d1));
79906 
79907 		/* - d1 < d2, both d1/d2 are normals (not Infinity, not NaN)
79908 		 * - d2 is +Infinity, d1 != +Infinity and NaN
79909 		 * - d1 is -Infinity, d2 != -Infinity and NaN
79910 		 */
79911 		return retval ^ 1;
79912 	} else {
79913 		if (d2 < d1) {
79914 			/* - !(d1 < d2), both d1/d2 are normals (not Infinity, not NaN)
79915 			 * - d1 is +Infinity, d2 != +Infinity and NaN
79916 			 * - d2 is -Infinity, d1 != -Infinity and NaN
79917 			 */
79918 			return retval;
79919 		} else {
79920 			/* - d1 and/or d2 is NaN
79921 			 * - d1 and d2 are both +/- 0
79922 			 * - d1 == d2 (including infinities)
79923 			 */
79924 			if (duk_double_is_nan(d1) || duk_double_is_nan(d2)) {
79925 				/* Note: undefined from Section 11.8.5 always
79926 				 * results in false return (see e.g. Section
79927 				 * 11.8.3) - hence special treatment here.
79928 				 */
79929 				return 0;  /* zero regardless of negation */
79930 			} else {
79931 				return retval;
79932 			}
79933 		}
79934 	}
79935 }
79936 #endif  /* DUK_USE_PARANOID_MATH */
79937 
79938 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) {
79939 	duk_double_t d1, d2;
79940 	duk_small_int_t rc;
79941 	duk_bool_t retval;
79942 
79943 	DUK_ASSERT(DUK_COMPARE_FLAG_NEGATE == 1);  /* Rely on this flag being lowest. */
79944 	retval = flags & DUK_COMPARE_FLAG_NEGATE;
79945 	DUK_ASSERT(retval == 0 || retval == 1);
79946 
79947 	/* Fast path for fastints */
79948 #if defined(DUK_USE_FASTINT)
79949 	if (DUK_LIKELY(DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y))) {
79950 		return duk__compare_fastint(retval,
79951 		                            DUK_TVAL_GET_FASTINT(tv_x),
79952 		                            DUK_TVAL_GET_FASTINT(tv_y));
79953 	}
79954 #endif  /* DUK_USE_FASTINT */
79955 
79956 	/* Fast path for numbers (one of which may be a fastint) */
79957 #if !defined(DUK_USE_PREFER_SIZE)
79958 	if (DUK_LIKELY(DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y))) {
79959 		return duk__compare_number(retval,
79960 		                           DUK_TVAL_GET_NUMBER(tv_x),
79961 		                           DUK_TVAL_GET_NUMBER(tv_y));
79962 	}
79963 #endif
79964 
79965 	/* Slow path */
79966 
79967 	duk_push_tval(thr, tv_x);
79968 	duk_push_tval(thr, tv_y);
79969 
79970 	if (flags & DUK_COMPARE_FLAG_EVAL_LEFT_FIRST) {
79971 		duk_to_primitive(thr, -2, DUK_HINT_NUMBER);
79972 		duk_to_primitive(thr, -1, DUK_HINT_NUMBER);
79973 	} else {
79974 		duk_to_primitive(thr, -1, DUK_HINT_NUMBER);
79975 		duk_to_primitive(thr, -2, DUK_HINT_NUMBER);
79976 	}
79977 
79978 	/* Note: reuse variables */
79979 	tv_x = DUK_GET_TVAL_NEGIDX(thr, -2);
79980 	tv_y = DUK_GET_TVAL_NEGIDX(thr, -1);
79981 
79982 	if (DUK_TVAL_IS_STRING(tv_x) && DUK_TVAL_IS_STRING(tv_y)) {
79983 		duk_hstring *h1 = DUK_TVAL_GET_STRING(tv_x);
79984 		duk_hstring *h2 = DUK_TVAL_GET_STRING(tv_y);
79985 		DUK_ASSERT(h1 != NULL);
79986 		DUK_ASSERT(h2 != NULL);
79987 
79988 		if (DUK_LIKELY(!DUK_HSTRING_HAS_SYMBOL(h1) && !DUK_HSTRING_HAS_SYMBOL(h2))) {
79989 			rc = duk_js_string_compare(h1, h2);
79990 			duk_pop_2_unsafe(thr);
79991 			if (rc < 0) {
79992 				return retval ^ 1;
79993 			} else {
79994 				return retval;
79995 			}
79996 		}
79997 
79998 		/* One or both are Symbols: fall through to handle in the
79999 		 * generic path.  Concretely, ToNumber() will fail.
80000 		 */
80001 	}
80002 
80003 	/* Ordering should not matter (E5 Section 11.8.5, step 3.a). */
80004 #if 0
80005 	if (flags & DUK_COMPARE_FLAG_EVAL_LEFT_FIRST) {
80006 		d1 = duk_to_number_m2(thr);
80007 		d2 = duk_to_number_m1(thr);
80008 	} else {
80009 		d2 = duk_to_number_m1(thr);
80010 		d1 = duk_to_number_m2(thr);
80011 	}
80012 #endif
80013 	d1 = duk_to_number_m2(thr);
80014 	d2 = duk_to_number_m1(thr);
80015 
80016 	/* We want to duk_pop_2_unsafe(thr); because the values are numbers
80017 	 * no decref check is needed.
80018 	 */
80019 #if defined(DUK_USE_PREFER_SIZE)
80020 	duk_pop_2_nodecref_unsafe(thr);
80021 #else
80022 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk_get_tval(thr, -2)));
80023 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk_get_tval(thr, -1)));
80024 	DUK_ASSERT(duk_get_top(thr) >= 2);
80025 	thr->valstack_top -= 2;
80026 	tv_x = thr->valstack_top;
80027 	tv_y = tv_x + 1;
80028 	DUK_TVAL_SET_UNDEFINED(tv_x);  /* Value stack policy */
80029 	DUK_TVAL_SET_UNDEFINED(tv_y);
80030 #endif
80031 
80032 	return duk__compare_number(retval, d1, d2);
80033 }
80034 
80035 /*
80036  *  instanceof
80037  */
80038 
80039 /*
80040  *  ES2015 Section 7.3.19 describes the OrdinaryHasInstance() algorithm
80041  *  which covers both bound and non-bound functions; in effect the algorithm
80042  *  includes E5 Sections 11.8.6, 15.3.5.3, and 15.3.4.5.3.
80043  *
80044  *  ES2015 Section 12.9.4 describes the instanceof operator which first
80045  *  checks @@hasInstance well-known symbol and falls back to
80046  *  OrdinaryHasInstance().
80047  *
80048  *  Limited Proxy support: don't support 'getPrototypeOf' trap but
80049  *  continue lookup in Proxy target if the value is a Proxy.
80050  */
80051 
80052 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) {
80053 	duk_hobject *func;
80054 	duk_hobject *val;
80055 	duk_hobject *proto;
80056 	duk_tval *tv;
80057 	duk_bool_t skip_first;
80058 	duk_uint_t sanity;
80059 
80060 	/*
80061 	 *  Get the values onto the stack first.  It would be possible to cover
80062 	 *  some normal cases without resorting to the value stack.
80063 	 *
80064 	 *  The right hand side could be a light function (as they generally
80065 	 *  behave like objects).  Light functions never have a 'prototype'
80066 	 *  property so E5.1 Section 15.3.5.3 step 3 always throws a TypeError.
80067 	 *  Using duk_require_hobject() is thus correct (except for error msg).
80068 	 */
80069 
80070 	duk_push_tval(thr, tv_x);
80071 	duk_push_tval(thr, tv_y);
80072 	func = duk_require_hobject(thr, -1);
80073 	DUK_ASSERT(func != NULL);
80074 
80075 #if defined(DUK_USE_SYMBOL_BUILTIN)
80076 	/*
80077 	 *  @@hasInstance check, ES2015 Section 12.9.4, Steps 2-4.
80078 	 */
80079 	if (!skip_sym_check) {
80080 		if (duk_get_method_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)) {
80081 			/* [ ... lhs rhs func ] */
80082 			duk_insert(thr, -3);    /* -> [ ... func lhs rhs ] */
80083 			duk_swap_top(thr, -2);  /* -> [ ... func rhs(this) lhs ] */
80084 			duk_call_method(thr, 1);
80085 			return duk_to_boolean_top_pop(thr);
80086 		}
80087 	}
80088 #else
80089 	DUK_UNREF(skip_sym_check);
80090 #endif
80091 
80092 	/*
80093 	 *  For bound objects, [[HasInstance]] just calls the target function
80094 	 *  [[HasInstance]].  If that is again a bound object, repeat until
80095 	 *  we find a non-bound Function object.
80096 	 *
80097 	 *  The bound function chain is now "collapsed" so there can be only
80098 	 *  one bound function in the chain.
80099 	 */
80100 
80101 	if (!DUK_HOBJECT_IS_CALLABLE(func)) {
80102 		/*
80103 		 *  Note: of native ECMAScript objects, only Function instances
80104 		 *  have a [[HasInstance]] internal property.  Custom objects might
80105 		 *  also have it, but not in current implementation.
80106 		 *
80107 		 *  XXX: add a separate flag, DUK_HOBJECT_FLAG_ALLOW_INSTANCEOF?
80108 		 */
80109 		goto error_invalid_rval;
80110 	}
80111 
80112 	if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
80113 		duk_push_tval(thr, &((duk_hboundfunc *) (void *) func)->target);
80114 		duk_replace(thr, -2);
80115 		func = duk_require_hobject(thr, -1);  /* lightfunc throws */
80116 
80117 		/* Rely on Function.prototype.bind() never creating bound
80118 		 * functions whose target is not proper.
80119 		 */
80120 		DUK_ASSERT(func != NULL);
80121 		DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(func));
80122 	}
80123 
80124 	/*
80125 	 *  'func' is now a non-bound object which supports [[HasInstance]]
80126 	 *  (which here just means DUK_HOBJECT_FLAG_CALLABLE).  Move on
80127 	 *  to execute E5 Section 15.3.5.3.
80128 	 */
80129 
80130 	DUK_ASSERT(func != NULL);
80131 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
80132 	DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(func));
80133 
80134 	/* [ ... lval rval(func) ] */
80135 
80136 	/* For lightfuncs, buffers, and pointers start the comparison directly
80137 	 * from the virtual prototype object.
80138 	 */
80139 	skip_first = 0;
80140 	tv = DUK_GET_TVAL_NEGIDX(thr, -2);
80141 	switch (DUK_TVAL_GET_TAG(tv)) {
80142 	case DUK_TAG_LIGHTFUNC:
80143 		val = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
80144 		DUK_ASSERT(val != NULL);
80145 		break;
80146 	case DUK_TAG_BUFFER:
80147 		val = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
80148 		DUK_ASSERT(val != NULL);
80149 		break;
80150 	case DUK_TAG_POINTER:
80151 		val = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
80152 		DUK_ASSERT(val != NULL);
80153 		break;
80154 	case DUK_TAG_OBJECT:
80155 		skip_first = 1;  /* Ignore object itself on first round. */
80156 		val = DUK_TVAL_GET_OBJECT(tv);
80157 		DUK_ASSERT(val != NULL);
80158 		break;
80159 	default:
80160 		goto pop2_and_false;
80161 	}
80162 	DUK_ASSERT(val != NULL);  /* Loop doesn't actually rely on this. */
80163 
80164 	/* Look up .prototype of rval.  Leave it on the value stack in case it
80165 	 * has been virtualized (e.g. getter, Proxy trap).
80166 	 */
80167 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_PROTOTYPE);  /* -> [ ... lval rval rval.prototype ] */
80168 #if defined(DUK_USE_VERBOSE_ERRORS)
80169 	proto = duk_get_hobject(thr, -1);
80170 	if (proto == NULL) {
80171 		goto error_invalid_rval_noproto;
80172 	}
80173 #else
80174 	proto = duk_require_hobject(thr, -1);
80175 #endif
80176 
80177 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
80178 	do {
80179 		/*
80180 		 *  Note: prototype chain is followed BEFORE first comparison.  This
80181 		 *  means that the instanceof lval is never itself compared to the
80182 		 *  rval.prototype property.  This is apparently intentional, see E5
80183 		 *  Section 15.3.5.3, step 4.a.
80184 		 *
80185 		 *  Also note:
80186 		 *
80187 		 *      js> (function() {}) instanceof Function
80188 		 *      true
80189 		 *      js> Function instanceof Function
80190 		 *      true
80191 		 *
80192 		 *  For the latter, h_proto will be Function.prototype, which is the
80193 		 *  built-in Function prototype.  Because Function.[[Prototype]] is
80194 		 *  also the built-in Function prototype, the result is true.
80195 		 */
80196 
80197 		if (!val) {
80198 			goto pop3_and_false;
80199 		}
80200 
80201 		DUK_ASSERT(val != NULL);
80202 #if defined(DUK_USE_ES6_PROXY)
80203 		val = duk_hobject_resolve_proxy_target(val);
80204 #endif
80205 
80206 		if (skip_first) {
80207 			skip_first = 0;
80208 		} else if (val == proto) {
80209 			goto pop3_and_true;
80210 		}
80211 
80212 		DUK_ASSERT(val != NULL);
80213 		val = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, val);
80214 	} while (--sanity > 0);
80215 
80216 	if (DUK_UNLIKELY(sanity == 0)) {
80217 		DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
80218 		DUK_WO_NORETURN(return 0;);
80219 	}
80220 	DUK_UNREACHABLE();
80221 
80222  pop2_and_false:
80223 	duk_pop_2_unsafe(thr);
80224 	return 0;
80225 
80226  pop3_and_false:
80227 	duk_pop_3_unsafe(thr);
80228 	return 0;
80229 
80230  pop3_and_true:
80231 	duk_pop_3_unsafe(thr);
80232 	return 1;
80233 
80234  error_invalid_rval:
80235 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_INSTANCEOF_RVAL);
80236 	DUK_WO_NORETURN(return 0;);
80237 
80238 #if defined(DUK_USE_VERBOSE_ERRORS)
80239  error_invalid_rval_noproto:
80240 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO);
80241 	DUK_WO_NORETURN(return 0;);
80242 #endif
80243 }
80244 
80245 #if defined(DUK_USE_SYMBOL_BUILTIN)
80246 DUK_INTERNAL duk_bool_t duk_js_instanceof_ordinary(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
80247 	return duk__js_instanceof_helper(thr, tv_x, tv_y, 1 /*skip_sym_check*/);
80248 }
80249 #endif
80250 
80251 DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
80252 	return duk__js_instanceof_helper(thr, tv_x, tv_y, 0 /*skip_sym_check*/);
80253 }
80254 
80255 /*
80256  *  in
80257  */
80258 
80259 /*
80260  *  E5 Sections 11.8.7, 8.12.6.
80261  *
80262  *  Basically just a property existence check using [[HasProperty]].
80263  */
80264 
80265 DUK_INTERNAL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
80266 	duk_bool_t retval;
80267 
80268 	/*
80269 	 *  Get the values onto the stack first.  It would be possible to cover
80270 	 *  some normal cases without resorting to the value stack (e.g. if
80271 	 *  lval is already a string).
80272 	 */
80273 
80274 	/* XXX: The ES5/5.1/6 specifications require that the key in 'key in obj'
80275 	 * must be string coerced before the internal HasProperty() algorithm is
80276 	 * invoked.  A fast path skipping coercion could be safely implemented for
80277 	 * numbers (as number-to-string coercion has no side effects).  For ES2015
80278 	 * proxy behavior, the trap 'key' argument must be in a string coerced
80279 	 * form (which is a shame).
80280 	 */
80281 
80282 	/* TypeError if rval is not an object or object like (e.g. lightfunc
80283 	 * or plain buffer).
80284 	 */
80285 	duk_push_tval(thr, tv_x);
80286 	duk_push_tval(thr, tv_y);
80287 	duk_require_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
80288 
80289 	(void) duk_to_property_key_hstring(thr, -2);
80290 
80291 	retval = duk_hobject_hasprop(thr,
80292 	                             DUK_GET_TVAL_NEGIDX(thr, -1),
80293 	                             DUK_GET_TVAL_NEGIDX(thr, -2));
80294 
80295 	duk_pop_2_unsafe(thr);
80296 	return retval;
80297 }
80298 
80299 /*
80300  *  typeof
80301  *
80302  *  E5 Section 11.4.3.
80303  *
80304  *  Very straightforward.  The only question is what to return for our
80305  *  non-standard tag / object types.
80306  *
80307  *  There is an unfortunate string constant define naming problem with
80308  *  typeof return values for e.g. "Object" and "object"; careful with
80309  *  the built-in string defines.  The LC_XXX defines are used for the
80310  *  lowercase variants now.
80311  */
80312 
80313 DUK_INTERNAL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x) {
80314 	duk_small_uint_t stridx = 0;
80315 
80316 	switch (DUK_TVAL_GET_TAG(tv_x)) {
80317 	case DUK_TAG_UNDEFINED: {
80318 		stridx = DUK_STRIDX_LC_UNDEFINED;
80319 		break;
80320 	}
80321 	case DUK_TAG_NULL: {
80322 		/* Note: not a typo, "object" is returned for a null value. */
80323 		stridx = DUK_STRIDX_LC_OBJECT;
80324 		break;
80325 	}
80326 	case DUK_TAG_BOOLEAN: {
80327 		stridx = DUK_STRIDX_LC_BOOLEAN;
80328 		break;
80329 	}
80330 	case DUK_TAG_POINTER: {
80331 		/* Implementation specific. */
80332 		stridx = DUK_STRIDX_LC_POINTER;
80333 		break;
80334 	}
80335 	case DUK_TAG_STRING: {
80336 		duk_hstring *str;
80337 
80338 		/* All internal keys are identified as Symbols. */
80339 		str = DUK_TVAL_GET_STRING(tv_x);
80340 		DUK_ASSERT(str != NULL);
80341 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(str))) {
80342 			stridx = DUK_STRIDX_LC_SYMBOL;
80343 		} else {
80344 			stridx = DUK_STRIDX_LC_STRING;
80345 		}
80346 		break;
80347 	}
80348 	case DUK_TAG_OBJECT: {
80349 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_x);
80350 		DUK_ASSERT(obj != NULL);
80351 		if (DUK_HOBJECT_IS_CALLABLE(obj)) {
80352 			stridx = DUK_STRIDX_LC_FUNCTION;
80353 		} else {
80354 			stridx = DUK_STRIDX_LC_OBJECT;
80355 		}
80356 		break;
80357 	}
80358 	case DUK_TAG_BUFFER: {
80359 		/* Implementation specific.  In Duktape 1.x this would be
80360 		 * 'buffer', in Duktape 2.x changed to 'object' because plain
80361 		 * buffers now mimic Uint8Array objects.
80362 		 */
80363 		stridx = DUK_STRIDX_LC_OBJECT;
80364 		break;
80365 	}
80366 	case DUK_TAG_LIGHTFUNC: {
80367 		stridx = DUK_STRIDX_LC_FUNCTION;
80368 		break;
80369 	}
80370 #if defined(DUK_USE_FASTINT)
80371 	case DUK_TAG_FASTINT:
80372 #endif
80373 	default: {
80374 		/* number */
80375 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));
80376 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
80377 		stridx = DUK_STRIDX_LC_NUMBER;
80378 		break;
80379 	}
80380 	}
80381 
80382 	DUK_ASSERT_STRIDX_VALID(stridx);
80383 	return stridx;
80384 }
80385 
80386 /*
80387  *  Array index and length
80388  *
80389  *  Array index: E5 Section 15.4
80390  *  Array length: E5 Section 15.4.5.1 steps 3.c - 3.d (array length write)
80391  */
80392 
80393 /* Compure array index from string context, or return a "not array index"
80394  * indicator.
80395  */
80396 DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, duk_uint32_t blen) {
80397 	duk_uarridx_t res;
80398 
80399 	/* Only strings with byte length 1-10 can be 32-bit array indices.
80400 	 * Leading zeroes (except '0' alone), plus/minus signs are not allowed.
80401 	 * We could do a lot of prechecks here, but since most strings won't
80402 	 * start with any digits, it's simpler to just parse the number and
80403 	 * fail quickly.
80404 	 */
80405 
80406 	res = 0;
80407 	if (blen == 0) {
80408 		goto parse_fail;
80409 	}
80410 	do {
80411 		duk_uarridx_t dig;
80412 		dig = (duk_uarridx_t) (*str++) - DUK_ASC_0;
80413 
80414 		if (dig <= 9U) {
80415 			/* Careful overflow handling.  When multiplying by 10:
80416 			 * - 0x19999998 x 10 = 0xfffffff0: no overflow, and adding
80417 			 *   0...9 is safe.
80418 			 * - 0x19999999 x 10 = 0xfffffffa: no overflow, adding
80419 			 *   0...5 is safe, 6...9 overflows.
80420 			 * - 0x1999999a x 10 = 0x100000004: always overflow.
80421 			 */
80422 			if (DUK_UNLIKELY(res >= 0x19999999UL)) {
80423 				if (res >= 0x1999999aUL) {
80424 					/* Always overflow. */
80425 					goto parse_fail;
80426 				}
80427 				DUK_ASSERT(res == 0x19999999UL);
80428 				if (dig >= 6U) {
80429 					goto parse_fail;
80430 				}
80431 				res = 0xfffffffaUL + dig;
80432 				DUK_ASSERT(res >= 0xfffffffaUL);
80433 				DUK_ASSERT_DISABLE(res <= 0xffffffffUL);  /* range */
80434 			} else {
80435 				res = res * 10U + dig;
80436 				if (DUK_UNLIKELY(res == 0)) {
80437 					/* If 'res' is 0, previous 'res' must
80438 					 * have been 0 and we scanned in a zero.
80439 					 * This is only allowed if blen == 1,
80440 					 * i.e. the exact string '0'.
80441 					 */
80442 					if (blen == (duk_uint32_t) 1) {
80443 						return 0;
80444 					}
80445 					goto parse_fail;
80446 				}
80447 			}
80448 		} else {
80449 			/* Because 'dig' is unsigned, catches both values
80450 			 * above '9' and below '0'.
80451 			 */
80452 			goto parse_fail;
80453 		}
80454 	} while (--blen > 0);
80455 
80456 	return res;
80457 
80458  parse_fail:
80459 	return DUK_HSTRING_NO_ARRAY_INDEX;
80460 }
80461 
80462 #if !defined(DUK_USE_HSTRING_ARRIDX)
80463 /* Get array index for a string which is known to be an array index.  This helper
80464  * is needed when duk_hstring doesn't concretely store the array index, but strings
80465  * are flagged as array indices at intern time.
80466  */
80467 DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast_known(duk_hstring *h) {
80468 	const duk_uint8_t *p;
80469 	duk_uarridx_t res;
80470 	duk_uint8_t t;
80471 
80472 	DUK_ASSERT(h != NULL);
80473 	DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(h));
80474 
80475 	p = DUK_HSTRING_GET_DATA(h);
80476 	res = 0;
80477 	for (;;) {
80478 		t = *p++;
80479 		if (DUK_UNLIKELY(t == 0)) {
80480 			/* Scanning to NUL is always safe for interned strings. */
80481 			break;
80482 		}
80483 		DUK_ASSERT(t >= (duk_uint8_t) DUK_ASC_0 && t <= (duk_uint8_t) DUK_ASC_9);
80484 		res = res * 10U + (duk_uarridx_t) t - (duk_uarridx_t) DUK_ASC_0;
80485 	}
80486 	return res;
80487 }
80488 
80489 DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h) {
80490 	DUK_ASSERT(h != NULL);
80491 	if (!DUK_HSTRING_HAS_ARRIDX(h)) {
80492 		return DUK_HSTRING_NO_ARRAY_INDEX;
80493 	}
80494 	return duk_js_to_arrayindex_hstring_fast_known(h);
80495 }
80496 #endif  /* DUK_USE_HSTRING_ARRIDX */
80497 /*
80498  *  Identifier access and function closure handling.
80499  *
80500  *  Provides the primitives for slow path identifier accesses: GETVAR,
80501  *  PUTVAR, DELVAR, etc.  The fast path, direct register accesses, should
80502  *  be used for most identifier accesses.  Consequently, these slow path
80503  *  primitives should be optimized for maximum compactness.
80504  *
80505  *  ECMAScript environment records (declarative and object) are represented
80506  *  as internal objects with control keys.  Environment records have a
80507  *  parent record ("outer environment reference") which is represented by
80508  *  the implicit prototype for technical reasons (in other words, it is a
80509  *  convenient field).  The prototype chain is not followed in the ordinary
80510  *  sense for variable lookups.
80511  *
80512  *  See identifier-handling.rst for more details on the identifier algorithms
80513  *  and the internal representation.  See function-objects.rst for details on
80514  *  what function templates and instances are expected to look like.
80515  *
80516  *  Care must be taken to avoid duk_tval pointer invalidation caused by
80517  *  e.g. value stack or object resizing.
80518  *
80519  *  TODO: properties for function instances could be initialized much more
80520  *  efficiently by creating a property allocation for a certain size and
80521  *  filling in keys and values directly (and INCREFing both with "bulk incref"
80522  *  primitives.
80523  *
80524  *  XXX: duk_hobject_getprop() and duk_hobject_putprop() calls are a bit
80525  *  awkward (especially because they follow the prototype chain); rework
80526  *  if "raw" own property helpers are added.
80527  */
80528 
80529 /* #include duk_internal.h -> already included */
80530 
80531 /*
80532  *  Local result type for duk__get_identifier_reference() lookup.
80533  */
80534 
80535 typedef struct {
80536 	duk_hobject *env;
80537 	duk_hobject *holder;      /* for object-bound identifiers */
80538 	duk_tval *value;          /* for register-bound and declarative env identifiers */
80539 	duk_uint_t attrs;         /* property attributes for identifier (relevant if value != NULL) */
80540 	duk_bool_t has_this;      /* for object-bound identifiers: provide 'this' binding */
80541 } duk__id_lookup_result;
80542 
80543 /*
80544  *  Create a new function object based on a "template function" which contains
80545  *  compiled bytecode, constants, etc, but lacks a lexical environment.
80546  *
80547  *  ECMAScript requires that each created closure is a separate object, with
80548  *  its own set of editable properties.  However, structured property values
80549  *  (such as the formal arguments list and the variable map) are shared.
80550  *  Also the bytecode, constants, and inner functions are shared.
80551  *
80552  *  See E5 Section 13.2 for detailed requirements on the function objects;
80553  *  there are no similar requirements for function "templates" which are an
80554  *  implementation dependent internal feature.  Also see function-objects.rst
80555  *  for a discussion on the function instance properties provided by this
80556  *  implementation.
80557  *
80558  *  Notes:
80559  *
80560  *   * Order of internal properties should match frequency of use, since the
80561  *     properties will be linearly scanned on lookup (functions usually don't
80562  *     have enough properties to warrant a hash part).
80563  *
80564  *   * The created closure is independent of its template; they do share the
80565  *     same 'data' buffer object, but the template object itself can be freed
80566  *     even if the closure object remains reachable.
80567  */
80568 
80569 DUK_LOCAL void duk__inc_data_inner_refcounts(duk_hthread *thr, duk_hcompfunc *f) {
80570 	duk_tval *tv, *tv_end;
80571 	duk_hobject **funcs, **funcs_end;
80572 
80573 	DUK_UNREF(thr);
80574 
80575 	/* If function creation fails due to out-of-memory, the data buffer
80576 	 * pointer may be NULL in some cases.  That's actually possible for
80577 	 * GC code, but shouldn't be possible here because the incomplete
80578 	 * function will be unwound from the value stack and never instantiated.
80579 	 */
80580 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, f) != NULL);
80581 
80582 	tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, f);
80583 	tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, f);
80584 	while (tv < tv_end) {
80585 		DUK_TVAL_INCREF(thr, tv);
80586 		tv++;
80587 	}
80588 
80589 	funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, f);
80590 	funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, f);
80591 	while (funcs < funcs_end) {
80592 		DUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) *funcs);
80593 		funcs++;
80594 	}
80595 }
80596 
80597 /* Push a new closure on the stack.
80598  *
80599  * Note: if fun_temp has NEWENV, i.e. a new lexical and variable declaration
80600  * is created when the function is called, only outer_lex_env matters
80601  * (outer_var_env is ignored and may or may not be same as outer_lex_env).
80602  */
80603 
80604 DUK_LOCAL const duk_uint16_t duk__closure_copy_proplist[] = {
80605 	/* order: most frequent to least frequent */
80606 	DUK_STRIDX_INT_VARMAP,
80607 	DUK_STRIDX_INT_FORMALS,
80608 #if defined(DUK_USE_PC2LINE)
80609 	DUK_STRIDX_INT_PC2LINE,
80610 #endif
80611 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
80612 	DUK_STRIDX_FILE_NAME,
80613 #endif
80614 #if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
80615 	DUK_STRIDX_INT_SOURCE
80616 #endif
80617 };
80618 
80619 DUK_INTERNAL
80620 void duk_js_push_closure(duk_hthread *thr,
80621                          duk_hcompfunc *fun_temp,
80622                          duk_hobject *outer_var_env,
80623                          duk_hobject *outer_lex_env,
80624                          duk_bool_t add_auto_proto) {
80625 	duk_hcompfunc *fun_clos;
80626 	duk_harray *formals;
80627 	duk_small_uint_t i;
80628 	duk_uint_t len_value;
80629 
80630 	DUK_ASSERT(fun_temp != NULL);
80631 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_temp) != NULL);
80632 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_temp) != NULL);
80633 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_temp) != NULL);
80634 	DUK_ASSERT(outer_var_env != NULL);
80635 	DUK_ASSERT(outer_lex_env != NULL);
80636 	DUK_UNREF(len_value);
80637 
80638 	DUK_STATS_INC(thr->heap, stats_envrec_pushclosure);
80639 
80640 	fun_clos = duk_push_hcompfunc(thr);
80641 	DUK_ASSERT(fun_clos != NULL);
80642 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) fun_clos) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
80643 
80644 	duk_push_hobject(thr, &fun_temp->obj);  /* -> [ ... closure template ] */
80645 
80646 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun_clos));
80647 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) == NULL);
80648 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_clos) == NULL);
80649 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_clos) == NULL);
80650 
80651 	DUK_HCOMPFUNC_SET_DATA(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_temp));
80652 	DUK_HCOMPFUNC_SET_FUNCS(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_temp));
80653 	DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_temp));
80654 
80655 	/* Note: all references inside 'data' need to get their refcounts
80656 	 * upped too.  This is the case because refcounts are decreased
80657 	 * through every function referencing 'data' independently.
80658 	 */
80659 
80660 	DUK_HBUFFER_INCREF(thr, DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos));
80661 	duk__inc_data_inner_refcounts(thr, fun_temp);
80662 
80663 	fun_clos->nregs = fun_temp->nregs;
80664 	fun_clos->nargs = fun_temp->nargs;
80665 #if defined(DUK_USE_DEBUGGER_SUPPORT)
80666 	fun_clos->start_line = fun_temp->start_line;
80667 	fun_clos->end_line = fun_temp->end_line;
80668 #endif
80669 
80670 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) != NULL);
80671 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_clos) != NULL);
80672 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_clos) != NULL);
80673 
80674 	/* XXX: Could also copy from template, but there's no way to have any
80675 	 * other value here now (used code has no access to the template).
80676 	 * Prototype is set by duk_push_hcompfunc().
80677 	 */
80678 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, &fun_clos->obj) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
80679 #if 0
80680 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &fun_clos->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
80681 #endif
80682 
80683 	/* Copy duk_hobject flags as is from the template using a mask.
80684 	 * Leave out duk_heaphdr owned flags just in case (e.g. if there's
80685 	 * some GC flag or similar).  Some flags can then be adjusted
80686 	 * separately if necessary.
80687 	 */
80688 
80689 	/* DUK_HEAPHDR_SET_FLAGS() masks changes to non-duk_heaphdr flags only. */
80690 	DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) fun_clos, DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_temp));
80691 	DUK_DD(DUK_DDPRINT("fun_temp heaphdr flags: 0x%08lx, fun_clos heaphdr flags: 0x%08lx",
80692 	                   (unsigned long) DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_temp),
80693 	                   (unsigned long) DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_clos)));
80694 
80695 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
80696 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&fun_clos->obj));
80697 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&fun_clos->obj));
80698 	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&fun_clos->obj));
80699 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(&fun_clos->obj));
80700 	/* DUK_HOBJECT_FLAG_ARRAY_PART: don't care */
80701 	/* DUK_HOBJECT_FLAG_NEWENV: handled below */
80702 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&fun_clos->obj));
80703 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&fun_clos->obj));
80704 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&fun_clos->obj));
80705 
80706 	if (!DUK_HOBJECT_HAS_CONSTRUCTABLE(&fun_clos->obj)) {
80707 		/* If the template is not constructable don't add an automatic
80708 		 * .prototype property.  This is the case for e.g. ES2015 object
80709 		 * literal getters/setters and method definitions.
80710 		 */
80711 		add_auto_proto = 0;
80712 	}
80713 
80714 	/*
80715 	 *  Setup environment record properties based on the template and
80716 	 *  its flags.
80717 	 *
80718 	 *  If DUK_HOBJECT_HAS_NEWENV(fun_temp) is true, the environment
80719 	 *  records represent identifiers "outside" the function; the
80720 	 *  "inner" environment records are created on demand.  Otherwise,
80721 	 *  the environment records are those that will be directly used
80722 	 *  (e.g. for declarations).
80723 	 *
80724 	 *  _Lexenv is always set; _Varenv defaults to _Lexenv if missing,
80725 	 *  so _Varenv is only set if _Lexenv != _Varenv.
80726 	 *
80727 	 *  This is relatively complex, see doc/identifier-handling.rst.
80728 	 */
80729 
80730 	if (DUK_HOBJECT_HAS_NEWENV(&fun_clos->obj)) {
80731 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
80732 		if (DUK_HOBJECT_HAS_NAMEBINDING(&fun_clos->obj)) {
80733 			duk_hobject *proto;
80734 			duk_hdecenv *new_env;
80735 
80736 			/*
80737 			 *  Named function expression, name needs to be bound
80738 			 *  in an intermediate environment record.  The "outer"
80739 			 *  lexical/variable environment will thus be:
80740 			 *
80741 			 *  a) { funcname: <func>, __prototype: outer_lex_env }
80742 			 *  b) { funcname: <func>, __prototype:  <globalenv> }  (if outer_lex_env missing)
80743 			 */
80744 
80745 			if (outer_lex_env) {
80746 				proto = outer_lex_env;
80747 			} else {
80748 				proto = thr->builtins[DUK_BIDX_GLOBAL_ENV];
80749 			}
80750 
80751 			/* -> [ ... closure template env ] */
80752 			new_env = duk_hdecenv_alloc(thr,
80753 			                            DUK_HOBJECT_FLAG_EXTENSIBLE |
80754 			                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
80755 			DUK_ASSERT(new_env != NULL);
80756 			duk_push_hobject(thr, (duk_hobject *) new_env);
80757 
80758 			DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
80759 			DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, proto);
80760 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, proto);
80761 
80762 			DUK_ASSERT(new_env->thread == NULL);  /* Closed. */
80763 			DUK_ASSERT(new_env->varmap == NULL);
80764 
80765 			/* It's important that duk_xdef_prop() is a 'raw define' so that any
80766 			 * properties in an ancestor are never an issue (they should never be
80767 			 * e.g. non-writable, but just in case).
80768 			 *
80769 			 * Because template objects are not visible to user code, the case
80770 			 * where .name is missing shouldn't happen in practice.  It it does,
80771 			 * the name 'undefined' gets bound and maps to the closure (which is
80772 			 * a bit odd, but safe).
80773 			 */
80774 			(void) duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
80775 			/* -> [ ... closure template env funcname ] */
80776 			duk_dup_m4(thr);                                           /* -> [ ... closure template env funcname closure ] */
80777 			duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE);           /* -> [ ... closure template env ] */
80778 			/* env[funcname] = closure */
80779 
80780 			/* [ ... closure template env ] */
80781 
80782 			DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, (duk_hobject *) new_env);
80783 			DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, (duk_hobject *) new_env);
80784 			DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);
80785 			DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);
80786 			duk_pop_unsafe(thr);
80787 
80788 			/* [ ... closure template ] */
80789 		}
80790 		else
80791 #endif  /* DUK_USE_FUNC_NAME_PROPERTY */
80792 		{
80793 			/*
80794 			 *  Other cases (function declaration, anonymous function expression,
80795 			 *  strict direct eval code).  The "outer" environment will be whatever
80796 			 *  the caller gave us.
80797 			 */
80798 
80799 			DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);
80800 			DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_lex_env);
80801 			DUK_HOBJECT_INCREF(thr, outer_lex_env);
80802 			DUK_HOBJECT_INCREF(thr, outer_lex_env);
80803 
80804 			/* [ ... closure template ] */
80805 		}
80806 	} else {
80807 		/*
80808 		 *  Function gets no new environment when called.  This is the
80809 		 *  case for global code, indirect eval code, and non-strict
80810 		 *  direct eval code.  There is no direct correspondence to the
80811 		 *  E5 specification, as global/eval code is not exposed as a
80812 		 *  function.
80813 		 */
80814 
80815 		DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj));
80816 
80817 		DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);
80818 		DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_var_env);
80819 		DUK_HOBJECT_INCREF(thr, outer_lex_env);  /* NULLs not allowed; asserted on entry */
80820 		DUK_HOBJECT_INCREF(thr, outer_var_env);
80821 	}
80822 	DUK_DDD(DUK_DDDPRINT("closure varenv -> %!ipO, lexenv -> %!ipO",
80823 	                     (duk_heaphdr *) fun_clos->var_env,
80824 	                     (duk_heaphdr *) fun_clos->lex_env));
80825 
80826 	/* Call handling assumes this for all callable closures. */
80827 	DUK_ASSERT(DUK_HCOMPFUNC_GET_LEXENV(thr->heap, fun_clos) != NULL);
80828 	DUK_ASSERT(DUK_HCOMPFUNC_GET_VARENV(thr->heap, fun_clos) != NULL);
80829 
80830 	/*
80831 	 *  Copy some internal properties directly
80832 	 *
80833 	 *  The properties will be non-writable and non-enumerable, but
80834 	 *  configurable.
80835 	 *
80836 	 *  Function templates are bare objects, so inheritance of internal
80837 	 *  Symbols is not an issue here even when using ordinary property
80838 	 *  reads.  The function instance created is not bare, so internal
80839 	 *  Symbols must be defined without inheritance checks.
80840 	 */
80841 
80842 	/* [ ... closure template ] */
80843 
80844 	DUK_DDD(DUK_DDDPRINT("copying properties: closure=%!iT, template=%!iT",
80845 	                     (duk_tval *) duk_get_tval(thr, -2),
80846 	                     (duk_tval *) duk_get_tval(thr, -1)));
80847 
80848 	for (i = 0; i < (duk_small_uint_t) (sizeof(duk__closure_copy_proplist) / sizeof(duk_uint16_t)); i++) {
80849 		duk_small_int_t stridx = (duk_small_int_t) duk__closure_copy_proplist[i];
80850 		if (duk_xget_owndataprop_stridx_short(thr, -1, stridx)) {
80851 			/* [ ... closure template val ] */
80852 			DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> found", (long) stridx));
80853 			duk_xdef_prop_stridx_short(thr, -3, stridx, DUK_PROPDESC_FLAGS_C);
80854 		} else {
80855 			DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> not found", (long) stridx));
80856 			duk_pop_unsafe(thr);
80857 		}
80858 	}
80859 
80860 	/*
80861 	 *  "length" maps to number of formals (E5 Section 13.2) for function
80862 	 *  declarations/expressions (non-bound functions).  Note that 'nargs'
80863 	 *  is NOT necessarily equal to the number of arguments.  Use length
80864 	 *  of _Formals; if missing, assume nargs matches .length.
80865 	 */
80866 
80867 	/* [ ... closure template ] */
80868 
80869 	formals = duk_hobject_get_formals(thr, (duk_hobject *) fun_temp);
80870 	if (formals) {
80871 		len_value = (duk_uint_t) formals->length;
80872 		DUK_DD(DUK_DDPRINT("closure length from _Formals -> %ld", (long) len_value));
80873 	} else {
80874 		len_value = fun_temp->nargs;
80875 		DUK_DD(DUK_DDPRINT("closure length defaulted from nargs -> %ld", (long) len_value));
80876 	}
80877 
80878 	duk_push_uint(thr, len_value);  /* [ ... closure template len_value ] */
80879 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
80880 
80881 	/*
80882 	 *  "prototype" is, by default, a fresh object with the "constructor"
80883 	 *  property.
80884 	 *
80885 	 *  Note that this creates a circular reference for every function
80886 	 *  instance (closure) which prevents refcount-based collection of
80887 	 *  function instances.
80888 	 *
80889 	 *  XXX: Try to avoid creating the default prototype object, because
80890 	 *  many functions are not used as constructors and the default
80891 	 *  prototype is unnecessary.  Perhaps it could be created on-demand
80892 	 *  when it is first accessed?
80893 	 */
80894 
80895 	/* [ ... closure template ] */
80896 
80897 	if (add_auto_proto) {
80898 		duk_push_object(thr);  /* -> [ ... closure template newobj ] */
80899 		duk_dup_m3(thr);       /* -> [ ... closure template newobj closure ] */
80900 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* -> [ ... closure template newobj ] */
80901 		duk_compact(thr, -1);  /* compact the prototype */
80902 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);     /* -> [ ... closure template ] */
80903 	}
80904 
80905 	/*
80906 	 *  "arguments" and "caller" must be mapped to throwers for strict
80907 	 *  mode and bound functions (E5 Section 15.3.5).
80908 	 *
80909 	 *  XXX: This is expensive to have for every strict function instance.
80910 	 *  Try to implement as virtual properties or on-demand created properties.
80911 	 */
80912 
80913 	/* [ ... closure template ] */
80914 
80915 	if (DUK_HOBJECT_HAS_STRICT(&fun_clos->obj)) {
80916 		duk_xdef_prop_stridx_thrower(thr, -2, DUK_STRIDX_CALLER);
80917 		duk_xdef_prop_stridx_thrower(thr, -2, DUK_STRIDX_LC_ARGUMENTS);
80918 	} else {
80919 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
80920 		DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property in use, add initial 'null' value"));
80921 		duk_push_null(thr);
80922 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
80923 #else
80924 		DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property not used"));
80925 #endif
80926 	}
80927 
80928 	/*
80929 	 *  "name" used to be non-standard but is now defined by ES2015.
80930 	 *  In ES2015/ES2016 the .name property is configurable.
80931 	 */
80932 
80933 	/* [ ... closure template ] */
80934 
80935 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
80936 	/* XXX: Look for own property only; doesn't matter much because
80937 	 * templates are bare objects.
80938 	 */
80939 	if (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME)) {
80940 		/* [ ... closure template name ] */
80941 		DUK_ASSERT(duk_is_string(thr, -1));
80942 		DUK_DD(DUK_DDPRINT("setting function instance name to %!T", duk_get_tval(thr, -1)));
80943 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);  /* -> [ ... closure template ] */
80944 	} else {
80945 		/* Anonymous functions don't have a .name in ES2015, so don't set
80946 		 * it on the instance either.  The instance will then inherit
80947 		 * it from Function.prototype.name.
80948 		 */
80949 		DUK_DD(DUK_DDPRINT("not setting function instance .name"));
80950 		duk_pop_unsafe(thr);
80951 	}
80952 #endif
80953 
80954 	/*
80955 	 *  Compact the closure, in most cases no properties will be added later.
80956 	 *  Also, without this the closures end up having unused property slots
80957 	 *  (e.g. in Duktape 0.9.0, 8 slots would be allocated and only 7 used).
80958 	 *  A better future solution would be to allocate the closure directly
80959 	 *  to correct size (and setup the properties directly without going
80960 	 *  through the API).
80961 	 */
80962 
80963 	duk_compact(thr, -2);
80964 
80965 	/*
80966 	 *  Some assertions (E5 Section 13.2).
80967 	 */
80968 
80969 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(&fun_clos->obj) == DUK_HOBJECT_CLASS_FUNCTION);
80970 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, &fun_clos->obj) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
80971 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
80972 	DUK_ASSERT(duk_has_prop_stridx(thr, -2, DUK_STRIDX_LENGTH) != 0);
80973 	DUK_ASSERT(add_auto_proto == 0 || duk_has_prop_stridx(thr, -2, DUK_STRIDX_PROTOTYPE) != 0);
80974 	/* May be missing .name */
80975 	DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
80976 	           duk_has_prop_stridx(thr, -2, DUK_STRIDX_CALLER) != 0);
80977 	DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
80978 	           duk_has_prop_stridx(thr, -2, DUK_STRIDX_LC_ARGUMENTS) != 0);
80979 
80980 	/*
80981 	 *  Finish
80982 	 */
80983 
80984 	/* [ ... closure template ] */
80985 
80986 	DUK_DDD(DUK_DDDPRINT("created function instance: template=%!iT -> closure=%!iT",
80987 	                     (duk_tval *) duk_get_tval(thr, -1),
80988 	                     (duk_tval *) duk_get_tval(thr, -2)));
80989 
80990 	duk_pop_unsafe(thr);
80991 
80992 	/* [ ... closure ] */
80993 }
80994 
80995 /*
80996  *  Delayed activation environment record initialization (for functions
80997  *  with NEWENV).
80998  *
80999  *  The non-delayed initialization is handled by duk_handle_call().
81000  */
81001 
81002 DUK_LOCAL void duk__preallocate_env_entries(duk_hthread *thr, duk_hobject *varmap, duk_hobject *env) {
81003 	duk_uint_fast32_t i;
81004 
81005 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {
81006 		duk_hstring *key;
81007 
81008 		key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
81009 		DUK_ASSERT(key != NULL);   /* assume keys are compact in _Varmap */
81010 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i));  /* assume plain values */
81011 
81012 		/* Predefine as 'undefined' to reserve a property slot.
81013 		 * This makes the unwind process (where register values
81014 		 * are copied to the env object) safe against throwing.
81015 		 *
81016 		 * XXX: This could be made much faster by creating the
81017 		 * property table directly.
81018 		 */
81019 		duk_push_undefined(thr);
81020 		DUK_DDD(DUK_DDDPRINT("preallocate env entry for key %!O", key));
81021 		duk_hobject_define_property_internal(thr, env, key, DUK_PROPDESC_FLAGS_WE);
81022 	}
81023 }
81024 
81025 /* shared helper */
81026 DUK_INTERNAL
81027 duk_hobject *duk_create_activation_environment_record(duk_hthread *thr,
81028                                                       duk_hobject *func,
81029                                                       duk_size_t bottom_byteoff) {
81030 	duk_hdecenv *env;
81031 	duk_hobject *parent;
81032 	duk_hcompfunc *f;
81033 
81034 	DUK_ASSERT(thr != NULL);
81035 	DUK_ASSERT(func != NULL);
81036 
81037 	DUK_STATS_INC(thr->heap, stats_envrec_create);
81038 
81039 	f = (duk_hcompfunc *) func;
81040 	parent = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
81041 	if (!parent) {
81042 		parent = thr->builtins[DUK_BIDX_GLOBAL_ENV];
81043 	}
81044 
81045 	env = duk_hdecenv_alloc(thr,
81046 	                        DUK_HOBJECT_FLAG_EXTENSIBLE |
81047 	                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
81048 	DUK_ASSERT(env != NULL);
81049 	duk_push_hobject(thr, (duk_hobject *) env);
81050 
81051 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
81052 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) env, parent);
81053 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, parent);  /* parent env is the prototype */
81054 
81055 	/* open scope information, for compiled functions only */
81056 
81057 	DUK_ASSERT(env->thread == NULL);
81058 	DUK_ASSERT(env->varmap == NULL);
81059 	DUK_ASSERT(env->regbase_byteoff == 0);
81060 	if (DUK_HOBJECT_IS_COMPFUNC(func)) {
81061 		duk_hobject *varmap;
81062 
81063 		varmap = duk_hobject_get_varmap(thr, func);
81064 		if (varmap != NULL) {
81065 			env->varmap = varmap;
81066 			DUK_HOBJECT_INCREF(thr, varmap);
81067 			env->thread = thr;
81068 			DUK_HTHREAD_INCREF(thr, thr);
81069 			env->regbase_byteoff = bottom_byteoff;
81070 
81071 			/* Preallocate env property table to avoid potential
81072 			 * for out-of-memory on unwind when the env is closed.
81073 			 */
81074 			duk__preallocate_env_entries(thr, varmap, (duk_hobject *) env);
81075 		} else {
81076 			/* If function has no _Varmap, leave the environment closed. */
81077 			DUK_ASSERT(env->thread == NULL);
81078 			DUK_ASSERT(env->varmap == NULL);
81079 			DUK_ASSERT(env->regbase_byteoff == 0);
81080 		}
81081 	}
81082 
81083 	return (duk_hobject *) env;
81084 }
81085 
81086 DUK_INTERNAL
81087 void duk_js_init_activation_environment_records_delayed(duk_hthread *thr,
81088                                                         duk_activation *act) {
81089 	duk_hobject *func;
81090 	duk_hobject *env;
81091 
81092 	DUK_ASSERT(thr != NULL);
81093 	func = DUK_ACT_GET_FUNC(act);
81094 	DUK_ASSERT(func != NULL);
81095 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound functions are never in act 'func' */
81096 
81097 	/*
81098 	 *  Delayed initialization only occurs for 'NEWENV' functions.
81099 	 */
81100 
81101 	DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
81102 	DUK_ASSERT(act->lex_env == NULL);
81103 	DUK_ASSERT(act->var_env == NULL);
81104 
81105 	DUK_STATS_INC(thr->heap, stats_envrec_delayedcreate);
81106 
81107 	env = duk_create_activation_environment_record(thr, func, act->bottom_byteoff);
81108 	DUK_ASSERT(env != NULL);
81109 	/* 'act' is a stable pointer, so still OK. */
81110 
81111 	DUK_DDD(DUK_DDDPRINT("created delayed fresh env: %!ipO", (duk_heaphdr *) env));
81112 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
81113 	{
81114 		duk_hobject *p = env;
81115 		while (p) {
81116 			DUK_DDD(DUK_DDDPRINT("  -> %!ipO", (duk_heaphdr *) p));
81117 			p = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, p);
81118 		}
81119 	}
81120 #endif
81121 
81122 	act->lex_env = env;
81123 	act->var_env = env;
81124 	DUK_HOBJECT_INCREF(thr, env);  /* XXX: incref by count (here 2 times) */
81125 	DUK_HOBJECT_INCREF(thr, env);
81126 
81127 	duk_pop_unsafe(thr);
81128 }
81129 
81130 /*
81131  *  Closing environment records.
81132  *
81133  *  The environment record MUST be closed with the thread where its activation
81134  *  is; i.e. if 'env' is open, 'thr' must match env->thread, and the regbase
81135  *  and varmap must still be valid.  On entry, 'env' must be reachable.
81136  */
81137 
81138 DUK_INTERNAL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env) {
81139 	duk_uint_fast32_t i;
81140 	duk_hobject *varmap;
81141 	duk_hstring *key;
81142 	duk_tval *tv;
81143 	duk_uint_t regnum;
81144 
81145 	DUK_ASSERT(thr != NULL);
81146 	DUK_ASSERT(env != NULL);
81147 
81148 	if (DUK_UNLIKELY(!DUK_HOBJECT_IS_DECENV(env))) {
81149 		DUK_DDD(DUK_DDDPRINT("env not a declarative record: %!iO", (duk_heaphdr *) env));
81150 		return;
81151 	}
81152 
81153 	varmap = ((duk_hdecenv *) env)->varmap;
81154 	if (varmap == NULL) {
81155 		DUK_DDD(DUK_DDDPRINT("env already closed: %!iO", (duk_heaphdr *) env));
81156 
81157 		return;
81158 	}
81159 	DUK_ASSERT(((duk_hdecenv *) env)->thread != NULL);
81160 	DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) env);
81161 
81162 	DUK_DDD(DUK_DDDPRINT("closing env: %!iO", (duk_heaphdr *) env));
81163 	DUK_DDD(DUK_DDDPRINT("varmap: %!O", (duk_heaphdr *) varmap));
81164 
81165 	/* Env must be closed in the same thread as where it runs. */
81166 	DUK_ASSERT(((duk_hdecenv *) env)->thread == thr);
81167 
81168 	/* XXX: additional conditions when to close variables? we don't want to do it
81169 	 * unless the environment may have "escaped" (referenced in a function closure).
81170 	 * With delayed environments, the existence is probably good enough of a check.
81171 	 */
81172 
81173 	/* Note: we rely on the _Varmap having a bunch of nice properties, like:
81174 	 *  - being compacted and unmodified during this process
81175 	 *  - not containing an array part
81176 	 *  - having correct value types
81177 	 */
81178 
81179 	DUK_DDD(DUK_DDDPRINT("copying bound register values, %ld bound regs", (long) DUK_HOBJECT_GET_ENEXT(varmap)));
81180 
81181 	/* Copy over current variable values from value stack to the
81182 	 * environment record.  The scope object is empty but may
81183 	 * inherit from another scope which has conflicting names.
81184 	 */
81185 
81186 	/* XXX: Do this using a once allocated entry area, no side effects.
81187 	 * Hash part would need special treatment however (maybe copy, and
81188 	 * then realloc with hash part if large enough).
81189 	 */
81190 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {
81191 		duk_size_t regbase_byteoff;
81192 
81193 		key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
81194 		DUK_ASSERT(key != NULL);   /* assume keys are compact in _Varmap */
81195 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i));  /* assume plain values */
81196 
81197 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, varmap, i);
81198 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
81199 		DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (duk_double_t) DUK_UINT32_MAX);  /* limits */
81200 #if defined(DUK_USE_FASTINT)
81201 		DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
81202 		regnum = (duk_uint_t) DUK_TVAL_GET_FASTINT_U32(tv);
81203 #else
81204 		regnum = (duk_uint_t) DUK_TVAL_GET_NUMBER(tv);
81205 #endif
81206 
81207 		regbase_byteoff = ((duk_hdecenv *) env)->regbase_byteoff;
81208 		DUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum >= (duk_uint8_t *) thr->valstack);
81209 		DUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum < (duk_uint8_t *) thr->valstack_top);
81210 
81211 		/* Write register value into env as named properties.
81212 		 * If property already exists, overwrites silently.
81213 		 * Property is writable, but not deletable (not configurable
81214 		 * in terms of property attributes).
81215 		 *
81216 		 * This property write must not throw because we're unwinding
81217 		 * and unwind code is not allowed to throw at present.  The
81218 		 * call itself has no such guarantees, but we've preallocated
81219 		 * entries for each property when the env was created, so no
81220 		 * out-of-memory error should be possible.  If this guarantee
81221 		 * is not provided, problems like GH-476 may happen.
81222 		 */
81223 		duk_push_tval(thr, (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum));
81224 		DUK_DDD(DUK_DDDPRINT("closing identifier %!O -> reg %ld, value %!T",
81225 		                     (duk_heaphdr *) key,
81226 		                     (long) regnum,
81227 		                     (duk_tval *) duk_get_tval(thr, -1)));
81228 		duk_hobject_define_property_internal(thr, env, key, DUK_PROPDESC_FLAGS_WE);
81229 	}
81230 
81231 	/* NULL atomically to avoid inconsistent state + side effects. */
81232 	DUK_HOBJECT_DECREF_NORZ(thr, ((duk_hdecenv *) env)->thread);
81233 	DUK_HOBJECT_DECREF_NORZ(thr, ((duk_hdecenv *) env)->varmap);
81234 	((duk_hdecenv *) env)->thread = NULL;
81235 	((duk_hdecenv *) env)->varmap = NULL;
81236 
81237 	DUK_DDD(DUK_DDDPRINT("env after closing: %!O", (duk_heaphdr *) env));
81238 }
81239 
81240 /*
81241  *  GETIDREF: a GetIdentifierReference-like helper.
81242  *
81243  *  Provides a parent traversing lookup and a single level lookup
81244  *  (for HasBinding).
81245  *
81246  *  Instead of returning the value, returns a bunch of values allowing
81247  *  the caller to read, write, or delete the binding.  Value pointers
81248  *  are duk_tval pointers which can be mutated directly as long as
81249  *  refcounts are properly updated.  Note that any operation which may
81250  *  reallocate valstacks or compact objects may invalidate the returned
81251  *  duk_tval (but not object) pointers, so caller must be very careful.
81252  *
81253  *  If starting environment record 'env' is given, 'act' is ignored.
81254  *  However, if 'env' is NULL, the caller may identify, in 'act', an
81255  *  activation which hasn't had its declarative environment initialized
81256  *  yet.  The activation registers are then looked up, and its parent
81257  *  traversed normally.
81258  *
81259  *  The 'out' structure values are only valid if the function returns
81260  *  success (non-zero).
81261  */
81262 
81263 /* lookup name from an open declarative record's registers */
81264 DUK_LOCAL
81265 duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
81266                                          duk_hstring *name,
81267                                          duk_hdecenv *env,
81268                                          duk__id_lookup_result *out) {
81269 	duk_tval *tv;
81270 	duk_size_t reg_rel;
81271 
81272 	DUK_ASSERT(thr != NULL);
81273 	DUK_ASSERT(name != NULL);
81274 	DUK_ASSERT(env != NULL);
81275 	DUK_ASSERT(out != NULL);
81276 
81277 	DUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) env));
81278 	DUK_HDECENV_ASSERT_VALID(env);
81279 
81280 	if (env->thread == NULL) {
81281 		/* already closed */
81282 		return 0;
81283 	}
81284 	DUK_ASSERT(env->varmap != NULL);
81285 
81286 	tv = duk_hobject_find_entry_tval_ptr(thr->heap, env->varmap, name);
81287 	if (DUK_UNLIKELY(tv == NULL)) {
81288 		return 0;
81289 	}
81290 
81291 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
81292 	DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (duk_double_t) DUK_UINT32_MAX);  /* limits */
81293 #if defined(DUK_USE_FASTINT)
81294 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
81295 	reg_rel = (duk_size_t) DUK_TVAL_GET_FASTINT_U32(tv);
81296 #else
81297 	reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
81298 #endif
81299 	DUK_ASSERT_DISABLE(reg_rel >= 0);  /* unsigned */
81300 
81301 	tv = (duk_tval *) (void *) ((duk_uint8_t *) env->thread->valstack + env->regbase_byteoff + sizeof(duk_tval) * reg_rel);
81302 	DUK_ASSERT(tv >= env->thread->valstack && tv < env->thread->valstack_end);  /* XXX: more accurate? */
81303 
81304 	out->value = tv;
81305 	out->attrs = DUK_PROPDESC_FLAGS_W;  /* registers are mutable, non-deletable */
81306 	out->env = (duk_hobject *) env;
81307 	out->holder = NULL;
81308 	out->has_this = 0;
81309 	return 1;
81310 }
81311 
81312 /* lookup name from current activation record's functions' registers */
81313 DUK_LOCAL
81314 duk_bool_t duk__getid_activation_regs(duk_hthread *thr,
81315                                       duk_hstring *name,
81316                                       duk_activation *act,
81317                                       duk__id_lookup_result *out) {
81318 	duk_tval *tv;
81319 	duk_hobject *func;
81320 	duk_hobject *varmap;
81321 	duk_size_t reg_rel;
81322 
81323 	DUK_ASSERT(thr != NULL);
81324 	DUK_ASSERT(name != NULL);
81325 	DUK_ASSERT(act != NULL);
81326 	DUK_ASSERT(out != NULL);
81327 
81328 	func = DUK_ACT_GET_FUNC(act);
81329 	DUK_ASSERT(func != NULL);
81330 	DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
81331 
81332 	if (!DUK_HOBJECT_IS_COMPFUNC(func)) {
81333 		return 0;
81334 	}
81335 
81336 	/* XXX: move varmap to duk_hcompfunc struct field? */
81337 	varmap = duk_hobject_get_varmap(thr, func);
81338 	if (!varmap) {
81339 		return 0;
81340 	}
81341 
81342 	tv = duk_hobject_find_entry_tval_ptr(thr->heap, varmap, name);
81343 	if (!tv) {
81344 		return 0;
81345 	}
81346 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
81347 	reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
81348 	DUK_ASSERT_DISABLE(reg_rel >= 0);
81349 	DUK_ASSERT(reg_rel < ((duk_hcompfunc *) func)->nregs);
81350 
81351 	tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
81352 	tv += reg_rel;
81353 
81354 	out->value = tv;
81355 	out->attrs = DUK_PROPDESC_FLAGS_W;  /* registers are mutable, non-deletable */
81356 	out->env = NULL;
81357 	out->holder = NULL;
81358 	out->has_this = 0;
81359 	return 1;
81360 }
81361 
81362 DUK_LOCAL
81363 duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
81364                                          duk_hobject *env,
81365                                          duk_hstring *name,
81366                                          duk_activation *act,
81367                                          duk_bool_t parents,
81368                                          duk__id_lookup_result *out) {
81369 	duk_tval *tv;
81370 	duk_uint_t sanity;
81371 
81372 	DUK_ASSERT(thr != NULL);
81373 	DUK_ASSERT(env != NULL || act != NULL);
81374 	DUK_ASSERT(name != NULL);
81375 	DUK_ASSERT(out != NULL);
81376 
81377 	DUK_ASSERT(!env || DUK_HOBJECT_IS_ENV(env));
81378 	DUK_ASSERT(!env || !DUK_HOBJECT_HAS_ARRAY_PART(env));
81379 
81380 	/*
81381 	 *  Conceptually, we look for the identifier binding by starting from
81382 	 *  'env' and following to chain of environment records (represented
81383 	 *  by the prototype chain).
81384 	 *
81385 	 *  If 'env' is NULL, the current activation does not yet have an
81386 	 *  allocated declarative environment record; this should be treated
81387 	 *  exactly as if the environment record existed but had no bindings
81388 	 *  other than register bindings.
81389 	 *
81390 	 *  Note: we assume that with the DUK_HOBJECT_FLAG_NEWENV cleared
81391 	 *  the environment will always be initialized immediately; hence
81392 	 *  a NULL 'env' should only happen with the flag set.  This is the
81393 	 *  case for: (1) function calls, and (2) strict, direct eval calls.
81394 	 */
81395 
81396 	if (env == NULL && act != NULL) {
81397 		duk_hobject *func;
81398 		duk_hcompfunc *f;
81399 
81400 		DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference: env is NULL, activation is non-NULL -> "
81401 		                     "delayed env case, look up activation regs first"));
81402 
81403 		/*
81404 		 *  Try registers
81405 		 */
81406 
81407 		if (duk__getid_activation_regs(thr, name, act, out)) {
81408 			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
81409 			                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
81410 			                     "(found from register bindings when env=NULL)",
81411 			                     (duk_heaphdr *) name, (duk_tval *) out->value,
81412 			                     (long) out->attrs, (long) out->has_this,
81413 			                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
81414 			return 1;
81415 		}
81416 
81417 		DUK_DDD(DUK_DDDPRINT("not found in current activation regs"));
81418 
81419 		/*
81420 		 *  Not found in registers, proceed to the parent record.
81421 		 *  Here we need to determine what the parent would be,
81422 		 *  if 'env' was not NULL (i.e. same logic as when initializing
81423 		 *  the record).
81424 		 *
81425 		 *  Note that environment initialization is only deferred when
81426 		 *  DUK_HOBJECT_HAS_NEWENV is set, and this only happens for:
81427 		 *    - Function code
81428 		 *    - Strict eval code
81429 		 *
81430 		 *  We only need to check _Lexenv here; _Varenv exists only if it
81431 		 *  differs from _Lexenv (and thus _Lexenv will also be present).
81432 		 */
81433 
81434 		if (!parents) {
81435 			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
81436 			                     "(not found from register bindings when env=NULL)"));
81437 			goto fail_not_found;
81438 		}
81439 
81440 		func = DUK_ACT_GET_FUNC(act);
81441 		DUK_ASSERT(func != NULL);
81442 		DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
81443 		f = (duk_hcompfunc *) func;
81444 
81445 		env = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
81446 		if (!env) {
81447 			env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
81448 		}
81449 
81450 		DUK_DDD(DUK_DDDPRINT("continue lookup from env: %!iO",
81451 		                     (duk_heaphdr *) env));
81452 	}
81453 
81454 	/*
81455 	 *  Prototype walking starting from 'env'.
81456 	 *
81457 	 *  ('act' is not needed anywhere here.)
81458 	 */
81459 
81460 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
81461 	while (env != NULL) {
81462 		duk_small_uint_t cl;
81463 		duk_uint_t attrs;
81464 
81465 		DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference, name=%!O, considering env=%p -> %!iO",
81466 		                     (duk_heaphdr *) name,
81467 		                     (void *) env,
81468 		                     (duk_heaphdr *) env));
81469 
81470 		DUK_ASSERT(env != NULL);
81471 		DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
81472 		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(env));
81473 
81474 		cl = DUK_HOBJECT_GET_CLASS_NUMBER(env);
81475 		DUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV || cl == DUK_HOBJECT_CLASS_DECENV);
81476 		if (cl == DUK_HOBJECT_CLASS_DECENV) {
81477 			/*
81478 			 *  Declarative environment record.
81479 			 *
81480 			 *  Identifiers can never be stored in ancestors and are
81481 			 *  always plain values, so we can use an internal helper
81482 			 *  and access the value directly with an duk_tval ptr.
81483 			 *
81484 			 *  A closed environment is only indicated by it missing
81485 			 *  the "book-keeping" properties required for accessing
81486 			 *  register-bound variables.
81487 			 */
81488 
81489 			DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) env);
81490 			if (duk__getid_open_decl_env_regs(thr, name, (duk_hdecenv *) env, out)) {
81491 				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
81492 				                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
81493 				                     "(declarative environment record, scope open, found in regs)",
81494 				                     (duk_heaphdr *) name, (duk_tval *) out->value,
81495 				                     (long) out->attrs, (long) out->has_this,
81496 				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
81497 				return 1;
81498 			}
81499 
81500 			tv = duk_hobject_find_entry_tval_ptr_and_attrs(thr->heap, env, name, &attrs);
81501 			if (tv) {
81502 				out->value = tv;
81503 				out->attrs = attrs;
81504 				out->env = env;
81505 				out->holder = env;
81506 				out->has_this = 0;
81507 
81508 				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
81509 				                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
81510 				                     "(declarative environment record, found in properties)",
81511 				                     (duk_heaphdr *) name, (duk_tval *) out->value,
81512 				                     (long) out->attrs, (long) out->has_this,
81513 				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
81514 				return 1;
81515 			}
81516 		} else {
81517 			/*
81518 			 *  Object environment record.
81519 			 *
81520 			 *  Binding (target) object is an external, uncontrolled object.
81521 			 *  Identifier may be bound in an ancestor property, and may be
81522 			 *  an accessor.  Target can also be a Proxy which we must support
81523 			 *  here.
81524 			 */
81525 
81526 			/* XXX: we could save space by using _Target OR _This.  If _Target, assume
81527 			 * this binding is undefined.  If _This, assumes this binding is _This, and
81528 			 * target is also _This.  One property would then be enough.
81529 			 */
81530 
81531 			duk_hobject *target;
81532 			duk_bool_t found;
81533 
81534 			DUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV);
81535 			DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) env);
81536 
81537 			target = ((duk_hobjenv *) env)->target;
81538 			DUK_ASSERT(target != NULL);
81539 
81540 			/* Target may be a Proxy or property may be an accessor, so we must
81541 			 * use an actual, Proxy-aware hasprop check here.
81542 			 *
81543 			 * out->holder is NOT set to the actual duk_hobject where the
81544 			 * property is found, but rather the object binding target object.
81545 			 */
81546 
81547 #if defined(DUK_USE_ES6_PROXY)
81548 			if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(target))) {
81549 				duk_tval tv_name;
81550 				duk_tval tv_target_tmp;
81551 
81552 				DUK_ASSERT(name != NULL);
81553 				DUK_TVAL_SET_STRING(&tv_name, name);
81554 				DUK_TVAL_SET_OBJECT(&tv_target_tmp, target);
81555 
81556 				found = duk_hobject_hasprop(thr, &tv_target_tmp, &tv_name);
81557 			} else
81558 #endif  /* DUK_USE_ES6_PROXY */
81559 			{
81560 				/* XXX: duk_hobject_hasprop() would be correct for
81561 				 * non-Proxy objects too, but it is about ~20-25%
81562 				 * slower at present so separate code paths for
81563 				 * Proxy and non-Proxy now.
81564 				 */
81565 				found = duk_hobject_hasprop_raw(thr, target, name);
81566 			}
81567 
81568 			if (found) {
81569 				out->value = NULL;  /* can't get value, may be accessor */
81570 				out->attrs = 0;     /* irrelevant when out->value == NULL */
81571 				out->env = env;
81572 				out->holder = target;
81573 				out->has_this = ((duk_hobjenv *) env)->has_this;
81574 
81575 				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
81576 				                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
81577 				                     "(object environment record)",
81578 				                     (duk_heaphdr *) name, (duk_tval *) out->value,
81579 				                     (long) out->attrs, (long) out->has_this,
81580 				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
81581 				return 1;
81582 			}
81583 		}
81584 
81585 		if (!parents) {
81586 			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
81587 			                     "(not found from first traversed env)"));
81588 			goto fail_not_found;
81589 		}
81590 
81591                 if (DUK_UNLIKELY(sanity-- == 0)) {
81592                         DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
81593 			DUK_WO_NORETURN(return 0;);
81594                 }
81595 		env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);
81596 	}
81597 
81598 	/*
81599 	 *  Not found (even in global object)
81600 	 */
81601 
81602  fail_not_found:
81603 	return 0;
81604 }
81605 
81606 /*
81607  *  HASVAR: check identifier binding from a given environment record
81608  *  without traversing its parents.
81609  *
81610  *  This primitive is not exposed to user code as such, but is used
81611  *  internally for e.g. declaration binding instantiation.
81612  *
81613  *  See E5 Sections:
81614  *    10.2.1.1.1 HasBinding(N)
81615  *    10.2.1.2.1 HasBinding(N)
81616  *
81617  *  Note: strictness has no bearing on this check.  Hence we don't take
81618  *  a 'strict' parameter.
81619  */
81620 
81621 #if 0  /*unused*/
81622 DUK_INTERNAL
81623 duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr,
81624                                 duk_hobject *env,
81625                                 duk_hstring *name) {
81626 	duk__id_lookup_result ref;
81627 	duk_bool_t parents;
81628 
81629 	DUK_DDD(DUK_DDDPRINT("hasvar: thr=%p, env=%p, name=%!O "
81630 	                     "(env -> %!dO)",
81631 	                     (void *) thr, (void *) env, (duk_heaphdr *) name,
81632 	                     (duk_heaphdr *) env));
81633 
81634 	DUK_ASSERT(thr != NULL);
81635 	DUK_ASSERT(env != NULL);
81636 	DUK_ASSERT(name != NULL);
81637 
81638         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
81639         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
81640 
81641 	DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
81642 	DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(env));
81643 
81644 	/* lookup results is ignored */
81645 	parents = 0;
81646 	return duk__get_identifier_reference(thr, env, name, NULL, parents, &ref);
81647 }
81648 #endif
81649 
81650 /*
81651  *  GETVAR
81652  *
81653  *  See E5 Sections:
81654  *    11.1.2 Identifier Reference
81655  *    10.3.1 Identifier Resolution
81656  *    11.13.1 Simple Assignment  [example of where the Reference is GetValue'd]
81657  *    8.7.1 GetValue (V)
81658  *    8.12.1 [[GetOwnProperty]] (P)
81659  *    8.12.2 [[GetProperty]] (P)
81660  *    8.12.3 [[Get]] (P)
81661  *
81662  *  If 'throw' is true, always leaves two values on top of stack: [val this].
81663  *
81664  *  If 'throw' is false, returns 0 if identifier cannot be resolved, and the
81665  *  stack will be unaffected in this case.  If identifier is resolved, returns
81666  *  1 and leaves [val this] on top of stack.
81667  *
81668  *  Note: the 'strict' flag of a reference returned by GetIdentifierReference
81669  *  is ignored by GetValue.  Hence we don't take a 'strict' parameter.
81670  *
81671  *  The 'throw' flag is needed for implementing 'typeof' for an unreferenced
81672  *  identifier.  An unreference identifier in other contexts generates a
81673  *  ReferenceError.
81674  */
81675 
81676 DUK_LOCAL
81677 duk_bool_t duk__getvar_helper(duk_hthread *thr,
81678                               duk_hobject *env,
81679                               duk_activation *act,
81680                               duk_hstring *name,
81681                               duk_bool_t throw_flag) {
81682 	duk__id_lookup_result ref;
81683 	duk_tval tv_tmp_obj;
81684 	duk_tval tv_tmp_key;
81685 	duk_bool_t parents;
81686 
81687 	DUK_DDD(DUK_DDDPRINT("getvar: thr=%p, env=%p, act=%p, name=%!O "
81688 	                     "(env -> %!dO)",
81689 	                     (void *) thr, (void *) env, (void *) act,
81690 	                     (duk_heaphdr *) name, (duk_heaphdr *) env));
81691 
81692 	DUK_ASSERT(thr != NULL);
81693 	DUK_ASSERT(name != NULL);
81694 	/* env and act may be NULL */
81695 
81696 	DUK_STATS_INC(thr->heap, stats_getvar_all);
81697 
81698         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
81699         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
81700 
81701 	parents = 1;     /* follow parent chain */
81702 	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
81703 		if (ref.value) {
81704 			duk_push_tval(thr, ref.value);
81705 			duk_push_undefined(thr);
81706 		} else {
81707 			DUK_ASSERT(ref.holder != NULL);
81708 
81709 			/* ref.holder is safe across the getprop call (even
81710 			 * with side effects) because 'env' is reachable and
81711 			 * ref.holder is a direct heap pointer.
81712 			 */
81713 
81714 			DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
81715 			DUK_TVAL_SET_STRING(&tv_tmp_key, name);
81716 			(void) duk_hobject_getprop(thr, &tv_tmp_obj, &tv_tmp_key);  /* [value] */
81717 
81718 			if (ref.has_this) {
81719 				duk_push_hobject(thr, ref.holder);
81720 			} else {
81721 				duk_push_undefined(thr);
81722 			}
81723 
81724 			/* [value this] */
81725 		}
81726 
81727 		return 1;
81728 	} else {
81729 		if (throw_flag) {
81730 			DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,
81731 			               "identifier '%s' undefined",
81732 			               (const char *) DUK_HSTRING_GET_DATA(name));
81733 			DUK_WO_NORETURN(return 0;);
81734 		}
81735 
81736 		return 0;
81737 	}
81738 }
81739 
81740 DUK_INTERNAL
81741 duk_bool_t duk_js_getvar_envrec(duk_hthread *thr,
81742                                 duk_hobject *env,
81743                                 duk_hstring *name,
81744                                 duk_bool_t throw_flag) {
81745 	return duk__getvar_helper(thr, env, NULL, name, throw_flag);
81746 }
81747 
81748 DUK_INTERNAL
81749 duk_bool_t duk_js_getvar_activation(duk_hthread *thr,
81750                                     duk_activation *act,
81751                                     duk_hstring *name,
81752                                     duk_bool_t throw_flag) {
81753 	DUK_ASSERT(act != NULL);
81754 	return duk__getvar_helper(thr, act->lex_env, act, name, throw_flag);
81755 }
81756 
81757 /*
81758  *  PUTVAR
81759  *
81760  *  See E5 Sections:
81761  *    11.1.2 Identifier Reference
81762  *    10.3.1 Identifier Resolution
81763  *    11.13.1 Simple Assignment  [example of where the Reference is PutValue'd]
81764  *    8.7.2 PutValue (V,W)  [see especially step 3.b, undefined -> automatic global in non-strict mode]
81765  *    8.12.4 [[CanPut]] (P)
81766  *    8.12.5 [[Put]] (P)
81767  *
81768  *  Note: may invalidate any valstack (or object) duk_tval pointers because
81769  *  putting a value may reallocate any object or any valstack.  Caller beware.
81770  */
81771 
81772 DUK_LOCAL
81773 void duk__putvar_helper(duk_hthread *thr,
81774                         duk_hobject *env,
81775                         duk_activation *act,
81776                         duk_hstring *name,
81777                         duk_tval *val,
81778                         duk_bool_t strict) {
81779 	duk__id_lookup_result ref;
81780 	duk_tval tv_tmp_obj;
81781 	duk_tval tv_tmp_key;
81782 	duk_bool_t parents;
81783 
81784 	DUK_STATS_INC(thr->heap, stats_putvar_all);
81785 
81786 	DUK_DDD(DUK_DDDPRINT("putvar: thr=%p, env=%p, act=%p, name=%!O, val=%p, strict=%ld "
81787 	                     "(env -> %!dO, val -> %!T)",
81788 	                     (void *) thr, (void *) env, (void *) act,
81789 	                     (duk_heaphdr *) name, (void *) val, (long) strict,
81790 	                     (duk_heaphdr *) env, (duk_tval *) val));
81791 
81792 	DUK_ASSERT(thr != NULL);
81793 	DUK_ASSERT(name != NULL);
81794 	DUK_ASSERT(val != NULL);
81795 	/* env and act may be NULL */
81796 
81797         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
81798         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
81799 	DUK_ASSERT_REFCOUNT_NONZERO_TVAL(val);
81800 
81801 	/*
81802 	 *  In strict mode E5 protects 'eval' and 'arguments' from being
81803 	 *  assigned to (or even declared anywhere).  Attempt to do so
81804 	 *  should result in a compile time SyntaxError.  See the internal
81805 	 *  design documentation for details.
81806 	 *
81807 	 *  Thus, we should never come here, run-time, for strict code,
81808 	 *  and name 'eval' or 'arguments'.
81809 	 */
81810 
81811 	DUK_ASSERT(!strict ||
81812 	           (name != DUK_HTHREAD_STRING_EVAL(thr) &&
81813 	            name != DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)));
81814 
81815 	/*
81816 	 *  Lookup variable and update in-place if found.
81817 	 */
81818 
81819 	parents = 1;     /* follow parent chain */
81820 
81821 	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
81822 		if (ref.value && (ref.attrs & DUK_PROPDESC_FLAG_WRITABLE)) {
81823 			/* Update duk_tval in-place if pointer provided and the
81824 			 * property is writable.  If the property is not writable
81825 			 * (immutable binding), use duk_hobject_putprop() which
81826 			 * will respect mutability.
81827 			 */
81828 			duk_tval *tv_val;
81829 
81830 			tv_val = ref.value;
81831 			DUK_ASSERT(tv_val != NULL);
81832 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv_val, val);  /* side effects */
81833 
81834 			/* ref.value invalidated here */
81835 		} else {
81836 			DUK_ASSERT(ref.holder != NULL);
81837 
81838 			DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
81839 			DUK_TVAL_SET_STRING(&tv_tmp_key, name);
81840 			(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, strict);
81841 
81842 			/* ref.value invalidated here */
81843 		}
81844 
81845 		return;
81846 	}
81847 
81848 	/*
81849 	 *  Not found: write to global object (non-strict) or ReferenceError
81850 	 *  (strict); see E5 Section 8.7.2, step 3.
81851 	 */
81852 
81853 	if (strict) {
81854 		DUK_DDD(DUK_DDDPRINT("identifier binding not found, strict => reference error"));
81855 		DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,
81856 		               "identifier '%s' undefined",
81857 		               (const char *) DUK_HSTRING_GET_DATA(name));
81858 		DUK_WO_NORETURN(return;);
81859 	}
81860 
81861 	DUK_DDD(DUK_DDDPRINT("identifier binding not found, not strict => set to global"));
81862 
81863 	DUK_TVAL_SET_OBJECT(&tv_tmp_obj, thr->builtins[DUK_BIDX_GLOBAL]);
81864 	DUK_TVAL_SET_STRING(&tv_tmp_key, name);
81865 	(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, 0);  /* 0 = no throw */
81866 
81867 	/* NB: 'val' may be invalidated here because put_value may realloc valstack,
81868 	 * caller beware.
81869 	 */
81870 }
81871 
81872 DUK_INTERNAL
81873 void duk_js_putvar_envrec(duk_hthread *thr,
81874                           duk_hobject *env,
81875                           duk_hstring *name,
81876                           duk_tval *val,
81877                           duk_bool_t strict) {
81878 	duk__putvar_helper(thr, env, NULL, name, val, strict);
81879 }
81880 
81881 DUK_INTERNAL
81882 void duk_js_putvar_activation(duk_hthread *thr,
81883                               duk_activation *act,
81884                               duk_hstring *name,
81885                               duk_tval *val,
81886                               duk_bool_t strict) {
81887 	DUK_ASSERT(act != NULL);
81888 	duk__putvar_helper(thr, act->lex_env, act, name, val, strict);
81889 }
81890 
81891 /*
81892  *  DELVAR
81893  *
81894  *  See E5 Sections:
81895  *    11.4.1 The delete operator
81896  *    10.2.1.1.5 DeleteBinding (N)  [declarative environment record]
81897  *    10.2.1.2.5 DeleteBinding (N)  [object environment record]
81898  *
81899  *  Variable bindings established inside eval() are deletable (configurable),
81900  *  other bindings are not, including variables declared in global level.
81901  *  Registers are always non-deletable, and the deletion of other bindings
81902  *  is controlled by the configurable flag.
81903  *
81904  *  For strict mode code, the 'delete' operator should fail with a compile
81905  *  time SyntaxError if applied to identifiers.  Hence, no strict mode
81906  *  run-time deletion of identifiers should ever happen.  This function
81907  *  should never be called from strict mode code!
81908  */
81909 
81910 DUK_LOCAL
81911 duk_bool_t duk__delvar_helper(duk_hthread *thr,
81912                               duk_hobject *env,
81913                               duk_activation *act,
81914                               duk_hstring *name) {
81915 	duk__id_lookup_result ref;
81916 	duk_bool_t parents;
81917 
81918 	DUK_DDD(DUK_DDDPRINT("delvar: thr=%p, env=%p, act=%p, name=%!O "
81919 	                     "(env -> %!dO)",
81920 	                     (void *) thr, (void *) env, (void *) act,
81921 	                     (duk_heaphdr *) name, (duk_heaphdr *) env));
81922 
81923 	DUK_ASSERT(thr != NULL);
81924 	DUK_ASSERT(name != NULL);
81925 	/* env and act may be NULL */
81926 
81927         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
81928 
81929 	parents = 1;     /* follow parent chain */
81930 
81931 	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
81932 		if (ref.value && !(ref.attrs & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
81933 			/* Identifier found in registers (always non-deletable)
81934 			 * or declarative environment record and non-configurable.
81935 			 */
81936 			return 0;
81937 		}
81938 		DUK_ASSERT(ref.holder != NULL);
81939 
81940 		return duk_hobject_delprop_raw(thr, ref.holder, name, 0);
81941 	}
81942 
81943 	/*
81944 	 *  Not found (even in global object).
81945 	 *
81946 	 *  In non-strict mode this is a silent SUCCESS (!), see E5 Section 11.4.1,
81947 	 *  step 3.b.  In strict mode this case is a compile time SyntaxError so
81948 	 *  we should not come here.
81949 	 */
81950 
81951 	DUK_DDD(DUK_DDDPRINT("identifier to be deleted not found: name=%!O "
81952 	                     "(treated as silent success)",
81953 	                     (duk_heaphdr *) name));
81954 	return 1;
81955 }
81956 
81957 #if 0  /*unused*/
81958 DUK_INTERNAL
81959 duk_bool_t duk_js_delvar_envrec(duk_hthread *thr,
81960                                 duk_hobject *env,
81961                                 duk_hstring *name) {
81962 	return duk__delvar_helper(thr, env, NULL, name);
81963 }
81964 #endif
81965 
81966 DUK_INTERNAL
81967 duk_bool_t duk_js_delvar_activation(duk_hthread *thr,
81968                                     duk_activation *act,
81969                                     duk_hstring *name) {
81970 	DUK_ASSERT(act != NULL);
81971 	return duk__delvar_helper(thr, act->lex_env, act, name);
81972 }
81973 
81974 /*
81975  *  DECLVAR
81976  *
81977  *  See E5 Sections:
81978  *    10.4.3 Entering Function Code
81979  *    10.5 Declaration Binding Instantion
81980  *    12.2 Variable Statement
81981  *    11.1.2 Identifier Reference
81982  *    10.3.1 Identifier Resolution
81983  *
81984  *  Variable declaration behavior is mainly discussed in Section 10.5,
81985  *  and is not discussed in the execution semantics (Sections 11-13).
81986  *
81987  *  Conceptually declarations happen when code (global, eval, function)
81988  *  is entered, before any user code is executed.  In practice, register-
81989  *  bound identifiers are 'declared' automatically (by virtue of being
81990  *  allocated to registers with the initial value 'undefined').  Other
81991  *  identifiers are declared in the function prologue with this primitive.
81992  *
81993  *  Since non-register bindings eventually back to an internal object's
81994  *  properties, the 'prop_flags' argument is used to specify binding
81995  *  type:
81996  *
81997  *    - Immutable binding: set DUK_PROPDESC_FLAG_WRITABLE to false
81998  *    - Non-deletable binding: set DUK_PROPDESC_FLAG_CONFIGURABLE to false
81999  *    - The flag DUK_PROPDESC_FLAG_ENUMERABLE should be set, although it
82000  *      doesn't really matter for internal objects
82001  *
82002  *  All bindings are non-deletable mutable bindings except:
82003  *
82004  *    - Declarations in eval code (mutable, deletable)
82005  *    - 'arguments' binding in strict function code (immutable)
82006  *    - Function name binding of a function expression (immutable)
82007  *
82008  *  Declarations may go to declarative environment records (always
82009  *  so for functions), but may also go to object environment records
82010  *  (e.g. global code).  The global object environment has special
82011  *  behavior when re-declaring a function (but not a variable); see
82012  *  E5.1 specification, Section 10.5, step 5.e.
82013  *
82014  *  Declarations always go to the 'top-most' environment record, i.e.
82015  *  we never check the record chain.  It's not an error even if a
82016  *  property (even an immutable or non-deletable one) of the same name
82017  *  already exists.
82018  *
82019  *  If a declared variable already exists, its value needs to be updated
82020  *  (if possible).  Returns 1 if a PUTVAR needs to be done by the caller;
82021  *  otherwise returns 0.
82022  */
82023 
82024 DUK_LOCAL
82025 duk_bool_t duk__declvar_helper(duk_hthread *thr,
82026                                duk_hobject *env,
82027                                duk_hstring *name,
82028                                duk_tval *val,
82029                                duk_small_uint_t prop_flags,
82030                                duk_bool_t is_func_decl) {
82031 	duk_hobject *holder;
82032 	duk_bool_t parents;
82033 	duk__id_lookup_result ref;
82034 	duk_tval *tv;
82035 
82036 	DUK_DDD(DUK_DDDPRINT("declvar: thr=%p, env=%p, name=%!O, val=%!T, prop_flags=0x%08lx, is_func_decl=%ld "
82037 	                     "(env -> %!iO)",
82038 	                     (void *) thr, (void *) env, (duk_heaphdr *) name,
82039 	                     (duk_tval *) val, (unsigned long) prop_flags,
82040 	                     (unsigned int) is_func_decl, (duk_heaphdr *) env));
82041 
82042 	DUK_ASSERT(thr != NULL);
82043 	DUK_ASSERT(env != NULL);
82044 	DUK_ASSERT(name != NULL);
82045 	DUK_ASSERT(val != NULL);
82046 
82047 	/* Note: in strict mode the compiler should reject explicit
82048 	 * declaration of 'eval' or 'arguments'.  However, internal
82049 	 * bytecode may declare 'arguments' in the function prologue.
82050 	 * We don't bother checking (or asserting) for these now.
82051 	 */
82052 
82053 	/* Note: val is a stable duk_tval pointer.  The caller makes
82054 	 * a value copy into its stack frame, so 'tv_val' is not subject
82055 	 * to side effects here.
82056 	 */
82057 
82058 	/*
82059 	 *  Check whether already declared.
82060 	 *
82061 	 *  We need to check whether the binding exists in the environment
82062 	 *  without walking its parents.  However, we still need to check
82063 	 *  register-bound identifiers and the prototype chain of an object
82064 	 *  environment target object.
82065 	 */
82066 
82067 	parents = 0;  /* just check 'env' */
82068 	if (duk__get_identifier_reference(thr, env, name, NULL, parents, &ref)) {
82069 		duk_int_t e_idx;
82070 		duk_int_t h_idx;
82071 		duk_small_uint_t flags;
82072 
82073 		/*
82074 		 *  Variable already declared, ignore re-declaration.
82075 		 *  The only exception is the updated behavior of E5.1 for
82076 		 *  global function declarations, E5.1 Section 10.5, step 5.e.
82077 		 *  This behavior does not apply to global variable declarations.
82078 		 */
82079 
82080 		if (!(is_func_decl && env == thr->builtins[DUK_BIDX_GLOBAL_ENV])) {
82081 			DUK_DDD(DUK_DDDPRINT("re-declare a binding, ignoring"));
82082 			return 1;  /* 1 -> needs a PUTVAR */
82083 		}
82084 
82085 		/*
82086 		 *  Special behavior in E5.1.
82087 		 *
82088 		 *  Note that even though parents == 0, the conflicting property
82089 		 *  may be an inherited property (currently our global object's
82090 		 *  prototype is Object.prototype).  Step 5.e first operates on
82091 		 *  the existing property (which is potentially in an ancestor)
82092 		 *  and then defines a new property in the global object (and
82093 		 *  never modifies the ancestor).
82094 		 *
82095 		 *  Also note that this logic would become even more complicated
82096 		 *  if the conflicting property might be a virtual one.  Object
82097 		 *  prototype has no virtual properties, though.
82098 		 *
82099 		 *  XXX: this is now very awkward, rework.
82100 		 */
82101 
82102 		DUK_DDD(DUK_DDDPRINT("re-declare a function binding in global object, "
82103 		                     "updated E5.1 processing"));
82104 
82105 		DUK_ASSERT(ref.holder != NULL);
82106 		holder = ref.holder;
82107 
82108 		/* holder will be set to the target object, not the actual object
82109 		 * where the property was found (see duk__get_identifier_reference()).
82110 		 */
82111 		DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(holder) == DUK_HOBJECT_CLASS_GLOBAL);
82112 		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(holder));  /* global object doesn't have array part */
82113 
82114 		/* XXX: use a helper for prototype traversal; no loop check here */
82115 		/* must be found: was found earlier, and cannot be inherited */
82116 		for (;;) {
82117 			DUK_ASSERT(holder != NULL);
82118 			if (duk_hobject_find_entry(thr->heap, holder, name, &e_idx, &h_idx)) {
82119 				DUK_ASSERT(e_idx >= 0);
82120 				break;
82121 			}
82122 			/* SCANBUILD: NULL pointer dereference, doesn't actually trigger,
82123 			 * asserted above.
82124 			 */
82125 			holder = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, holder);
82126 		}
82127 		DUK_ASSERT(holder != NULL);
82128 		DUK_ASSERT(e_idx >= 0);
82129 		/* SCANBUILD: scan-build produces a NULL pointer dereference warning
82130 		 * below; it never actually triggers because holder is actually never
82131 		 * NULL.
82132 		 */
82133 
82134 		/* ref.holder is global object, holder is the object with the
82135 		 * conflicting property.
82136 		 */
82137 
82138 		flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, holder, e_idx);
82139 		if (!(flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
82140 			if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
82141 				DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
82142 				                     "accessor -> reject"));
82143 				goto fail_existing_attributes;
82144 			}
82145 			if (!((flags & DUK_PROPDESC_FLAG_WRITABLE) &&
82146 			      (flags & DUK_PROPDESC_FLAG_ENUMERABLE))) {
82147 				DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
82148 				                     "plain property which is not writable and "
82149 				                     "enumerable -> reject"));
82150 				goto fail_existing_attributes;
82151 			}
82152 
82153 			DUK_DDD(DUK_DDDPRINT("existing property is not configurable but "
82154 			                     "is plain, enumerable, and writable -> "
82155 			                     "allow redeclaration"));
82156 		}
82157 
82158 		if (holder == ref.holder) {
82159 			/* XXX: if duk_hobject_define_property_internal() was updated
82160 			 * to handle a pre-existing accessor property, this would be
82161 			 * a simple call (like for the ancestor case).
82162 			 */
82163 			DUK_DDD(DUK_DDDPRINT("redefine, offending property in global object itself"));
82164 
82165 			if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
82166 				duk_hobject *tmp;
82167 
82168 				tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, holder, e_idx);
82169 				DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, holder, e_idx, NULL);
82170 				DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
82171 				DUK_UNREF(tmp);
82172 				tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, holder, e_idx);
82173 				DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, holder, e_idx, NULL);
82174 				DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
82175 				DUK_UNREF(tmp);
82176 			} else {
82177 				tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
82178 				DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);
82179 			}
82180 
82181 			/* Here val would be potentially invalid if we didn't make
82182 			 * a value copy at the caller.
82183 			 */
82184 
82185 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
82186 			DUK_TVAL_SET_TVAL(tv, val);
82187 			DUK_TVAL_INCREF(thr, tv);
82188 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, holder, e_idx, prop_flags);
82189 
82190 			DUK_DDD(DUK_DDDPRINT("updated global binding, final result: "
82191 			                     "value -> %!T, prop_flags=0x%08lx",
82192 			                     (duk_tval *) DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx),
82193 			                     (unsigned long) prop_flags));
82194 		} else {
82195 			DUK_DDD(DUK_DDDPRINT("redefine, offending property in ancestor"));
82196 
82197 			DUK_ASSERT(ref.holder == thr->builtins[DUK_BIDX_GLOBAL]);
82198 			duk_push_tval(thr, val);
82199 			duk_hobject_define_property_internal(thr, ref.holder, name, prop_flags);
82200 		}
82201 
82202 		return 0;
82203 	}
82204 
82205 	/*
82206 	 *  Not found (in registers or record objects).  Declare
82207 	 *  to current variable environment.
82208 	 */
82209 
82210 	/*
82211 	 *  Get holder object
82212 	 */
82213 
82214 	if (DUK_HOBJECT_IS_DECENV(env)) {
82215 		DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) env);
82216 		holder = env;
82217 	} else {
82218 		DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) env);
82219 		holder = ((duk_hobjenv *) env)->target;
82220 		DUK_ASSERT(holder != NULL);
82221 	}
82222 
82223 	/*
82224 	 *  Define new property
82225 	 *
82226 	 *  Note: this may fail if the holder is not extensible.
82227 	 */
82228 
82229 	/* XXX: this is awkward as we use an internal method which doesn't handle
82230 	 * extensibility etc correctly.  Basically we'd want to do a [[DefineOwnProperty]]
82231 	 * or Object.defineProperty() here.
82232 	 */
82233 
82234 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(holder)) {
82235 		goto fail_not_extensible;
82236 	}
82237 
82238 	duk_push_hobject(thr, holder);
82239 	duk_push_hstring(thr, name);
82240 	duk_push_tval(thr, val);
82241 	duk_xdef_prop(thr, -3, prop_flags);  /* [holder name val] -> [holder] */
82242 	duk_pop_unsafe(thr);
82243 
82244 	return 0;
82245 
82246  fail_existing_attributes:
82247  fail_not_extensible:
82248 	DUK_ERROR_TYPE(thr, "declaration failed");
82249 	DUK_WO_NORETURN(return 0;);
82250 }
82251 
82252 DUK_INTERNAL
82253 duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
82254                                      duk_activation *act,
82255                                      duk_hstring *name,
82256                                      duk_tval *val,
82257                                      duk_small_uint_t prop_flags,
82258                                      duk_bool_t is_func_decl) {
82259 	duk_hobject *env;
82260 	duk_tval tv_val_copy;
82261 
82262 	DUK_ASSERT(act != NULL);
82263 
82264 	/*
82265 	 *  Make a value copy of the input val.  This ensures that
82266 	 *  side effects cannot invalidate the pointer.
82267 	 */
82268 
82269 	DUK_TVAL_SET_TVAL(&tv_val_copy, val);
82270 	val = &tv_val_copy;
82271 
82272 	/*
82273 	 *  Delayed env creation check
82274 	 */
82275 
82276 	if (!act->var_env) {
82277 		DUK_ASSERT(act->lex_env == NULL);
82278 		duk_js_init_activation_environment_records_delayed(thr, act);
82279 		/* 'act' is a stable pointer, so still OK. */
82280 	}
82281 	DUK_ASSERT(act->lex_env != NULL);
82282 	DUK_ASSERT(act->var_env != NULL);
82283 
82284 	env = act->var_env;
82285 	DUK_ASSERT(env != NULL);
82286 	DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
82287 
82288 	return duk__declvar_helper(thr, env, name, val, prop_flags, is_func_decl);
82289 }
82290 /*
82291  *  Lexer for source files, ToNumber() string conversions, RegExp expressions,
82292  *  and JSON.
82293  *
82294  *  Provides a stream of ECMAScript tokens from an UTF-8/CESU-8 buffer.  The
82295  *  caller can also rewind the token stream into a certain position which is
82296  *  needed by the compiler part for multi-pass scanning.  Tokens are
82297  *  represented as duk_token structures, and contain line number information.
82298  *  Token types are identified with DUK_TOK_* defines.
82299  *
82300  *  Characters are decoded into a fixed size lookup window consisting of
82301  *  decoded Unicode code points, with window positions past the end of the
82302  *  input filled with an invalid codepoint (-1).  The tokenizer can thus
82303  *  perform multiple character lookups efficiently and with few sanity
82304  *  checks (such as access outside the end of the input), which keeps the
82305  *  tokenization code small at the cost of performance.
82306  *
82307  *  Character data in tokens, such as identifier names and string literals,
82308  *  is encoded into CESU-8 format on-the-fly while parsing the token in
82309  *  question.  The string data is made reachable to garbage collection by
82310  *  placing the token-related values in value stack entries allocated for
82311  *  this purpose by the caller.  The characters exist in Unicode code point
82312  *  form only in the fixed size lookup window, which keeps character data
82313  *  expansion (of especially ASCII data) low.
82314  *
82315  *  Token parsing supports the full range of Unicode characters as described
82316  *  in the E5 specification.  Parsing has been optimized for ASCII characters
82317  *  because ordinary ECMAScript code consists almost entirely of ASCII
82318  *  characters.  Matching of complex Unicode codepoint sets (such as in the
82319  *  IdentifierStart and IdentifierPart productions) is optimized for size,
82320  *  and is done using a linear scan of a bit-packed list of ranges.  This is
82321  *  very slow, but should never be entered unless the source code actually
82322  *  contains Unicode characters.
82323  *
82324  *  ECMAScript tokenization is partially context sensitive.  First,
82325  *  additional future reserved words are recognized in strict mode (see E5
82326  *  Section 7.6.1.2).  Second, a forward slash character ('/') can be
82327  *  recognized either as starting a RegExp literal or as a division operator,
82328  *  depending on context.  The caller must provide necessary context flags
82329  *  when requesting a new token.
82330  *
82331  *  Future work:
82332  *
82333  *    * Make line number tracking optional, as it consumes space.
82334  *
82335  *    * Add a feature flag for disabling UTF-8 decoding of input, as most
82336  *      source code is ASCII.  Because of Unicode escapes written in ASCII,
82337  *      this does not allow Unicode support to be removed from e.g.
82338  *      duk_unicode_is_identifier_start() nor does it allow removal of CESU-8
82339  *      encoding of e.g. string literals.
82340  *
82341  *    * Add a feature flag for disabling Unicode compliance of e.g. identifier
82342  *      names.  This allows for a build more than a kilobyte smaller, because
82343  *      Unicode ranges needed by duk_unicode_is_identifier_start() and
82344  *      duk_unicode_is_identifier_part() can be dropped.  String literals
82345  *      should still be allowed to contain escaped Unicode, so this still does
82346  *      not allow removal of CESU-8 encoding of e.g. string literals.
82347  *
82348  *    * Character lookup tables for codepoints above BMP could be stripped.
82349  *
82350  *    * Strictly speaking, E5 specification requires that source code consists
82351  *      of 16-bit code units, and if not, must be conceptually converted to
82352  *      that format first.  The current lexer processes Unicode code points
82353  *      and allows characters outside the BMP.  These should be converted to
82354  *      surrogate pairs while reading the source characters into the window,
82355  *      not after tokens have been formed (as is done now).  However, the fix
82356  *      is not trivial because two characters are decoded from one codepoint.
82357  *
82358  *    * Optimize for speed as well as size.  Large if-else ladders are (at
82359  *      least potentially) slow.
82360  */
82361 
82362 /* #include duk_internal.h -> already included */
82363 
82364 /*
82365  *  Various defines and file specific helper macros
82366  */
82367 
82368 #define DUK__MAX_RE_DECESC_DIGITS     9
82369 #define DUK__MAX_RE_QUANT_DIGITS      9   /* Does not allow e.g. 2**31-1, but one more would allow overflows of u32. */
82370 
82371 /* whether to use macros or helper function depends on call count */
82372 #define DUK__ISDIGIT(x)          ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_9)
82373 #define DUK__ISHEXDIGIT(x)       duk__is_hex_digit((x))
82374 #define DUK__ISOCTDIGIT(x)       ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_7)
82375 #define DUK__ISDIGIT03(x)        ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_3)
82376 #define DUK__ISDIGIT47(x)        ((x) >= DUK_ASC_4 && (x) <= DUK_ASC_7)
82377 
82378 /* lexer character window helpers */
82379 #define DUK__LOOKUP(lex_ctx,idx)            ((lex_ctx)->window[(idx)].codepoint)
82380 #define DUK__ADVANCECHARS(lex_ctx,count)    duk__advance_chars((lex_ctx), (count))
82381 #define DUK__ADVANCEBYTES(lex_ctx,count)    duk__advance_bytes((lex_ctx), (count))
82382 #define DUK__INITBUFFER(lex_ctx)            duk__initbuffer((lex_ctx))
82383 #define DUK__APPENDBUFFER(lex_ctx,x)        duk__appendbuffer((lex_ctx), (duk_codepoint_t) (x))
82384 #define DUK__APPENDBUFFER_ASCII(lex_ctx,x)  duk__appendbuffer_ascii((lex_ctx), (duk_codepoint_t) (x))
82385 
82386 /* lookup shorthands (note: assume context variable is named 'lex_ctx') */
82387 #define DUK__L0()  DUK__LOOKUP(lex_ctx, 0)
82388 #define DUK__L1()  DUK__LOOKUP(lex_ctx, 1)
82389 #define DUK__L2()  DUK__LOOKUP(lex_ctx, 2)
82390 #define DUK__L3()  DUK__LOOKUP(lex_ctx, 3)
82391 #define DUK__L4()  DUK__LOOKUP(lex_ctx, 4)
82392 #define DUK__L5()  DUK__LOOKUP(lex_ctx, 5)
82393 
82394 /* packed advance/token number macro used by multiple functions */
82395 #define DUK__ADVTOK(advbytes,tok)  ((((advbytes) * sizeof(duk_lexer_codepoint)) << 8) + (tok))
82396 
82397 /*
82398  *  Advance lookup window by N characters, filling in new characters as
82399  *  necessary.  After returning caller is guaranteed a character window of
82400  *  at least DUK_LEXER_WINDOW_SIZE characters.
82401  *
82402  *  The main function duk__advance_bytes() is called at least once per every
82403  *  token so it has a major lexer/compiler performance impact.  There are two
82404  *  variants for the main duk__advance_bytes() algorithm: a sliding window
82405  *  approach which is slightly faster at the cost of larger code footprint,
82406  *  and a simple copying one.
82407  *
82408  *  Decoding directly from the source string would be another lexing option.
82409  *  But the lookup window based approach has the advantage of hiding the
82410  *  source string and its encoding effectively which gives more flexibility
82411  *  going forward to e.g. support chunked streaming of source from flash.
82412  *
82413  *  Decodes UTF-8/CESU-8 leniently with support for code points from U+0000 to
82414  *  U+10FFFF, causing an error if the input is unparseable.  Leniency means:
82415  *
82416  *    * Unicode code point validation is intentionally not performed,
82417  *      except to check that the codepoint does not exceed 0x10ffff.
82418  *
82419  *    * In particular, surrogate pairs are allowed and not combined, which
82420  *      allows source files to represent all SourceCharacters with CESU-8.
82421  *      Broken surrogate pairs are allowed, as ECMAScript does not mandate
82422  *      their validation.
82423  *
82424  *    * Allow non-shortest UTF-8 encodings.
82425  *
82426  *  Leniency here causes few security concerns because all character data is
82427  *  decoded into Unicode codepoints before lexer processing, and is then
82428  *  re-encoded into CESU-8.  The source can be parsed as strict UTF-8 with
82429  *  a compiler option.  However, ECMAScript source characters include -all-
82430  *  16-bit unsigned integer codepoints, so leniency seems to be appropriate.
82431  *
82432  *  Note that codepoints above the BMP are not strictly SourceCharacters,
82433  *  but the lexer still accepts them as such.  Before ending up in a string
82434  *  or an identifier name, codepoints above BMP are converted into surrogate
82435  *  pairs and then CESU-8 encoded, resulting in 16-bit Unicode data as
82436  *  expected by ECMAScript.
82437  *
82438  *  An alternative approach to dealing with invalid or partial sequences
82439  *  would be to skip them and replace them with e.g. the Unicode replacement
82440  *  character U+FFFD.  This has limited utility because a replacement character
82441  *  will most likely cause a parse error, unless it occurs inside a string.
82442  *  Further, ECMAScript source is typically pure ASCII.
82443  *
82444  *  See:
82445  *
82446  *     http://en.wikipedia.org/wiki/UTF-8
82447  *     http://en.wikipedia.org/wiki/CESU-8
82448  *     http://tools.ietf.org/html/rfc3629
82449  *     http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
82450  *
82451  *  Future work:
82452  *
82453  *    * Reject other invalid Unicode sequences (see Wikipedia entry for examples)
82454  *      in strict UTF-8 mode.
82455  *
82456  *    * Size optimize.  An attempt to use a 16-byte lookup table for the first
82457  *      byte resulted in a code increase though.
82458  *
82459  *    * Is checking against maximum 0x10ffff really useful?  4-byte encoding
82460  *      imposes a certain limit anyway.
82461  *
82462  *    * Support chunked streaming of source code.  Can be implemented either
82463  *      by streaming chunks of bytes or chunks of codepoints.
82464  */
82465 
82466 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
82467 DUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t start_offset_bytes) {
82468 	duk_lexer_codepoint *cp, *cp_end;
82469 	duk_ucodepoint_t x;
82470 	duk_small_uint_t contlen;
82471 	const duk_uint8_t *p, *p_end;
82472 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
82473 	duk_ucodepoint_t mincp;
82474 #endif
82475 	duk_int_t input_line;
82476 
82477 	/* Use temporaries and update lex_ctx only when finished. */
82478 	input_line = lex_ctx->input_line;
82479 	p = lex_ctx->input + lex_ctx->input_offset;
82480 	p_end = lex_ctx->input + lex_ctx->input_length;
82481 
82482 	cp = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->buffer + start_offset_bytes);
82483 	cp_end = lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE;
82484 
82485 	for (; cp != cp_end; cp++) {
82486 		cp->offset = (duk_size_t) (p - lex_ctx->input);
82487 		cp->line = input_line;
82488 
82489 		/* XXX: potential issue with signed pointers, p_end < p. */
82490 		if (DUK_UNLIKELY(p >= p_end)) {
82491 			/* If input_offset were assigned a negative value, it would
82492 			 * result in a large positive value.  Most likely it would be
82493 			 * larger than input_length and be caught here.  In any case
82494 			 * no memory unsafe behavior would happen.
82495 			 */
82496 			cp->codepoint = -1;
82497 			continue;
82498 		}
82499 
82500 		x = (duk_ucodepoint_t) (*p++);
82501 
82502 		/* Fast path. */
82503 
82504 		if (DUK_LIKELY(x < 0x80UL)) {
82505 			DUK_ASSERT(x != 0x2028UL && x != 0x2029UL);  /* not LS/PS */
82506 			if (DUK_UNLIKELY(x <= 0x000dUL)) {
82507 				if ((x == 0x000aUL) ||
82508 				    ((x == 0x000dUL) && (p >= p_end || *p != 0x000aUL))) {
82509 					/* lookup for 0x000a above assumes shortest encoding now */
82510 
82511 					/* E5 Section 7.3, treat the following as newlines:
82512 					 *   LF
82513 					 *   CR [not followed by LF]
82514 					 *   LS
82515 					 *   PS
82516 					 *
82517 					 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
82518 					 * the line number.
82519 					 */
82520 					input_line++;
82521 				}
82522 			}
82523 
82524 			cp->codepoint = (duk_codepoint_t) x;
82525 			continue;
82526 		}
82527 
82528 		/* Slow path. */
82529 
82530 		if (x < 0xc0UL) {
82531 			/* 10xx xxxx -> invalid */
82532 			goto error_encoding;
82533 		} else if (x < 0xe0UL) {
82534 			/* 110x xxxx   10xx xxxx  */
82535 			contlen = 1;
82536 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
82537 			mincp = 0x80UL;
82538 #endif
82539 			x = x & 0x1fUL;
82540 		} else if (x < 0xf0UL) {
82541 			/* 1110 xxxx   10xx xxxx   10xx xxxx */
82542 			contlen = 2;
82543 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
82544 			mincp = 0x800UL;
82545 #endif
82546 			x = x & 0x0fUL;
82547 		} else if (x < 0xf8UL) {
82548 			/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx */
82549 			contlen = 3;
82550 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
82551 			mincp = 0x10000UL;
82552 #endif
82553 			x = x & 0x07UL;
82554 		} else {
82555 			/* no point in supporting encodings of 5 or more bytes */
82556 			goto error_encoding;
82557 		}
82558 
82559 		DUK_ASSERT(p_end >= p);
82560 		if ((duk_size_t) contlen > (duk_size_t) (p_end - p)) {
82561 			goto error_clipped;
82562 		}
82563 
82564 		while (contlen > 0) {
82565 			duk_small_uint_t y;
82566 			y = *p++;
82567 			if ((y & 0xc0U) != 0x80U) {
82568 				/* check that byte has the form 10xx xxxx */
82569 				goto error_encoding;
82570 			}
82571 			x = x << 6;
82572 			x += y & 0x3fUL;
82573 			contlen--;
82574 		}
82575 
82576 		/* check final character validity */
82577 
82578 		if (x > 0x10ffffUL) {
82579 			goto error_encoding;
82580 		}
82581 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
82582 		if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
82583 			goto error_encoding;
82584 		}
82585 #endif
82586 
82587 		DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
82588 		if ((x == 0x2028UL) || (x == 0x2029UL)) {
82589 			input_line++;
82590 		}
82591 
82592 		cp->codepoint = (duk_codepoint_t) x;
82593 	}
82594 
82595 	lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
82596 	lex_ctx->input_line = input_line;
82597 	return;
82598 
82599  error_clipped:   /* clipped codepoint */
82600  error_encoding:  /* invalid codepoint encoding or codepoint */
82601 	lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
82602 	lex_ctx->input_line = input_line;
82603 
82604 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_SOURCE_DECODE_FAILED);
82605 	DUK_WO_NORETURN(return;);
82606 }
82607 
82608 DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
82609 	duk_small_uint_t used_bytes, avail_bytes;
82610 
82611 	DUK_ASSERT_DISABLE(count_bytes >= 0);  /* unsigned */
82612 	DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
82613 	DUK_ASSERT(lex_ctx->window >= lex_ctx->buffer);
82614 	DUK_ASSERT(lex_ctx->window < lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE);
82615 	DUK_ASSERT((duk_uint8_t *) lex_ctx->window + count_bytes <= (duk_uint8_t *) lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint));
82616 
82617 	/* Zero 'count' is also allowed to make call sites easier.
82618 	 * Arithmetic in bytes generates better code in GCC.
82619 	 */
82620 
82621 	lex_ctx->window = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->window + count_bytes);  /* avoid multiply */
82622 	used_bytes = (duk_small_uint_t) ((duk_uint8_t *) lex_ctx->window - (duk_uint8_t *) lex_ctx->buffer);
82623 	avail_bytes = DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint) - used_bytes;
82624 	if (avail_bytes < (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint))) {
82625 		/* Not enough data to provide a full window, so "scroll" window to
82626 		 * start of buffer and fill up the rest.
82627 		 */
82628 		duk_memmove((void *) lex_ctx->buffer,
82629 		            (const void *) lex_ctx->window,
82630 		            (size_t) avail_bytes);
82631 		lex_ctx->window = lex_ctx->buffer;
82632 		duk__fill_lexer_buffer(lex_ctx, avail_bytes);
82633 	}
82634 }
82635 
82636 DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
82637 	lex_ctx->window = lex_ctx->buffer;
82638 	duk__fill_lexer_buffer(lex_ctx, 0);
82639 }
82640 #else  /* DUK_USE_LEXER_SLIDING_WINDOW */
82641 DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {
82642 	duk_ucodepoint_t x;
82643 	duk_small_uint_t len;
82644 	duk_small_uint_t i;
82645 	const duk_uint8_t *p;
82646 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
82647 	duk_ucodepoint_t mincp;
82648 #endif
82649 	duk_size_t input_offset;
82650 
82651 	input_offset = lex_ctx->input_offset;
82652 	if (DUK_UNLIKELY(input_offset >= lex_ctx->input_length)) {
82653 		/* If input_offset were assigned a negative value, it would
82654 		 * result in a large positive value.  Most likely it would be
82655 		 * larger than input_length and be caught here.  In any case
82656 		 * no memory unsafe behavior would happen.
82657 		 */
82658 		return -1;
82659 	}
82660 
82661 	p = lex_ctx->input + input_offset;
82662 	x = (duk_ucodepoint_t) (*p);
82663 
82664 	if (DUK_LIKELY(x < 0x80UL)) {
82665 		/* 0xxx xxxx -> fast path */
82666 
82667 		/* input offset tracking */
82668 		lex_ctx->input_offset++;
82669 
82670 		DUK_ASSERT(x != 0x2028UL && x != 0x2029UL);  /* not LS/PS */
82671 		if (DUK_UNLIKELY(x <= 0x000dUL)) {
82672 			if ((x == 0x000aUL) ||
82673 			    ((x == 0x000dUL) && (lex_ctx->input_offset >= lex_ctx->input_length ||
82674 			                         lex_ctx->input[lex_ctx->input_offset] != 0x000aUL))) {
82675 				/* lookup for 0x000a above assumes shortest encoding now */
82676 
82677 				/* E5 Section 7.3, treat the following as newlines:
82678 				 *   LF
82679 				 *   CR [not followed by LF]
82680 				 *   LS
82681 				 *   PS
82682 				 *
82683 				 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
82684 				 * the line number.
82685 				 */
82686 				lex_ctx->input_line++;
82687 			}
82688 		}
82689 
82690 		return (duk_codepoint_t) x;
82691 	}
82692 
82693 	/* Slow path. */
82694 
82695 	if (x < 0xc0UL) {
82696 		/* 10xx xxxx -> invalid */
82697 		goto error_encoding;
82698 	} else if (x < 0xe0UL) {
82699 		/* 110x xxxx   10xx xxxx  */
82700 		len = 2;
82701 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
82702 		mincp = 0x80UL;
82703 #endif
82704 		x = x & 0x1fUL;
82705 	} else if (x < 0xf0UL) {
82706 		/* 1110 xxxx   10xx xxxx   10xx xxxx */
82707 		len = 3;
82708 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
82709 		mincp = 0x800UL;
82710 #endif
82711 		x = x & 0x0fUL;
82712 	} else if (x < 0xf8UL) {
82713 		/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx */
82714 		len = 4;
82715 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
82716 		mincp = 0x10000UL;
82717 #endif
82718 		x = x & 0x07UL;
82719 	} else {
82720 		/* no point in supporting encodings of 5 or more bytes */
82721 		goto error_encoding;
82722 	}
82723 
82724 	DUK_ASSERT(lex_ctx->input_length >= lex_ctx->input_offset);
82725 	if ((duk_size_t) len > (duk_size_t) (lex_ctx->input_length - lex_ctx->input_offset)) {
82726 		goto error_clipped;
82727 	}
82728 
82729 	p++;
82730 	for (i = 1; i < len; i++) {
82731 		duk_small_uint_t y;
82732 		y = *p++;
82733 		if ((y & 0xc0U) != 0x80U) {
82734 			/* check that byte has the form 10xx xxxx */
82735 			goto error_encoding;
82736 		}
82737 		x = x << 6;
82738 		x += y & 0x3fUL;
82739 	}
82740 
82741 	/* check final character validity */
82742 
82743 	if (x > 0x10ffffUL) {
82744 		goto error_encoding;
82745 	}
82746 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
82747 	if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
82748 		goto error_encoding;
82749 	}
82750 #endif
82751 
82752 	/* input offset tracking */
82753 	lex_ctx->input_offset += len;
82754 
82755 	/* line tracking */
82756 	DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
82757 	if ((x == 0x2028UL) || (x == 0x2029UL)) {
82758 		lex_ctx->input_line++;
82759 	}
82760 
82761 	return (duk_codepoint_t) x;
82762 
82763  error_clipped:   /* clipped codepoint */
82764  error_encoding:  /* invalid codepoint encoding or codepoint */
82765 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_SOURCE_DECODE_FAILED);
82766 	DUK_WO_NORETURN(return 0;);
82767 }
82768 
82769 DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
82770 	duk_small_uint_t keep_bytes;
82771 	duk_lexer_codepoint *cp, *cp_end;
82772 
82773 	DUK_ASSERT_DISABLE(count_bytes >= 0);  /* unsigned */
82774 	DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
82775 
82776 	/* Zero 'count' is also allowed to make call sites easier. */
82777 
82778 	keep_bytes = DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint) - count_bytes;
82779 	duk_memmove((void *) lex_ctx->window,
82780 	            (const void *) ((duk_uint8_t *) lex_ctx->window + count_bytes),
82781 	            (size_t) keep_bytes);
82782 
82783 	cp = (duk_lexer_codepoint *) ((duk_uint8_t *) lex_ctx->window + keep_bytes);
82784 	cp_end = lex_ctx->window + DUK_LEXER_WINDOW_SIZE;
82785 	for (; cp != cp_end; cp++) {
82786 		cp->offset = lex_ctx->input_offset;
82787 		cp->line = lex_ctx->input_line;
82788 		cp->codepoint = duk__read_char(lex_ctx);
82789 	}
82790 }
82791 
82792 DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
82793 	/* Call with count == DUK_LEXER_WINDOW_SIZE to fill buffer initially. */
82794 	duk__advance_bytes(lex_ctx, DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint));  /* fill window */
82795 }
82796 #endif  /* DUK_USE_LEXER_SLIDING_WINDOW */
82797 
82798 DUK_LOCAL void duk__advance_chars(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_chars) {
82799 	duk__advance_bytes(lex_ctx, count_chars * sizeof(duk_lexer_codepoint));
82800 }
82801 
82802 /*
82803  *  (Re)initialize the temporary byte buffer.  May be called extra times
82804  *  with little impact.
82805  */
82806 
82807 DUK_LOCAL void duk__initbuffer(duk_lexer_ctx *lex_ctx) {
82808 	/* Reuse buffer as is unless buffer has grown large. */
82809 	if (DUK_HBUFFER_DYNAMIC_GET_SIZE(lex_ctx->buf) < DUK_LEXER_TEMP_BUF_LIMIT) {
82810 		/* Keep current size */
82811 	} else {
82812 		duk_hbuffer_resize(lex_ctx->thr, lex_ctx->buf, DUK_LEXER_TEMP_BUF_LIMIT);
82813 	}
82814 
82815 	DUK_BW_INIT_WITHBUF(lex_ctx->thr, &lex_ctx->bw, lex_ctx->buf);
82816 }
82817 
82818 /*
82819  *  Append a Unicode codepoint to the temporary byte buffer.  Performs
82820  *  CESU-8 surrogate pair encoding for codepoints above the BMP.
82821  *  Existing surrogate pairs are allowed and also encoded into CESU-8.
82822  */
82823 
82824 DUK_LOCAL void duk__appendbuffer(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
82825 	/*
82826 	 *  Since character data is only generated by decoding the source or by
82827 	 *  the compiler itself, we rely on the input codepoints being correct
82828 	 *  and avoid a check here.
82829 	 *
82830 	 *  Character data can also come here through decoding of Unicode
82831 	 *  escapes ("\udead\ubeef") so all 16-but unsigned values can be
82832 	 *  present, even when the source file itself is strict UTF-8.
82833 	 */
82834 	DUK_ASSERT(x >= 0 && x <= 0x10ffffL);
82835 
82836 	DUK_BW_WRITE_ENSURE_CESU8(lex_ctx->thr, &lex_ctx->bw, (duk_ucodepoint_t) x);
82837 }
82838 
82839 DUK_LOCAL void duk__appendbuffer_ascii(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
82840 	/* ASCII characters can be emitted as a single byte without encoding
82841 	 * which matters for some fast paths.
82842 	 */
82843 	DUK_ASSERT(x >= 0 && x <= 0x7f);
82844 
82845 	DUK_BW_WRITE_ENSURE_U8(lex_ctx->thr, &lex_ctx->bw, (duk_uint8_t) x);
82846 }
82847 
82848 /*
82849  *  Intern the temporary byte buffer into a valstack slot
82850  *  (in practice, slot1 or slot2).
82851  */
82852 
82853 DUK_LOCAL duk_hstring *duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valstack_idx) {
82854 	DUK_ASSERT(valstack_idx == lex_ctx->slot1_idx || valstack_idx == lex_ctx->slot2_idx);
82855 
82856 	DUK_BW_PUSH_AS_STRING(lex_ctx->thr, &lex_ctx->bw);
82857 	duk_replace(lex_ctx->thr, valstack_idx);
82858 	return duk_known_hstring(lex_ctx->thr, valstack_idx);
82859 }
82860 
82861 /*
82862  *  Init lexer context
82863  */
82864 
82865 DUK_INTERNAL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx) {
82866 	DUK_ASSERT(lex_ctx != NULL);
82867 
82868 	duk_memzero(lex_ctx, sizeof(*lex_ctx));
82869 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
82870 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
82871 	lex_ctx->window = NULL;
82872 #endif
82873 	lex_ctx->thr = NULL;
82874 	lex_ctx->input = NULL;
82875 	lex_ctx->buf = NULL;
82876 #endif
82877 }
82878 
82879 /*
82880  *  Set lexer input position and reinitialize lookup window.
82881  */
82882 
82883 DUK_INTERNAL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
82884 	pt->offset = lex_ctx->window[0].offset;
82885 	pt->line = lex_ctx->window[0].line;
82886 }
82887 
82888 DUK_INTERNAL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
82889 	DUK_ASSERT_DISABLE(pt->offset >= 0);  /* unsigned */
82890 	DUK_ASSERT(pt->line >= 1);
82891 	lex_ctx->input_offset = pt->offset;
82892 	lex_ctx->input_line = pt->line;
82893 	duk__init_lexer_window(lex_ctx);
82894 }
82895 
82896 /*
82897  *  Lexing helpers
82898  */
82899 
82900 /* Numeric value of a hex digit (also covers octal and decimal digits) or
82901  * -1 if not a valid hex digit.
82902  */
82903 DUK_LOCAL duk_codepoint_t duk__hexval_validate(duk_codepoint_t x) {
82904 	duk_small_int_t t;
82905 
82906 	/* Here 'x' is a Unicode codepoint */
82907 	if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
82908 		t = duk_hex_dectab[x];
82909 		if (DUK_LIKELY(t >= 0)) {
82910 			return t;
82911 		}
82912 	}
82913 
82914 	return -1;
82915 }
82916 
82917 /* Just a wrapper for call sites where 'x' is known to be valid so
82918  * we assert for it before decoding.
82919  */
82920 DUK_LOCAL duk_codepoint_t duk__hexval(duk_codepoint_t x) {
82921 	duk_codepoint_t ret;
82922 
82923 	DUK_ASSERT((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
82924 	           (x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_F) ||
82925 	           (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_F));
82926 	ret = duk__hexval_validate(x);
82927 	DUK_ASSERT(ret >= 0 && ret <= 15);
82928 	return ret;
82929 }
82930 
82931 /* having this as a separate function provided a size benefit */
82932 DUK_LOCAL duk_bool_t duk__is_hex_digit(duk_codepoint_t x) {
82933 	if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
82934 		return (duk_hex_dectab[x] >= 0);
82935 	}
82936 	return 0;
82937 }
82938 
82939 /* Parse a Unicode escape of the form \xHH, \uHHHH, or \u{H+}.  Shared by
82940  * source and RegExp parsing.
82941  */
82942 DUK_LOCAL duk_codepoint_t duk__lexer_parse_escape(duk_lexer_ctx *lex_ctx, duk_bool_t allow_es6) {
82943 	duk_small_int_t digits;  /* Initial value 2 or 4 for fixed length escapes, 0 for ES2015 \u{H+}. */
82944 	duk_codepoint_t escval;
82945 	duk_codepoint_t x;
82946 	duk_small_uint_t adv;
82947 
82948 	DUK_ASSERT(DUK__L0() == DUK_ASC_BACKSLASH);  /* caller responsibilities */
82949 	DUK_ASSERT(DUK__L1() == DUK_ASC_LC_X || DUK__L1() == DUK_ASC_LC_U);
82950 	DUK_UNREF(allow_es6);
82951 
82952 	adv = 2;
82953 	digits = 2;
82954 	if (DUK__L1() == DUK_ASC_LC_U) {
82955 		digits = 4;
82956 #if defined(DUK_USE_ES6_UNICODE_ESCAPE)
82957 		if (DUK__L2() == DUK_ASC_LCURLY && allow_es6) {
82958 			digits = 0;
82959 			adv = 3;
82960 		}
82961 #endif
82962 	}
82963 	DUK__ADVANCECHARS(lex_ctx, adv);
82964 
82965 	escval = 0;
82966 	for (;;) {
82967 		/* One of the escape forms: \xHH, \uHHHH, \u{H+}.
82968 		 * The 'digits' variable tracks parsing state and is
82969 		 * initialized to:
82970 		 *
82971 		 *   \xHH     2
82972 		 *   \uHH     4
82973 		 *   \u{H+}   0 first time, updated to -1 to indicate
82974 		 *            at least one digit has been parsed
82975 		 *
82976 		 * Octal parsing is handled separately because it can be
82977 		 * done with fixed lookahead and also has validation
82978 		 * rules which depend on the escape length (which is
82979 		 * variable).
82980 		 *
82981 		 * We don't need a specific check for x < 0 (end of
82982 		 * input) or duk_unicode_is_line_terminator(x)
82983 		 * because the 'dig' decode will fail and lead to a
82984 		 * SyntaxError.
82985 		 */
82986 		duk_codepoint_t dig;
82987 
82988 		x = DUK__L0();
82989 		DUK__ADVANCECHARS(lex_ctx, 1);
82990 
82991 		dig = duk__hexval_validate(x);
82992 		if (digits > 0) {
82993 			digits--;
82994 			if (dig < 0) {
82995 				goto fail_escape;
82996 			}
82997 			DUK_ASSERT(dig >= 0x00 && dig <= 0x0f);
82998 			escval = (escval << 4) + dig;
82999 			if (digits == 0) {
83000 				DUK_ASSERT(escval >= 0 && escval <= 0xffffL);
83001 				break;
83002 			}
83003 		} else {
83004 #if defined(DUK_USE_ES6_UNICODE_ESCAPE)
83005 			DUK_ASSERT(digits == 0 /* first time */ || digits == -1 /* others */);
83006 			if (dig >= 0) {
83007 				DUK_ASSERT(dig >= 0x00 && dig <= 0x0f);
83008 				escval = (escval << 4) + dig;
83009 				if (escval > 0x10ffffL) {
83010 					goto fail_escape;
83011 				}
83012 			} else if (x == DUK_ASC_RCURLY) {
83013 				if (digits == 0) {
83014 					/* Empty escape, \u{}. */
83015 					goto fail_escape;
83016 				}
83017 				DUK_ASSERT(escval >= 0 && escval <= 0x10ffffL);
83018 				break;
83019 			} else {
83020 				goto fail_escape;
83021 			}
83022 			digits = -1;  /* Indicate we have at least one digit. */
83023 #else  /* DUK_USE_ES6_UNICODE_ESCAPE */
83024 			DUK_ASSERT(0);  /* Never happens if \u{H+} support disabled. */
83025 #endif  /* DUK_USE_ES6_UNICODE_ESCAPE */
83026 		}
83027 	}
83028 
83029 	return escval;
83030 
83031  fail_escape:
83032 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
83033 	DUK_WO_NORETURN(return 0;);
83034 }
83035 
83036 /* Parse legacy octal escape of the form \N{1,3}, e.g. \0, \5, \0377.  Maximum
83037  * allowed value is \0377 (U+00FF), longest match is used.  Used for both string
83038  * RegExp octal escape parsing.  Window[0] must be the slash '\' and the first
83039  * digit must already be validated to be in [0-9] by the caller.
83040  */
83041 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) {
83042 	duk_codepoint_t cp;
83043 	duk_small_uint_t lookup_idx;
83044 	duk_small_uint_t adv;
83045 	duk_codepoint_t tmp;
83046 
83047 	DUK_ASSERT(out_adv != NULL);
83048 	DUK_ASSERT(DUK__LOOKUP(lex_ctx, 0) == DUK_ASC_BACKSLASH);
83049 	DUK_ASSERT(DUK__LOOKUP(lex_ctx, 1) >= DUK_ASC_0 && DUK__LOOKUP(lex_ctx, 1) <= DUK_ASC_9);
83050 
83051 	cp = 0;
83052 	tmp = 0;
83053 	for (lookup_idx = 1; lookup_idx <= 3; lookup_idx++) {
83054 		DUK_DDD(DUK_DDDPRINT("lookup_idx=%ld, cp=%ld", (long) lookup_idx, (long) cp));
83055 		tmp = DUK__LOOKUP(lex_ctx, lookup_idx);
83056 		if (tmp < DUK_ASC_0 || tmp > DUK_ASC_7) {
83057 			/* No more valid digits. */
83058 			break;
83059 		}
83060 		tmp = (cp << 3) + (tmp - DUK_ASC_0);
83061 		if (tmp > 0xff) {
83062 			/* Three digit octal escapes above \377 (= 0xff)
83063 			 * are not allowed.
83064 			 */
83065 			break;
83066 		}
83067 		cp = tmp;
83068 	}
83069 	DUK_DDD(DUK_DDDPRINT("final lookup_idx=%ld, cp=%ld", (long) lookup_idx, (long) cp));
83070 
83071 	adv = lookup_idx;
83072 	if (lookup_idx == 1) {
83073 		DUK_DDD(DUK_DDDPRINT("\\8 or \\9 -> treat as literal, accept in strict mode too"));
83074 		DUK_ASSERT(tmp == DUK_ASC_8 || tmp == DUK_ASC_9);
83075 		cp = tmp;
83076 		adv++;  /* correction to above, eat offending character */
83077 	} else if (lookup_idx == 2 && cp == 0) {
83078 		/* Note: 'foo\0bar' is OK in strict mode, but 'foo\00bar' is not.
83079 		 * It won't be interpreted as 'foo\u{0}0bar' but as a SyntaxError.
83080 		 */
83081 		DUK_DDD(DUK_DDDPRINT("\\0 -> accept in strict mode too"));
83082 	} else {
83083 		/* This clause also handles non-shortest zero, e.g. \00. */
83084 		if (reject_annex_b) {
83085 			DUK_DDD(DUK_DDDPRINT("non-zero octal literal %ld -> reject in strict-mode", (long) cp));
83086 			cp = -1;
83087 		} else {
83088 			DUK_DDD(DUK_DDDPRINT("non-zero octal literal %ld -> accepted", (long) cp));
83089 			DUK_ASSERT(cp >= 0 && cp <= 0xff);
83090 		}
83091 	}
83092 
83093 	*out_adv = adv;
83094 
83095 	DUK_ASSERT((cp >= 0 && cp <= 0xff) || (cp == -1 && reject_annex_b));
83096 	return cp;
83097 }
83098 
83099 /* XXX: move strict mode to lex_ctx? */
83100 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) {
83101 	duk_small_uint_t adv;
83102 
83103 	for (adv = 1 /* initial quote */ ;;) {
83104 		duk_codepoint_t x;
83105 
83106 		DUK__ADVANCECHARS(lex_ctx, adv);  /* eat opening quote on first loop */
83107 		x = DUK__L0();
83108 
83109 		adv = 1;
83110 		if (x == quote) {
83111 			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat closing quote */
83112 			break;
83113 		} else if (x == '\\') {
83114 			/* DUK__L0        -> '\' char
83115 			 * DUK__L1 ... DUK__L5 -> more lookup
83116 			 */
83117 			duk_small_int_t emitcp = -1;
83118 
83119 			x = DUK__L1();
83120 
83121 			/* How much to advance before next loop. */
83122 			adv = 2;  /* note: long live range */
83123 
83124 			switch (x) {
83125 			case '\'':
83126 				emitcp = 0x0027;
83127 				break;
83128 			case '"':
83129 				emitcp = 0x0022;
83130 				break;
83131 			case '\\':
83132 				emitcp = 0x005c;
83133 				break;
83134 			case 'b':
83135 				emitcp = 0x0008;
83136 				break;
83137 			case 'f':
83138 				emitcp = 0x000c;
83139 				break;
83140 			case 'n':
83141 				emitcp = 0x000a;
83142 				break;
83143 			case 'r':
83144 				emitcp = 0x000d;
83145 				break;
83146 			case 't':
83147 				emitcp = 0x0009;
83148 				break;
83149 			case 'v':
83150 				emitcp = 0x000b;
83151 				break;
83152 			case 'x':
83153 			case 'u': {
83154 				duk_codepoint_t esc_cp;
83155 				esc_cp = duk__lexer_parse_escape(lex_ctx, 1 /*allow_es6*/);
83156 				DUK__APPENDBUFFER(lex_ctx, esc_cp);
83157 				adv = 0;
83158 				break;
83159 			}
83160 			default: {
83161 				if (duk_unicode_is_line_terminator(x)) {
83162 					/* line continuation */
83163 					if (x == 0x000d && DUK__L2() == 0x000a) {
83164 						/* CR LF again a special case */
83165 						adv = 3;  /* line terminator, CR, LF */
83166 					}
83167 				} else if (DUK__ISDIGIT(x)) {
83168 					/*
83169 					 *  Octal escape or zero escape:
83170 					 *    \0                                     (lookahead not OctalDigit)
83171 					 *    \1 ... \7                              (lookahead not OctalDigit)
83172 					 *    \ZeroToThree OctalDigit                (lookahead not OctalDigit)
83173 					 *    \FourToSeven OctalDigit                (no lookahead restrictions)
83174 					 *    \ZeroToThree OctalDigit OctalDigit     (no lookahead restrictions)
83175 					 *
83176 					 *  Zero escape is part of the standard syntax.  Octal escapes are
83177 					 *  defined in E5 Section B.1.2, and are only allowed in non-strict mode.
83178 					 *  Any other productions starting with a decimal digit are invalid
83179 					 *  but are in practice treated like identity escapes.
83180 					 *
83181 					 *  Parse octal (up to 3 digits) from the lookup window.
83182 					 */
83183 
83184 					emitcp = duk__lexer_parse_legacy_octal(lex_ctx, &adv, strict_mode /*reject_annex_b*/);
83185 					if (emitcp < 0) {
83186 						goto fail_escape;
83187 					}
83188 				} else if (x < 0) {
83189 					goto fail_unterminated;
83190 				} else {
83191 					/* escaped NonEscapeCharacter */
83192 					DUK__APPENDBUFFER(lex_ctx, x);
83193 				}
83194 			}  /* end default clause */
83195 			}  /* end switch */
83196 
83197 			/* Shared handling for single codepoint escapes. */
83198 			if (emitcp >= 0) {
83199 				DUK__APPENDBUFFER(lex_ctx, emitcp);
83200 			}
83201 
83202 			/* Track number of escapes; count not really needed but directive
83203 			 * prologues need to detect whether there were any escapes or line
83204 			 * continuations or not.
83205 			 */
83206 			out_token->num_escapes++;
83207 		} else if (x >= 0x20 && x <= 0x7f) {
83208 			/* Fast path for ASCII case, avoids line terminator
83209 			 * check and CESU-8 encoding.
83210 			 */
83211 			DUK_ASSERT(x >= 0);
83212 			DUK_ASSERT(!duk_unicode_is_line_terminator(x));
83213 			DUK_ASSERT(x != quote);
83214 			DUK_ASSERT(x != DUK_ASC_BACKSLASH);
83215 			DUK__APPENDBUFFER_ASCII(lex_ctx, x);
83216 		} else if (x < 0 || duk_unicode_is_line_terminator(x)) {
83217 			goto fail_unterminated;
83218 		} else {
83219 			/* Character which is part of the string but wasn't handled
83220 			 * by the fast path.
83221 			 */
83222 			DUK__APPENDBUFFER(lex_ctx, x);
83223 		}
83224 	} /* string parse loop */
83225 
83226 	return;
83227 
83228  fail_escape:
83229 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
83230 	DUK_WO_NORETURN(return;);
83231 
83232  fail_unterminated:
83233 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_STRING);
83234 	DUK_WO_NORETURN(return;);
83235 }
83236 
83237 /* Skip to end-of-line (or end-of-file), used for single line comments. */
83238 DUK_LOCAL void duk__lexer_skip_to_endofline(duk_lexer_ctx *lex_ctx) {
83239 	for (;;) {
83240 		duk_codepoint_t x;
83241 
83242 		x = DUK__L0();
83243 		if (x < 0 || duk_unicode_is_line_terminator(x)) {
83244 			break;
83245 		}
83246 		DUK__ADVANCECHARS(lex_ctx, 1);
83247 	}
83248 }
83249 
83250 /*
83251  *  Parse ECMAScript source InputElementDiv or InputElementRegExp
83252  *  (E5 Section 7), skipping whitespace, comments, and line terminators.
83253  *
83254  *  Possible results are:
83255  *    (1) a token
83256  *    (2) a line terminator (skipped)
83257  *    (3) a comment (skipped)
83258  *    (4) EOF
83259  *
83260  *  White space is automatically skipped from the current position (but
83261  *  not after the input element).  If input has already ended, returns
83262  *  DUK_TOK_EOF indefinitely.  If a parse error occurs, uses an DUK_ERROR()
83263  *  macro call (and hence a longjmp through current heap longjmp context).
83264  *  Comments and line terminator tokens are automatically skipped.
83265  *
83266  *  The input element being matched is determined by regexp_mode; if set,
83267  *  parses a InputElementRegExp, otherwise a InputElementDiv.  The
83268  *  difference between these are handling of productions starting with a
83269  *  forward slash.
83270  *
83271  *  If strict_mode is set, recognizes additional future reserved words
83272  *  specific to strict mode, and refuses to parse octal literals.
83273  *
83274  *  The matching strategy below is to (currently) use a six character
83275  *  lookup window to quickly determine which production is the -longest-
83276  *  matching one, and then parse that.  The top-level if-else clauses
83277  *  match the first character, and the code blocks for each clause
83278  *  handle -all- alternatives for that first character.  ECMAScript
83279  *  specification uses the "longest match wins" semantics, so the order
83280  *  of the if-clauses matters.
83281  *
83282  *  Misc notes:
83283  *
83284  *    * ECMAScript numeric literals do not accept a sign character.
83285  *      Consequently e.g. "-1.0" is parsed as two tokens: a negative
83286  *      sign and a positive numeric literal.  The compiler performs
83287  *      the negation during compilation, so this has no adverse impact.
83288  *
83289  *    * There is no token for "undefined": it is just a value available
83290  *      from the global object (or simply established by doing a reference
83291  *      to an undefined value).
83292  *
83293  *    * Some contexts want Identifier tokens, which are IdentifierNames
83294  *      excluding reserved words, while some contexts want IdentifierNames
83295  *      directly.  In the latter case e.g. "while" is interpreted as an
83296  *      identifier name, not a DUK_TOK_WHILE token.  The solution here is
83297  *      to provide both token types: DUK_TOK_WHILE goes to 't' while
83298  *      DUK_TOK_IDENTIFIER goes to 't_nores', and 'slot1' always contains
83299  *      the identifier / keyword name.
83300  *
83301  *    * Directive prologue needs to identify string literals such as
83302  *      "use strict" and 'use strict', which are sensitive to line
83303  *      continuations and escape sequences.  For instance, "use\u0020strict"
83304  *      is a valid directive but is distinct from "use strict".  The solution
83305  *      here is to decode escapes while tokenizing, but to keep track of the
83306  *      number of escapes.  Directive detection can then check that the
83307  *      number of escapes is zero.
83308  *
83309  *    * Multi-line comments with one or more internal LineTerminator are
83310  *      treated like a line terminator to comply with automatic semicolon
83311  *      insertion.
83312  */
83313 
83314 DUK_INTERNAL
83315 void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
83316                                       duk_token *out_token,
83317                                       duk_bool_t strict_mode,
83318                                       duk_bool_t regexp_mode) {
83319 	duk_codepoint_t x;           /* temporary, must be signed and 32-bit to hold Unicode code points */
83320 	duk_small_uint_t advtok = 0; /* (advance << 8) + token_type, updated at function end,
83321 	                              * init is unnecessary but suppresses "may be used uninitialized" warnings.
83322 	                              */
83323 	duk_bool_t got_lineterm = 0;  /* got lineterm preceding non-whitespace, non-lineterm token */
83324 
83325 	if (++lex_ctx->token_count >= lex_ctx->token_limit) {
83326 		goto fail_token_limit;
83327 	}
83328 
83329 	out_token->t = DUK_TOK_EOF;
83330 	out_token->t_nores = DUK_TOK_INVALID;  /* marker: copy t if not changed */
83331 #if 0  /* not necessary to init, disabled for faster parsing */
83332 	out_token->num = DUK_DOUBLE_NAN;
83333 	out_token->str1 = NULL;
83334 	out_token->str2 = NULL;
83335 #endif
83336 	out_token->num_escapes = 0;
83337 	/* out_token->lineterm set by caller */
83338 
83339 	/* This would be nice, but parsing is faster without resetting the
83340 	 * value slots.  The only side effect is that references to temporary
83341 	 * string values may linger until lexing is finished; they're then
83342 	 * freed normally.
83343 	 */
83344 #if 0
83345 	duk_to_undefined(lex_ctx->thr, lex_ctx->slot1_idx);
83346 	duk_to_undefined(lex_ctx->thr, lex_ctx->slot2_idx);
83347 #endif
83348 
83349 	/* 'advtok' indicates how much to advance and which token id to assign
83350 	 * at the end.  This shared functionality minimizes code size.  All
83351 	 * code paths are required to set 'advtok' to some value, so no default
83352 	 * init value is used.  Code paths calling DUK_ERROR() never return so
83353 	 * they don't need to set advtok.
83354 	 */
83355 
83356 	/*
83357 	 *  Matching order:
83358 	 *
83359 	 *    Punctuator first chars, also covers comments, regexps
83360 	 *    LineTerminator
83361 	 *    Identifier or reserved word, also covers null/true/false literals
83362 	 *    NumericLiteral
83363 	 *    StringLiteral
83364 	 *    EOF
83365 	 *
83366 	 *  The order does not matter as long as the longest match is
83367 	 *  always correctly identified.  There are order dependencies
83368 	 *  in the clauses, so it's not trivial to convert to a switch.
83369 	 */
83370 
83371  restart_lineupdate:
83372 	out_token->start_line = lex_ctx->window[0].line;
83373 
83374  restart:
83375 	out_token->start_offset = lex_ctx->window[0].offset;
83376 
83377 	x = DUK__L0();
83378 
83379 	switch (x) {
83380 	case DUK_ASC_SPACE:
83381 	case DUK_ASC_HT:  /* fast paths for space and tab */
83382 		DUK__ADVANCECHARS(lex_ctx, 1);
83383 		goto restart;
83384 	case DUK_ASC_LF:  /* LF line terminator; CR LF and Unicode lineterms are handled in slow path */
83385 		DUK__ADVANCECHARS(lex_ctx, 1);
83386 		got_lineterm = 1;
83387 		goto restart_lineupdate;
83388 #if defined(DUK_USE_SHEBANG_COMMENTS)
83389 	case DUK_ASC_HASH:  /* '#' */
83390 		if (DUK__L1() == DUK_ASC_EXCLAMATION && lex_ctx->window[0].offset == 0 &&
83391 		    (lex_ctx->flags & DUK_COMPILE_SHEBANG)) {
83392 			/* "Shebang" comment ('#! ...') on first line. */
83393 			/* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but not necessary */
83394 			duk__lexer_skip_to_endofline(lex_ctx);
83395 			goto restart;  /* line terminator will be handled on next round */
83396 		}
83397 		goto fail_token;
83398 #endif  /* DUK_USE_SHEBANG_COMMENTS */
83399 	case DUK_ASC_SLASH:  /* '/' */
83400 		if (DUK__L1() == DUK_ASC_SLASH) {
83401 			/*
83402 			 *  E5 Section 7.4, allow SourceCharacter (which is any 16-bit
83403 			 *  code point).
83404 			 */
83405 
83406 			/* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but not necessary */
83407 			duk__lexer_skip_to_endofline(lex_ctx);
83408 			goto restart;  /* line terminator will be handled on next round */
83409 		} else if (DUK__L1() == DUK_ASC_STAR) {
83410 			/*
83411 			 *  E5 Section 7.4.  If the multi-line comment contains a newline,
83412 			 *  it is treated like a single line terminator for automatic
83413 			 *  semicolon insertion.
83414 			 */
83415 
83416 			duk_bool_t last_asterisk = 0;
83417 			DUK__ADVANCECHARS(lex_ctx, 2);
83418 			for (;;) {
83419 				x = DUK__L0();
83420 				if (x < 0) {
83421 					goto fail_unterm_comment;
83422 				}
83423 				DUK__ADVANCECHARS(lex_ctx, 1);
83424 				if (last_asterisk && x == DUK_ASC_SLASH) {
83425 					break;
83426 				}
83427 				if (duk_unicode_is_line_terminator(x)) {
83428 					got_lineterm = 1;
83429 				}
83430 				last_asterisk = (x == DUK_ASC_STAR);
83431 			}
83432 			goto restart_lineupdate;
83433 		} else if (regexp_mode) {
83434 #if defined(DUK_USE_REGEXP_SUPPORT)
83435 			/*
83436 			 *  "/" followed by something in regexp mode.  See E5 Section 7.8.5.
83437 			 *
83438 			 *  RegExp parsing is a bit complex.  First, the regexp body is delimited
83439 			 *  by forward slashes, but the body may also contain forward slashes as
83440 			 *  part of an escape sequence or inside a character class (delimited by
83441 			 *  square brackets).  A mini state machine is used to implement these.
83442 			 *
83443 			 *  Further, an early (parse time) error must be thrown if the regexp
83444 			 *  would cause a run-time error when used in the expression new RegExp(...).
83445 			 *  Parsing here simply extracts the (candidate) regexp, and also accepts
83446 			 *  invalid regular expressions (which are delimited properly).  The caller
83447 			 *  (compiler) must perform final validation and regexp compilation.
83448 			 *
83449 			 *  RegExp first char may not be '/' (single line comment) or '*' (multi-
83450 			 *  line comment).  These have already been checked above, so there is no
83451 			 *  need below for special handling of the first regexp character as in
83452 			 *  the E5 productions.
83453 			 *
83454 			 *  About unicode escapes within regexp literals:
83455 			 *
83456 			 *      E5 Section 7.8.5 grammar does NOT accept \uHHHH escapes.
83457 			 *      However, Section 6 states that regexps accept the escapes,
83458 			 *      see paragraph starting with "In string literals...".
83459 			 *      The regexp grammar, which sees the decoded regexp literal
83460 			 *      (after lexical parsing) DOES have a \uHHHH unicode escape.
83461 			 *      So, for instance:
83462 			 *
83463 			 *          /\u1234/
83464 			 *
83465 			 *      should first be parsed by the lexical grammar as:
83466 			 *
83467 			 *          '\' 'u'      RegularExpressionBackslashSequence
83468 			 *          '1'          RegularExpressionNonTerminator
83469 			 *          '2'          RegularExpressionNonTerminator
83470 			 *          '3'          RegularExpressionNonTerminator
83471 			 *          '4'          RegularExpressionNonTerminator
83472 			 *
83473 			 *      and the escape itself is then parsed by the regexp engine.
83474 			 *      This is the current implementation.
83475 			 *
83476 			 *  Minor spec inconsistency:
83477 			 *
83478 			 *      E5 Section 7.8.5 RegularExpressionBackslashSequence is:
83479 			 *
83480 			 *         \ RegularExpressionNonTerminator
83481 			 *
83482 			 *      while Section A.1 RegularExpressionBackslashSequence is:
83483 			 *
83484 			 *         \ NonTerminator
83485 			 *
83486 			 *      The latter is not normative and a typo.
83487 			 *
83488 			 */
83489 
83490 			/* first, parse regexp body roughly */
83491 
83492 			duk_small_int_t state = 0;  /* 0=base, 1=esc, 2=class, 3=class+esc */
83493 
83494 			DUK__INITBUFFER(lex_ctx);
83495 			for (;;) {
83496 				DUK__ADVANCECHARS(lex_ctx, 1);  /* skip opening slash on first loop */
83497 				x = DUK__L0();
83498 				if (x < 0 || duk_unicode_is_line_terminator(x)) {
83499 					goto fail_unterm_regexp;
83500 				}
83501 				x = DUK__L0();  /* re-read to avoid spill / fetch */
83502 				if (state == 0) {
83503 					if (x == DUK_ASC_SLASH) {
83504 						DUK__ADVANCECHARS(lex_ctx, 1);  /* eat closing slash */
83505 						break;
83506 					} else if (x == DUK_ASC_BACKSLASH) {
83507 						state = 1;
83508 					} else if (x == DUK_ASC_LBRACKET) {
83509 						state = 2;
83510 					}
83511 				} else if (state == 1) {
83512 					state = 0;
83513 				} else if (state == 2) {
83514 					if (x == DUK_ASC_RBRACKET) {
83515 						state = 0;
83516 					} else if (x == DUK_ASC_BACKSLASH) {
83517 						state = 3;
83518 					}
83519 				} else { /* state == 3 */
83520 					state = 2;
83521 				}
83522 				DUK__APPENDBUFFER(lex_ctx, x);
83523 			}
83524 			out_token->str1 = duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
83525 
83526 			/* second, parse flags */
83527 
83528 			DUK__INITBUFFER(lex_ctx);
83529 			for (;;) {
83530 				x = DUK__L0();
83531 				if (!duk_unicode_is_identifier_part(x)) {
83532 					break;
83533 				}
83534 				x = DUK__L0();  /* re-read to avoid spill / fetch */
83535 				DUK__APPENDBUFFER(lex_ctx, x);
83536 				DUK__ADVANCECHARS(lex_ctx, 1);
83537 			}
83538 			out_token->str2 = duk__internbuffer(lex_ctx, lex_ctx->slot2_idx);
83539 
83540 			DUK__INITBUFFER(lex_ctx);  /* free some memory */
83541 
83542 			/* validation of the regexp is caller's responsibility */
83543 
83544 			advtok = DUK__ADVTOK(0, DUK_TOK_REGEXP);
83545 #else  /* DUK_USE_REGEXP_SUPPORT */
83546 			goto fail_regexp_support;
83547 #endif  /* DUK_USE_REGEXP_SUPPORT */
83548 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
83549 			/* "/=" and not in regexp mode */
83550 			advtok = DUK__ADVTOK(2, DUK_TOK_DIV_EQ);
83551 		} else {
83552 			/* "/" and not in regexp mode */
83553 			advtok = DUK__ADVTOK(1, DUK_TOK_DIV);
83554 		}
83555 		break;
83556 	case DUK_ASC_LCURLY:  /* '{' */
83557 		advtok = DUK__ADVTOK(1, DUK_TOK_LCURLY);
83558 		break;
83559 	case DUK_ASC_RCURLY:  /* '}' */
83560 		advtok = DUK__ADVTOK(1, DUK_TOK_RCURLY);
83561 		break;
83562 	case DUK_ASC_LPAREN:  /* '(' */
83563 		advtok = DUK__ADVTOK(1, DUK_TOK_LPAREN);
83564 		break;
83565 	case DUK_ASC_RPAREN:  /* ')' */
83566 		advtok = DUK__ADVTOK(1, DUK_TOK_RPAREN);
83567 		break;
83568 	case DUK_ASC_LBRACKET:  /* '[' */
83569 		advtok = DUK__ADVTOK(1, DUK_TOK_LBRACKET);
83570 		break;
83571 	case DUK_ASC_RBRACKET:  /* ']' */
83572 		advtok = DUK__ADVTOK(1, DUK_TOK_RBRACKET);
83573 		break;
83574 	case DUK_ASC_PERIOD:  /* '.' */
83575 		if (DUK__ISDIGIT(DUK__L1())) {
83576 			/* Period followed by a digit can only start DecimalLiteral
83577 			 * (handled in slow path).  We could jump straight into the
83578 			 * DecimalLiteral handling but should avoid goto to inside
83579 			 * a block.
83580 			 */
83581 			goto slow_path;
83582 		}
83583 		advtok = DUK__ADVTOK(1, DUK_TOK_PERIOD);
83584 		break;
83585 	case DUK_ASC_SEMICOLON:  /* ';' */
83586 		advtok = DUK__ADVTOK(1, DUK_TOK_SEMICOLON);
83587 		break;
83588 	case DUK_ASC_COMMA:  /* ',' */
83589 		advtok = DUK__ADVTOK(1, DUK_TOK_COMMA);
83590 		break;
83591 	case DUK_ASC_LANGLE:  /* '<' */
83592 #if defined(DUK_USE_HTML_COMMENTS)
83593 		if (DUK__L1() == DUK_ASC_EXCLAMATION && DUK__L2() == DUK_ASC_MINUS && DUK__L3() == DUK_ASC_MINUS) {
83594 			/*
83595 			 *  ES2015: B.1.3, handle "<!--" SingleLineHTMLOpenComment
83596 			 */
83597 
83598 			/* DUK__ADVANCECHARS(lex_ctx, 4) would be correct here, but not necessary */
83599 			duk__lexer_skip_to_endofline(lex_ctx);
83600 			goto restart;  /* line terminator will be handled on next round */
83601 		}
83602 		else
83603 #endif  /* DUK_USE_HTML_COMMENTS */
83604 		if (DUK__L1() == DUK_ASC_LANGLE && DUK__L2() == DUK_ASC_EQUALS) {
83605 			advtok = DUK__ADVTOK(3, DUK_TOK_ALSHIFT_EQ);
83606 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
83607 			advtok = DUK__ADVTOK(2, DUK_TOK_LE);
83608 		} else if (DUK__L1() == DUK_ASC_LANGLE) {
83609 			advtok = DUK__ADVTOK(2, DUK_TOK_ALSHIFT);
83610 		} else {
83611 			advtok = DUK__ADVTOK(1, DUK_TOK_LT);
83612 		}
83613 		break;
83614 	case DUK_ASC_RANGLE:  /* '>' */
83615 		if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE && DUK__L3() == DUK_ASC_EQUALS) {
83616 			advtok = DUK__ADVTOK(4, DUK_TOK_RSHIFT_EQ);
83617 		} else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE) {
83618 			advtok = DUK__ADVTOK(3, DUK_TOK_RSHIFT);
83619 		} else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_EQUALS) {
83620 			advtok = DUK__ADVTOK(3, DUK_TOK_ARSHIFT_EQ);
83621 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
83622 			advtok = DUK__ADVTOK(2, DUK_TOK_GE);
83623 		} else if (DUK__L1() == DUK_ASC_RANGLE) {
83624 			advtok = DUK__ADVTOK(2, DUK_TOK_ARSHIFT);
83625 		} else {
83626 			advtok = DUK__ADVTOK(1, DUK_TOK_GT);
83627 		}
83628 		break;
83629 	case DUK_ASC_EQUALS:  /* '=' */
83630 		if (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {
83631 			advtok = DUK__ADVTOK(3, DUK_TOK_SEQ);
83632 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
83633 			advtok = DUK__ADVTOK(2, DUK_TOK_EQ);
83634 		} else {
83635 			advtok = DUK__ADVTOK(1, DUK_TOK_EQUALSIGN);
83636 		}
83637 		break;
83638 	case DUK_ASC_EXCLAMATION:  /* '!' */
83639 		if (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {
83640 			advtok = DUK__ADVTOK(3, DUK_TOK_SNEQ);
83641 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
83642 			advtok = DUK__ADVTOK(2, DUK_TOK_NEQ);
83643 		} else {
83644 			advtok = DUK__ADVTOK(1, DUK_TOK_LNOT);
83645 		}
83646 		break;
83647 	case DUK_ASC_PLUS:  /* '+' */
83648 		if (DUK__L1() == DUK_ASC_PLUS) {
83649 			advtok = DUK__ADVTOK(2, DUK_TOK_INCREMENT);
83650 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
83651 			advtok = DUK__ADVTOK(2, DUK_TOK_ADD_EQ);
83652 		} else {
83653 			advtok = DUK__ADVTOK(1, DUK_TOK_ADD);
83654 		}
83655 		break;
83656 	case DUK_ASC_MINUS:  /* '-' */
83657 #if defined(DUK_USE_HTML_COMMENTS)
83658 		if (got_lineterm && DUK__L1() == DUK_ASC_MINUS && DUK__L2() == DUK_ASC_RANGLE) {
83659 			/*
83660 			 *  ES2015: B.1.3, handle "-->" SingleLineHTMLCloseComment
83661 			 *  Only allowed:
83662 			 *  - on new line
83663 			 *  - preceded only by whitespace
83664 			 *  - preceded by end of multiline comment and optional whitespace
83665 			 *
83666 			 * Since whitespace generates no tokens, and multiline comments
83667 			 * are treated as a line ending, consulting `got_lineterm` is
83668 			 * sufficient to test for these three options.
83669 			 */
83670 
83671 			/* DUK__ADVANCECHARS(lex_ctx, 3) would be correct here, but not necessary */
83672 			duk__lexer_skip_to_endofline(lex_ctx);
83673 			goto restart;  /* line terminator will be handled on next round */
83674 		} else
83675 #endif  /* DUK_USE_HTML_COMMENTS */
83676 		if (DUK__L1() == DUK_ASC_MINUS) {
83677 			advtok = DUK__ADVTOK(2, DUK_TOK_DECREMENT);
83678 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
83679 			advtok = DUK__ADVTOK(2, DUK_TOK_SUB_EQ);
83680 		} else {
83681 			advtok = DUK__ADVTOK(1, DUK_TOK_SUB);
83682 		}
83683 		break;
83684 	case DUK_ASC_STAR:  /* '*' */
83685 #if defined(DUK_USE_ES7_EXP_OPERATOR)
83686 		if (DUK__L1() == DUK_ASC_STAR && DUK__L2() == DUK_ASC_EQUALS) {
83687 			advtok = DUK__ADVTOK(3, DUK_TOK_EXP_EQ);
83688 		} else if (DUK__L1() == DUK_ASC_STAR) {
83689 			advtok = DUK__ADVTOK(2, DUK_TOK_EXP);
83690 		} else
83691 #endif
83692 		if (DUK__L1() == DUK_ASC_EQUALS) {
83693 			advtok = DUK__ADVTOK(2, DUK_TOK_MUL_EQ);
83694 		} else {
83695 			advtok = DUK__ADVTOK(1, DUK_TOK_MUL);
83696 		}
83697 		break;
83698 	case DUK_ASC_PERCENT:  /* '%' */
83699 		if (DUK__L1() == DUK_ASC_EQUALS) {
83700 			advtok = DUK__ADVTOK(2, DUK_TOK_MOD_EQ);
83701 		} else {
83702 			advtok = DUK__ADVTOK(1, DUK_TOK_MOD);
83703 		}
83704 		break;
83705 	case DUK_ASC_AMP:  /* '&' */
83706 		if (DUK__L1() == DUK_ASC_AMP) {
83707 			advtok = DUK__ADVTOK(2, DUK_TOK_LAND);
83708 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
83709 			advtok = DUK__ADVTOK(2, DUK_TOK_BAND_EQ);
83710 		} else {
83711 			advtok = DUK__ADVTOK(1, DUK_TOK_BAND);
83712 		}
83713 		break;
83714 	case DUK_ASC_PIPE:  /* '|' */
83715 		if (DUK__L1() == DUK_ASC_PIPE) {
83716 			advtok = DUK__ADVTOK(2, DUK_TOK_LOR);
83717 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
83718 			advtok = DUK__ADVTOK(2, DUK_TOK_BOR_EQ);
83719 		} else {
83720 			advtok = DUK__ADVTOK(1, DUK_TOK_BOR);
83721 		}
83722 		break;
83723 	case DUK_ASC_CARET:  /* '^' */
83724 		if (DUK__L1() == DUK_ASC_EQUALS) {
83725 			advtok = DUK__ADVTOK(2, DUK_TOK_BXOR_EQ);
83726 		} else {
83727 			advtok = DUK__ADVTOK(1, DUK_TOK_BXOR);
83728 		}
83729 		break;
83730 	case DUK_ASC_TILDE:  /* '~' */
83731 		advtok = DUK__ADVTOK(1, DUK_TOK_BNOT);
83732 		break;
83733 	case DUK_ASC_QUESTION:  /* '?' */
83734 		advtok = DUK__ADVTOK(1, DUK_TOK_QUESTION);
83735 		break;
83736 	case DUK_ASC_COLON:  /* ':' */
83737 		advtok = DUK__ADVTOK(1, DUK_TOK_COLON);
83738 		break;
83739 	case DUK_ASC_DOUBLEQUOTE:    /* '"' */
83740 	case DUK_ASC_SINGLEQUOTE: {  /* '\'' */
83741 		DUK__INITBUFFER(lex_ctx);
83742 		duk__lexer_parse_string_literal(lex_ctx, out_token, x /*quote*/, strict_mode);
83743 		duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
83744 		out_token->str1 = duk_known_hstring(lex_ctx->thr, lex_ctx->slot1_idx);
83745 
83746 		DUK__INITBUFFER(lex_ctx);  /* free some memory */
83747 
83748 		advtok = DUK__ADVTOK(0, DUK_TOK_STRING);
83749 		break;
83750 	}
83751 	default:
83752 		goto slow_path;
83753 	}  /* switch */
83754 
83755 	goto skip_slow_path;
83756 
83757  slow_path:
83758 	if (duk_unicode_is_line_terminator(x)) {
83759 		if (x == 0x000d && DUK__L1() == 0x000a) {
83760 			/*
83761 			 *  E5 Section 7.3: CR LF is detected as a single line terminator for
83762 			 *  line numbers.  Here we also detect it as a single line terminator
83763 			 *  token.
83764 			 */
83765 			DUK__ADVANCECHARS(lex_ctx, 2);
83766 		} else {
83767 			DUK__ADVANCECHARS(lex_ctx, 1);
83768 		}
83769 		got_lineterm = 1;
83770 		goto restart_lineupdate;
83771 	} else if (duk_unicode_is_identifier_start(x) || x == DUK_ASC_BACKSLASH) {
83772 		/*
83773 		 *  Parse an identifier and then check whether it is:
83774 		 *    - reserved word (keyword or other reserved word)
83775 		 *    - "null"  (NullLiteral)
83776 		 *    - "true"  (BooleanLiteral)
83777 		 *    - "false" (BooleanLiteral)
83778 		 *    - anything else => identifier
83779 		 *
83780 		 *  This does not follow the E5 productions cleanly, but is
83781 		 *  useful and compact.
83782 		 *
83783 		 *  Note that identifiers may contain Unicode escapes,
83784 		 *  see E5 Sections 6 and 7.6.  They must be decoded first,
83785 		 *  and the result checked against allowed characters.
83786 		 *  The above if-clause accepts an identifier start and an
83787 		 *  '\' character -- no other token can begin with a '\'.
83788 		 *
83789 		 *  Note that "get" and "set" are not reserved words in E5
83790 		 *  specification so they are recognized as plain identifiers
83791 		 *  (the tokens DUK_TOK_GET and DUK_TOK_SET are actually not
83792 		 *  used now).  The compiler needs to work around this.
83793 		 *
83794 		 *  Strictly speaking, following ECMAScript longest match
83795 		 *  specification, an invalid escape for the first character
83796 		 *  should cause a syntax error.  However, an invalid escape
83797 		 *  for IdentifierParts should just terminate the identifier
83798 		 *  early (longest match), and let the next tokenization
83799 		 *  fail.  For instance Rhino croaks with 'foo\z' when
83800 		 *  parsing the identifier.  This has little practical impact.
83801 		 */
83802 
83803 		duk_small_uint_t i, i_end;
83804 		duk_bool_t first = 1;
83805 		duk_hstring *str;
83806 
83807 		DUK__INITBUFFER(lex_ctx);
83808 		for (;;) {
83809 			/* re-lookup first char on first loop */
83810 			if (DUK__L0() == DUK_ASC_BACKSLASH) {
83811 				duk_codepoint_t esc_cp;
83812 				if (DUK__L1() != DUK_ASC_LC_U) {
83813 					goto fail_escape;
83814 				}
83815 				esc_cp = duk__lexer_parse_escape(lex_ctx, 1 /*allow_es6*/);
83816 				DUK__APPENDBUFFER(lex_ctx, esc_cp);
83817 
83818 				/* IdentifierStart is stricter than IdentifierPart, so if the first
83819 				 * character is escaped, must have a stricter check here.
83820 				 */
83821 				if (!(first ? duk_unicode_is_identifier_start(esc_cp) : duk_unicode_is_identifier_part(esc_cp))) {
83822 					goto fail_escape;
83823 				}
83824 
83825 				/* Track number of escapes: necessary for proper keyword
83826 				 * detection.
83827 				 */
83828 				out_token->num_escapes++;
83829 			} else {
83830 				/* Note: first character is checked against this.  But because
83831 				 * IdentifierPart includes all IdentifierStart characters, and
83832 				 * the first character (if unescaped) has already been checked
83833 				 * in the if condition, this is OK.
83834 				 */
83835 				if (!duk_unicode_is_identifier_part(DUK__L0())) {
83836 					break;
83837 				}
83838 				DUK__APPENDBUFFER(lex_ctx, DUK__L0());
83839 				DUK__ADVANCECHARS(lex_ctx, 1);
83840 			}
83841 			first = 0;
83842 		}
83843 
83844 		out_token->str1 = duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
83845 		str = out_token->str1;
83846 		out_token->t_nores = DUK_TOK_IDENTIFIER;
83847 
83848 		DUK__INITBUFFER(lex_ctx);  /* free some memory */
83849 
83850 		/*
83851 		 *  Interned identifier is compared against reserved words, which are
83852 		 *  currently interned into the heap context.  See genbuiltins.py.
83853 		 *
83854 		 *  Note that an escape in the identifier disables recognition of
83855 		 *  keywords; e.g. "\u0069f = 1;" is a valid statement (assigns to
83856 		 *  identifier named "if").  This is not necessarily compliant,
83857 		 *  see test-dec-escaped-char-in-keyword.js.
83858 		 *
83859 		 *  Note: "get" and "set" are awkward.  They are not officially
83860 		 *  ReservedWords (and indeed e.g. "var set = 1;" is valid), and
83861 		 *  must come out as DUK_TOK_IDENTIFIER.  The compiler needs to
83862 		 *  work around this a bit.
83863 		 */
83864 
83865 		/* XXX: optimize by adding the token numbers directly into the
83866 		 * always interned duk_hstring objects (there should be enough
83867 		 * flag bits free for that)?
83868 		 */
83869 
83870 		i_end = (strict_mode ? DUK_STRIDX_END_RESERVED : DUK_STRIDX_START_STRICT_RESERVED);
83871 
83872 		advtok = DUK__ADVTOK(0, DUK_TOK_IDENTIFIER);
83873 		if (out_token->num_escapes == 0) {
83874 			for (i = DUK_STRIDX_START_RESERVED; i < i_end; i++) {
83875 				DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
83876 				DUK_ASSERT(i < DUK_HEAP_NUM_STRINGS);
83877 				if (DUK_HTHREAD_GET_STRING(lex_ctx->thr, i) == str) {
83878 					advtok = DUK__ADVTOK(0, DUK_STRIDX_TO_TOK(i));
83879 					break;
83880 				}
83881 			}
83882 		}
83883 	} else if (DUK__ISDIGIT(x) || (x == DUK_ASC_PERIOD)) {
83884 		/* Note: decimal number may start with a period, but must be followed by a digit */
83885 
83886 		/*
83887 		 *  Pre-parsing for decimal, hex, octal (both legacy and ES2015),
83888 		 *  and binary literals, followed by an actual parser step
83889 		 *  provided by numconv.
83890 		 *
83891 		 *  Note: the leading sign character ('+' or '-') is -not- part of
83892 		 *  the production in E5 grammar, and that the a DecimalLiteral
83893 		 *  starting with a '0' must be followed by a non-digit.
83894 		 *
83895 		 *  XXX: the two step parsing process is quite awkward, it would
83896 		 *  be more straightforward to allow numconv to parse the longest
83897 		 *  valid prefix (it already does that, it only needs to indicate
83898 		 *  where the input ended).  However, the lexer decodes characters
83899 		 *  using a limited lookup window, so this is not a trivial change.
83900 		 */
83901 
83902 		/* XXX: because of the final check below (that the literal is not
83903 		 * followed by a digit), this could maybe be simplified, if we bail
83904 		 * out early from a leading zero (and if there are no periods etc).
83905 		 * Maybe too complex.
83906 		 */
83907 
83908 		duk_double_t val;
83909 		duk_bool_t legacy_oct = 0;
83910 		duk_small_int_t state;  /* 0=before period/exp,
83911 		                         * 1=after period, before exp
83912 		                         * 2=after exp, allow '+' or '-'
83913 		                         * 3=after exp and exp sign
83914 		                         */
83915 		duk_small_uint_t s2n_flags;
83916 		duk_codepoint_t y, z;
83917 		duk_small_int_t s2n_radix = 10;
83918 		duk_small_uint_t pre_adv = 0;
83919 
83920 		DUK__INITBUFFER(lex_ctx);
83921 		y = DUK__L1();
83922 
83923 		if (x == DUK_ASC_0) {
83924 			z = DUK_LOWERCASE_CHAR_ASCII(y);
83925 
83926 			pre_adv = 2;  /* default for 0xNNN, 0oNNN, 0bNNN. */
83927 			if (z == DUK_ASC_LC_X) {
83928 				s2n_radix = 16;
83929 			} else if (z == DUK_ASC_LC_O) {
83930 				s2n_radix = 8;
83931 			} else if (z == DUK_ASC_LC_B) {
83932 				s2n_radix = 2;
83933 			} else {
83934 				pre_adv = 0;
83935 				if (DUK__ISDIGIT(y)) {
83936 					if (strict_mode) {
83937 						/* Reject octal like \07 but also octal-lookalike
83938 						 * decimal like \08 in strict mode.
83939 						 */
83940 						goto fail_number_literal;
83941 					} else {
83942 						/* Legacy OctalIntegerLiteral or octal-lookalice
83943 						 * decimal.  Deciding between the two happens below
83944 						 * in digit scanning.
83945 						 */
83946 						DUK__APPENDBUFFER(lex_ctx, x);
83947 						pre_adv = 1;
83948 						legacy_oct = 1;
83949 						s2n_radix = 8;  /* tentative unless conflicting digits found */
83950 					}
83951 				}
83952 			}
83953 		}
83954 
83955 		DUK__ADVANCECHARS(lex_ctx, pre_adv);
83956 
83957 		/* XXX: we could parse integers here directly, and fall back
83958 		 * to numconv only when encountering a fractional expression
83959 		 * or when an octal literal turned out to be decimal (0778 etc).
83960 		 */
83961 		state = 0;
83962 		for (;;) {
83963 			x = DUK__L0();  /* re-lookup curr char on first round */
83964 			if (DUK__ISDIGIT(x)) {
83965 				/* Note: intentionally allow leading zeroes here, as the
83966 				 * actual parser will check for them.
83967 				 */
83968 				if (state == 0 && legacy_oct && (x == DUK_ASC_8 || x == DUK_ASC_9)) {
83969 					/* Started out as an octal-lookalike
83970 					 * but interpreted as decimal, e.g.
83971 					 * '0779' -> 779.  This also means
83972 					 * that fractions are allowed, e.g.
83973 					 * '0779.123' is allowed but '0777.123'
83974 					 * is not!
83975 					 */
83976 					s2n_radix = 10;
83977 				}
83978 				if (state == 2) {
83979 					state = 3;
83980 				}
83981 			} else if (s2n_radix == 16 && DUK__ISHEXDIGIT(x)) {
83982 				/* Note: 'e' and 'E' are also accepted here. */
83983 				;
83984 			} else if (x == DUK_ASC_PERIOD) {
83985 				if (state >= 1 || s2n_radix != 10) {
83986 					break;
83987 				} else {
83988 					state = 1;
83989 				}
83990 			} else if (x == DUK_ASC_LC_E || x == DUK_ASC_UC_E) {
83991 				if (state >= 2 || s2n_radix != 10) {
83992 					break;
83993 				} else {
83994 					state = 2;
83995 				}
83996 			} else if (x == DUK_ASC_MINUS || x == DUK_ASC_PLUS) {
83997 				if (state != 2) {
83998 					break;
83999 				} else {
84000 					state = 3;
84001 				}
84002 			} else {
84003 				break;
84004 			}
84005 			DUK__APPENDBUFFER(lex_ctx, x);
84006 			DUK__ADVANCECHARS(lex_ctx, 1);
84007 		}
84008 
84009 		/* XXX: better coercion */
84010 		(void) duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
84011 
84012 		if (s2n_radix != 10) {
84013 			/* For bases other than 10, integer only. */
84014 			s2n_flags = DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
84015 		} else {
84016 			s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
84017 			            DUK_S2N_FLAG_ALLOW_FRAC |
84018 			            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
84019 			            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
84020 			            DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
84021 		}
84022 
84023 		duk_dup(lex_ctx->thr, lex_ctx->slot1_idx);
84024 		duk_numconv_parse(lex_ctx->thr, s2n_radix, s2n_flags);
84025 		val = duk_to_number_m1(lex_ctx->thr);
84026 		if (DUK_ISNAN(val)) {
84027 			goto fail_number_literal;
84028 		}
84029 		duk_replace(lex_ctx->thr, lex_ctx->slot1_idx);  /* could also just pop? */
84030 
84031 		DUK__INITBUFFER(lex_ctx);  /* free some memory */
84032 
84033 		/* Section 7.8.3 (note): NumericLiteral must be followed by something other than
84034 		 * IdentifierStart or DecimalDigit.
84035 		 */
84036 
84037 		if (DUK__ISDIGIT(DUK__L0()) || duk_unicode_is_identifier_start(DUK__L0())) {
84038 			goto fail_number_literal;
84039 		}
84040 
84041 		out_token->num = val;
84042 		advtok = DUK__ADVTOK(0, DUK_TOK_NUMBER);
84043 	} else if (duk_unicode_is_whitespace(DUK__LOOKUP(lex_ctx, 0))) {
84044 		DUK__ADVANCECHARS(lex_ctx, 1);
84045 		goto restart;
84046 	} else if (x < 0) {
84047 		advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
84048 	} else {
84049 		goto fail_token;
84050 	}
84051  skip_slow_path:
84052 
84053 	/*
84054 	 *  Shared exit path
84055 	 */
84056 
84057 	DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
84058 	out_token->t = advtok & 0xff;
84059 	if (out_token->t_nores == DUK_TOK_INVALID) {
84060 		out_token->t_nores = out_token->t;
84061 	}
84062 	out_token->lineterm = got_lineterm;
84063 
84064 	/* Automatic semicolon insertion is allowed if a token is preceded
84065 	 * by line terminator(s), or terminates a statement list (right curly
84066 	 * or EOF).
84067 	 */
84068 	if (got_lineterm || out_token->t == DUK_TOK_RCURLY || out_token->t == DUK_TOK_EOF) {
84069 		out_token->allow_auto_semi = 1;
84070 	} else {
84071 		out_token->allow_auto_semi = 0;
84072 	}
84073 
84074 	return;
84075 
84076  fail_token_limit:
84077 	DUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT);
84078 	DUK_WO_NORETURN(return;);
84079 
84080  fail_token:
84081 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_TOKEN);
84082 	DUK_WO_NORETURN(return;);
84083 
84084  fail_number_literal:
84085 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_NUMBER_LITERAL);
84086 	DUK_WO_NORETURN(return;);
84087 
84088  fail_escape:
84089 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
84090 	DUK_WO_NORETURN(return;);
84091 
84092  fail_unterm_regexp:
84093 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_REGEXP);
84094 	DUK_WO_NORETURN(return;);
84095 
84096  fail_unterm_comment:
84097 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_COMMENT);
84098 	DUK_WO_NORETURN(return;);
84099 
84100 #if !defined(DUK_USE_REGEXP_SUPPORT)
84101  fail_regexp_support:
84102 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_REGEXP_SUPPORT_DISABLED);
84103 	DUK_WO_NORETURN(return;);
84104 #endif
84105 }
84106 
84107 #if defined(DUK_USE_REGEXP_SUPPORT)
84108 
84109 /*
84110  *  Parse a RegExp token.  The grammar is described in E5 Section 15.10.
84111  *  Terminal constructions (such as quantifiers) are parsed directly here.
84112  *
84113  *  0xffffffffU is used as a marker for "infinity" in quantifiers.  Further,
84114  *  DUK__MAX_RE_QUANT_DIGITS limits the maximum number of digits that
84115  *  will be accepted for a quantifier.
84116  */
84117 
84118 DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
84119 	duk_small_uint_t advtok = 0;  /* init is unnecessary but suppresses "may be used uninitialized" warnings */
84120 	duk_codepoint_t x, y;
84121 
84122 	if (++lex_ctx->token_count >= lex_ctx->token_limit) {
84123 		goto fail_token_limit;
84124 	}
84125 
84126 	duk_memzero(out_token, sizeof(*out_token));
84127 
84128 	x = DUK__L0();
84129 	y = DUK__L1();
84130 
84131 	DUK_DDD(DUK_DDDPRINT("parsing regexp token, L0=%ld, L1=%ld", (long) x, (long) y));
84132 
84133 	switch (x) {
84134 	case DUK_ASC_PIPE: {
84135 		advtok = DUK__ADVTOK(1, DUK_RETOK_DISJUNCTION);
84136 		break;
84137 	}
84138 	case DUK_ASC_CARET: {
84139 		advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_START);
84140 		break;
84141 	}
84142 	case DUK_ASC_DOLLAR: {
84143 		advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_END);
84144 		break;
84145 	}
84146 	case DUK_ASC_QUESTION: {
84147 		out_token->qmin = 0;
84148 		out_token->qmax = 1;
84149 		if (y == DUK_ASC_QUESTION) {
84150 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
84151 			out_token->greedy = 0;
84152 		} else {
84153 			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
84154 			out_token->greedy = 1;
84155 		}
84156 		break;
84157 	}
84158 	case DUK_ASC_STAR: {
84159 		out_token->qmin = 0;
84160 		out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
84161 		if (y == DUK_ASC_QUESTION) {
84162 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
84163 			out_token->greedy = 0;
84164 		} else {
84165 			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
84166 			out_token->greedy = 1;
84167 		}
84168 		break;
84169 	}
84170 	case DUK_ASC_PLUS: {
84171 		out_token->qmin = 1;
84172 		out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
84173 		if (y == DUK_ASC_QUESTION) {
84174 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
84175 			out_token->greedy = 0;
84176 		} else {
84177 			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
84178 			out_token->greedy = 1;
84179 		}
84180 		break;
84181 	}
84182 	case DUK_ASC_LCURLY: {
84183 		/* Production allows 'DecimalDigits', including leading zeroes */
84184 		duk_uint32_t val1 = 0;
84185 		duk_uint32_t val2 = DUK_RE_QUANTIFIER_INFINITE;
84186 		duk_small_int_t digits = 0;
84187 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
84188 		duk_lexer_point lex_pt;
84189 #endif
84190 
84191 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
84192 		/* Store lexer position, restoring if quantifier is invalid. */
84193 		DUK_LEXER_GETPOINT(lex_ctx, &lex_pt);
84194 #endif
84195 
84196 		for (;;) {
84197 			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat '{' on entry */
84198 			x = DUK__L0();
84199 			if (DUK__ISDIGIT(x)) {
84200 				digits++;
84201 				val1 = val1 * 10 + (duk_uint32_t) duk__hexval(x);
84202 			} else if (x == DUK_ASC_COMMA) {
84203 				if (digits > DUK__MAX_RE_QUANT_DIGITS) {
84204 					goto invalid_quantifier;
84205 				}
84206 				if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
84207 					goto invalid_quantifier;
84208 				}
84209 				if (DUK__L1() == DUK_ASC_RCURLY) {
84210 					/* form: { DecimalDigits , }, val1 = min count */
84211 					if (digits == 0) {
84212 						goto invalid_quantifier;
84213 					}
84214 					out_token->qmin = val1;
84215 					out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
84216 					DUK__ADVANCECHARS(lex_ctx, 2);
84217 					break;
84218 				}
84219 				val2 = val1;
84220 				val1 = 0;
84221 				digits = 0;  /* not strictly necessary because of lookahead '}' above */
84222 			} else if (x == DUK_ASC_RCURLY) {
84223 				if (digits > DUK__MAX_RE_QUANT_DIGITS) {
84224 					goto invalid_quantifier;
84225 				}
84226 				if (digits == 0) {
84227 					goto invalid_quantifier;
84228 				}
84229 				if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
84230 					/* val2 = min count, val1 = max count */
84231 					out_token->qmin = val2;
84232 					out_token->qmax = val1;
84233 				} else {
84234 					/* val1 = count */
84235 					out_token->qmin = val1;
84236 					out_token->qmax = val1;
84237 				}
84238 				DUK__ADVANCECHARS(lex_ctx, 1);
84239 				break;
84240 			} else {
84241 				goto invalid_quantifier;
84242 			}
84243 		}
84244 		if (DUK__L0() == DUK_ASC_QUESTION) {
84245 			out_token->greedy = 0;
84246 			DUK__ADVANCECHARS(lex_ctx, 1);
84247 		} else {
84248 			out_token->greedy = 1;
84249 		}
84250 		advtok = DUK__ADVTOK(0, DUK_RETOK_QUANTIFIER);
84251 		break;
84252  invalid_quantifier:
84253 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
84254 		/* Failed to match the quantifier, restore lexer and parse
84255 		 * opening brace as a literal.
84256 		 */
84257 		DUK_LEXER_SETPOINT(lex_ctx, &lex_pt);
84258 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
84259 		out_token->num = DUK_ASC_LCURLY;
84260 #else
84261 		goto fail_quantifier;
84262 #endif
84263 		break;
84264 	}
84265 	case DUK_ASC_PERIOD: {
84266 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_PERIOD);
84267 		break;
84268 	}
84269 	case DUK_ASC_BACKSLASH: {
84270 		/* The E5.1 specification does not seem to allow IdentifierPart characters
84271 		 * to be used as identity escapes.  Unfortunately this includes '$', which
84272 		 * cannot be escaped as '\$'; it needs to be escaped e.g. as '\u0024'.
84273 		 * Many other implementations (including V8 and Rhino, for instance) do
84274 		 * accept '\$' as a valid identity escape, which is quite pragmatic, and
84275 		 * ES2015 Annex B relaxes the rules to allow these (and other) real world forms.
84276 		 */
84277 
84278 		advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);  /* default: char escape (two chars) */
84279 		if (y == DUK_ASC_LC_B) {
84280 			advtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_WORD_BOUNDARY);
84281 		} else if (y == DUK_ASC_UC_B) {
84282 			advtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY);
84283 		} else if (y == DUK_ASC_LC_F) {
84284 			out_token->num = 0x000c;
84285 		} else if (y == DUK_ASC_LC_N) {
84286 			out_token->num = 0x000a;
84287 		} else if (y == DUK_ASC_LC_T) {
84288 			out_token->num = 0x0009;
84289 		} else if (y == DUK_ASC_LC_R) {
84290 			out_token->num = 0x000d;
84291 		} else if (y == DUK_ASC_LC_V) {
84292 			out_token->num = 0x000b;
84293 		} else if (y == DUK_ASC_LC_C) {
84294 			x = DUK__L2();
84295 			if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) ||
84296 			    (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
84297 				out_token->num = (duk_uint32_t) (x % 32);
84298 				advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_CHAR);
84299 			} else {
84300 				goto fail_escape;
84301 			}
84302 		} else if (y == DUK_ASC_LC_X || y == DUK_ASC_LC_U) {
84303 			/* The token value is the Unicode codepoint without
84304 			 * it being decode into surrogate pair characters
84305 			 * here.  The \u{H+} is only allowed in Unicode mode
84306 			 * which we don't support yet.
84307 			 */
84308 			out_token->num = (duk_uint32_t) duk__lexer_parse_escape(lex_ctx, 0 /*allow_es6*/);
84309 			advtok = DUK__ADVTOK(0, DUK_RETOK_ATOM_CHAR);
84310 		} else if (y == DUK_ASC_LC_D) {
84311 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_DIGIT);
84312 		} else if (y == DUK_ASC_UC_D) {
84313 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_DIGIT);
84314 		} else if (y == DUK_ASC_LC_S) {
84315 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WHITE);
84316 		} else if (y == DUK_ASC_UC_S) {
84317 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_WHITE);
84318 		} else if (y == DUK_ASC_LC_W) {
84319 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WORD_CHAR);
84320 		} else if (y == DUK_ASC_UC_W) {
84321 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_WORD_CHAR);
84322 		} else if (DUK__ISDIGIT(y)) {
84323 			/* E5 Section 15.10.2.11 */
84324 			if (y == DUK_ASC_0) {
84325 				if (DUK__ISDIGIT(DUK__L2())) {
84326 					goto fail_escape;
84327 				}
84328 				out_token->num = 0x0000;
84329 				advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);
84330 			} else {
84331 				/* XXX: shared parsing? */
84332 				duk_uint32_t val = 0;
84333 				duk_small_int_t i;
84334 				for (i = 0; ; i++) {
84335 					if (i >= DUK__MAX_RE_DECESC_DIGITS) {
84336 						goto fail_escape;
84337 					}
84338 					DUK__ADVANCECHARS(lex_ctx, 1);  /* eat backslash on entry */
84339 					x = DUK__L0();
84340 					if (!DUK__ISDIGIT(x)) {
84341 						break;
84342 					}
84343 					val = val * 10 + (duk_uint32_t) duk__hexval(x);
84344 				}
84345 				/* DUK__L0() cannot be a digit, because the loop doesn't terminate if it is */
84346 				advtok = DUK__ADVTOK(0, DUK_RETOK_ATOM_BACKREFERENCE);
84347 				out_token->num = val;
84348 			}
84349 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
84350 		} else if (y >= 0) {
84351 			/* For ES2015 Annex B, accept any source character as identity
84352 			 * escape except 'c' which is used for control characters.
84353 			 * http://www.ecma-international.org/ecma-262/6.0/#sec-regular-expressions-patterns
84354 			 * Careful not to match end-of-buffer (<0) here.
84355 			 * This is not yet full ES2015 Annex B because cases above
84356 			 * (like hex escape) won't backtrack.
84357 			 */
84358 			DUK_ASSERT(y != DUK_ASC_LC_C);  /* covered above */
84359 #else  /* DUK_USE_ES6_REGEXP_SYNTAX */
84360 		} else if ((y >= 0 && !duk_unicode_is_identifier_part(y)) ||
84361 		           y == DUK_UNICODE_CP_ZWNJ ||
84362 		           y == DUK_UNICODE_CP_ZWJ) {
84363 			/* For ES5.1 identity escapes are not allowed for identifier
84364 			 * parts.  This conflicts with a lot of real world code as this
84365 			 * doesn't e.g. allow escaping a dollar sign as /\$/, see
84366 			 * test-regexp-identity-escape-dollar.js.
84367 			 */
84368 #endif  /* DUK_USE_ES6_REGEXP_SYNTAX */
84369 			out_token->num = (duk_uint32_t) y;
84370 		} else {
84371 			goto fail_escape;
84372 		}
84373 		break;
84374 	}
84375 	case DUK_ASC_LPAREN: {
84376 		/* XXX: naming is inconsistent: ATOM_END_GROUP ends an ASSERT_START_LOOKAHEAD */
84377 
84378 		if (y == DUK_ASC_QUESTION) {
84379 			if (DUK__L2() == DUK_ASC_EQUALS) {
84380 				/* (?= */
84381 				advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_POS_LOOKAHEAD);
84382 			} else if (DUK__L2() == DUK_ASC_EXCLAMATION) {
84383 				/* (?! */
84384 				advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD);
84385 			} else if (DUK__L2() == DUK_ASC_COLON) {
84386 				/* (?: */
84387 				advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_START_NONCAPTURE_GROUP);
84388 			} else {
84389 				goto fail_group;
84390 			}
84391 		} else {
84392 			/* ( */
84393 			advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CAPTURE_GROUP);
84394 		}
84395 		break;
84396 	}
84397 	case DUK_ASC_RPAREN: {
84398 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_END_GROUP);
84399 		break;
84400 	}
84401 	case DUK_ASC_LBRACKET: {
84402 		/*
84403 		 *  To avoid creating a heavy intermediate value for the list of ranges,
84404 		 *  only the start token ('[' or '[^') is parsed here.  The regexp
84405 		 *  compiler parses the ranges itself.
84406 		 */
84407 
84408 		/* XXX: with DUK_USE_ES6_REGEXP_SYNTAX we should allow left bracket
84409 		 * literal too, but it's not easy to parse without backtracking.
84410 		 */
84411 
84412 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CHARCLASS);
84413 		if (y == DUK_ASC_CARET) {
84414 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_START_CHARCLASS_INVERTED);
84415 		}
84416 		break;
84417 	}
84418 #if !defined(DUK_USE_ES6_REGEXP_SYNTAX)
84419 	case DUK_ASC_RCURLY:
84420 	case DUK_ASC_RBRACKET: {
84421 		/* Although these could be parsed as PatternCharacters unambiguously (here),
84422 		 * E5 Section 15.10.1 grammar explicitly forbids these as PatternCharacters.
84423 		 */
84424 		goto fail_invalid_char;
84425 		break;
84426 	}
84427 #endif
84428 	case -1: {
84429 		/* EOF */
84430 		advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
84431 		break;
84432 	}
84433 	default: {
84434 		/* PatternCharacter, all excluded characters are matched by cases above */
84435 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
84436 		out_token->num = (duk_uint32_t) x;
84437 		break;
84438 	}
84439 	}
84440 
84441 	/*
84442 	 *  Shared exit path
84443 	 */
84444 
84445 	DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
84446 	out_token->t = advtok & 0xff;
84447 	return;
84448 
84449  fail_token_limit:
84450 	DUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT);
84451 	DUK_WO_NORETURN(return;);
84452 
84453  fail_escape:
84454 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE);
84455 	DUK_WO_NORETURN(return;);
84456 
84457  fail_group:
84458 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_GROUP);
84459 	DUK_WO_NORETURN(return;);
84460 
84461 #if !defined(DUK_USE_ES6_REGEXP_SYNTAX)
84462  fail_invalid_char:
84463 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_CHARACTER);
84464 	DUK_WO_NORETURN(return;);
84465 
84466  fail_quantifier:
84467 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_QUANTIFIER);
84468 	DUK_WO_NORETURN(return;);
84469 #endif
84470 }
84471 
84472 /*
84473  *  Special parser for character classes; calls callback for every
84474  *  range parsed and returns the number of ranges present.
84475  */
84476 
84477 /* XXX: this duplicates functionality in duk_regexp.c where a similar loop is
84478  * required anyway.  We could use that BUT we need to update the regexp compiler
84479  * 'nranges' too.  Work this out a bit more cleanly to save space.
84480  */
84481 
84482 /* XXX: the handling of character range detection is a bit convoluted.
84483  * Try to simplify and make smaller.
84484  */
84485 
84486 /* XXX: logic for handling character ranges is now incorrect, it will accept
84487  * e.g. [\d-z] whereas it should croak from it?  SMJS accepts this too, though.
84488  *
84489  * Needs a read through and a lot of additional tests.
84490  */
84491 
84492 DUK_LOCAL
84493 void duk__emit_u16_direct_ranges(duk_lexer_ctx *lex_ctx,
84494                                  duk_re_range_callback gen_range,
84495                                  void *userdata,
84496                                  const duk_uint16_t *ranges,
84497                                  duk_small_int_t num) {
84498 	const duk_uint16_t *ranges_end;
84499 
84500 	DUK_UNREF(lex_ctx);
84501 
84502 	ranges_end = ranges + num;
84503 	while (ranges < ranges_end) {
84504 		/* mark range 'direct', bypass canonicalization (see Wiki) */
84505 		gen_range(userdata, (duk_codepoint_t) ranges[0], (duk_codepoint_t) ranges[1], 1);
84506 		ranges += 2;
84507 	}
84508 }
84509 
84510 DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata) {
84511 	duk_codepoint_t start = -1;
84512 	duk_codepoint_t ch;
84513 	duk_codepoint_t x;
84514 	duk_bool_t dash = 0;
84515 	duk_small_uint_t adv = 0;
84516 
84517 	DUK_DD(DUK_DDPRINT("parsing regexp ranges"));
84518 
84519 	for (;;) {
84520 		DUK__ADVANCECHARS(lex_ctx, adv);
84521 		adv = 1;
84522 
84523 		x = DUK__L0();
84524 
84525 		ch = -1;  /* not strictly necessary, but avoids "uninitialized variable" warnings */
84526 		DUK_UNREF(ch);
84527 
84528 		if (x < 0) {
84529 			goto fail_unterm_charclass;
84530 		} else if (x == DUK_ASC_RBRACKET) {
84531 			if (start >= 0) {
84532 				gen_range(userdata, start, start, 0);
84533 			}
84534 			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat ']' before finishing */
84535 			break;
84536 		} else if (x == DUK_ASC_MINUS) {
84537 			if (start >= 0 && !dash && DUK__L1() != DUK_ASC_RBRACKET) {
84538 				/* '-' as a range indicator */
84539 				dash = 1;
84540 				continue;
84541 			} else {
84542 				/* '-' verbatim */
84543 				ch = x;
84544 			}
84545 		} else if (x == DUK_ASC_BACKSLASH) {
84546 			/*
84547 			 *  The escapes are same as outside a character class, except that \b has a
84548 			 *  different meaning, and \B and backreferences are prohibited (see E5
84549 			 *  Section 15.10.2.19).  However, it's difficult to share code because we
84550 			 *  handle e.g. "\n" very differently: here we generate a single character
84551 			 *  range for it.
84552 			 */
84553 
84554 			/* XXX: ES2015 surrogate pair handling. */
84555 
84556 			x = DUK__L1();
84557 
84558 			adv = 2;
84559 
84560 			if (x == DUK_ASC_LC_B) {
84561 				/* Note: '\b' in char class is different than outside (assertion),
84562 				 * '\B' is not allowed and is caught by the duk_unicode_is_identifier_part()
84563 				 * check below.
84564 				 */
84565 				ch = 0x0008;
84566 			} else if (x == DUK_ASC_LC_F) {
84567 				ch = 0x000c;
84568 			} else if (x == DUK_ASC_LC_N) {
84569 				ch = 0x000a;
84570 			} else if (x == DUK_ASC_LC_T) {
84571 				ch = 0x0009;
84572 			} else if (x == DUK_ASC_LC_R) {
84573 				ch = 0x000d;
84574 			} else if (x == DUK_ASC_LC_V) {
84575 				ch = 0x000b;
84576 			} else if (x == DUK_ASC_LC_C) {
84577 				x = DUK__L2();
84578 				adv = 3;
84579 				if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) ||
84580 				    (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
84581 					ch = (x % 32);
84582 				} else {
84583 					goto fail_escape;
84584 				}
84585 			} else if (x == DUK_ASC_LC_X || x == DUK_ASC_LC_U) {
84586 				/* The \u{H+} form is only allowed in Unicode mode which
84587 				 * we don't support yet.
84588 				 */
84589 				ch = duk__lexer_parse_escape(lex_ctx, 0 /*allow_es6*/);
84590 				adv = 0;
84591 			} else if (x == DUK_ASC_LC_D) {
84592 				duk__emit_u16_direct_ranges(lex_ctx,
84593 				                            gen_range,
84594 				                            userdata,
84595 				                            duk_unicode_re_ranges_digit,
84596 				                            sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));
84597 				ch = -1;
84598 			} else if (x == DUK_ASC_UC_D) {
84599 				duk__emit_u16_direct_ranges(lex_ctx,
84600 				                            gen_range,
84601 				                            userdata,
84602 				                            duk_unicode_re_ranges_not_digit,
84603 				                            sizeof(duk_unicode_re_ranges_not_digit) / sizeof(duk_uint16_t));
84604 				ch = -1;
84605 			} else if (x == DUK_ASC_LC_S) {
84606 				duk__emit_u16_direct_ranges(lex_ctx,
84607 				                            gen_range,
84608 				                            userdata,
84609 				                            duk_unicode_re_ranges_white,
84610 				                            sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));
84611 				ch = -1;
84612 			} else if (x == DUK_ASC_UC_S) {
84613 				duk__emit_u16_direct_ranges(lex_ctx,
84614 				                            gen_range,
84615 				                            userdata,
84616 				                            duk_unicode_re_ranges_not_white,
84617 				                            sizeof(duk_unicode_re_ranges_not_white) / sizeof(duk_uint16_t));
84618 				ch = -1;
84619 			} else if (x == DUK_ASC_LC_W) {
84620 				duk__emit_u16_direct_ranges(lex_ctx,
84621 				                            gen_range,
84622 				                            userdata,
84623 				                            duk_unicode_re_ranges_wordchar,
84624 				                            sizeof(duk_unicode_re_ranges_wordchar) / sizeof(duk_uint16_t));
84625 				ch = -1;
84626 			} else if (x == DUK_ASC_UC_W) {
84627 				duk__emit_u16_direct_ranges(lex_ctx,
84628 				                            gen_range,
84629 				                            userdata,
84630 				                            duk_unicode_re_ranges_not_wordchar,
84631 				                            sizeof(duk_unicode_re_ranges_not_wordchar) / sizeof(duk_uint16_t));
84632 				ch = -1;
84633 			} else if (DUK__ISDIGIT(x)) {
84634 				/* DecimalEscape, only \0 is allowed, no leading
84635 				 * zeroes are allowed.
84636 				 *
84637 				 * ES2015 Annex B also allows (maximal match) legacy
84638 				 * octal escapes up to \377 and \8 and \9 are
84639 				 * accepted as literal '8' and '9', also in strict mode.
84640 				 */
84641 
84642 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
84643 				ch = duk__lexer_parse_legacy_octal(lex_ctx, &adv, 0 /*reject_annex_b*/);
84644 				DUK_ASSERT(ch >= 0);  /* no rejections */
84645 #else
84646 				if (x == DUK_ASC_0 && !DUK__ISDIGIT(DUK__L2())) {
84647 					ch = 0x0000;
84648 				} else {
84649 					goto fail_escape;
84650 				}
84651 #endif
84652 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
84653 			} else if (x >= 0) {
84654 				/* IdentityEscape: ES2015 Annex B allows almost all
84655 				 * source characters here.  Match anything except
84656 				 * EOF here.
84657 				 */
84658 				ch = x;
84659 #else  /* DUK_USE_ES6_REGEXP_SYNTAX */
84660 			} else if (!duk_unicode_is_identifier_part(x)) {
84661 				/* IdentityEscape: ES5.1 doesn't allow identity escape
84662 				 * for identifier part characters, which conflicts with
84663 				 * some real world code.  For example, it doesn't allow
84664 				 * /[\$]/ which is awkward.
84665 				 */
84666 				ch = x;
84667 #endif  /* DUK_USE_ES6_REGEXP_SYNTAX */
84668 			} else {
84669 				goto fail_escape;
84670 			}
84671 		} else {
84672 			/* character represents itself */
84673 			ch = x;
84674 		}
84675 
84676 		/* ch is a literal character here or -1 if parsed entity was
84677 		 * an escape such as "\s".
84678 		 */
84679 
84680 		if (ch < 0) {
84681 			/* multi-character sets not allowed as part of ranges, see
84682 			 * E5 Section 15.10.2.15, abstract operation CharacterRange.
84683 			 */
84684 			if (start >= 0) {
84685 				if (dash) {
84686 					goto fail_range;
84687 				} else {
84688 					gen_range(userdata, start, start, 0);
84689 					start = -1;
84690 					/* dash is already 0 */
84691 				}
84692 			}
84693 		} else {
84694 			if (start >= 0) {
84695 				if (dash) {
84696 					if (start > ch) {
84697 						goto fail_range;
84698 					}
84699 					gen_range(userdata, start, ch, 0);
84700 					start = -1;
84701 					dash = 0;
84702 				} else {
84703 					gen_range(userdata, start, start, 0);
84704 					start = ch;
84705 					/* dash is already 0 */
84706 				}
84707 			} else {
84708 				start = ch;
84709 			}
84710 		}
84711 	}
84712 
84713 	return;
84714 
84715  fail_escape:
84716 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE);
84717 	DUK_WO_NORETURN(return;);
84718 
84719  fail_range:
84720 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_RANGE);
84721 	DUK_WO_NORETURN(return;);
84722 
84723  fail_unterm_charclass:
84724 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_CHARCLASS);
84725 	DUK_WO_NORETURN(return;);
84726 }
84727 
84728 #endif  /* DUK_USE_REGEXP_SUPPORT */
84729 
84730 /* automatic undefs */
84731 #undef DUK__ADVANCEBYTES
84732 #undef DUK__ADVANCECHARS
84733 #undef DUK__ADVTOK
84734 #undef DUK__APPENDBUFFER
84735 #undef DUK__APPENDBUFFER_ASCII
84736 #undef DUK__INITBUFFER
84737 #undef DUK__ISDIGIT
84738 #undef DUK__ISDIGIT03
84739 #undef DUK__ISDIGIT47
84740 #undef DUK__ISHEXDIGIT
84741 #undef DUK__ISOCTDIGIT
84742 #undef DUK__L0
84743 #undef DUK__L1
84744 #undef DUK__L2
84745 #undef DUK__L3
84746 #undef DUK__L4
84747 #undef DUK__L5
84748 #undef DUK__LOOKUP
84749 #undef DUK__MAX_RE_DECESC_DIGITS
84750 #undef DUK__MAX_RE_QUANT_DIGITS
84751 /*
84752  *  Number-to-string and string-to-number conversions.
84753  *
84754  *  Slow path number-to-string and string-to-number conversion is based on
84755  *  a Dragon4 variant, with fast paths for small integers.  Big integer
84756  *  arithmetic is needed for guaranteeing that the conversion is correct
84757  *  and uses a minimum number of digits.  The big number arithmetic has a
84758  *  fixed maximum size and does not require dynamic allocations.
84759  *
84760  *  See: doc/number-conversion.rst.
84761  */
84762 
84763 /* #include duk_internal.h -> already included */
84764 
84765 #define DUK__IEEE_DOUBLE_EXP_BIAS  1023
84766 #define DUK__IEEE_DOUBLE_EXP_MIN   (-1022)   /* biased exp == 0 -> denormal, exp -1022 */
84767 
84768 #define DUK__DIGITCHAR(x)  duk_lc_digits[(x)]
84769 
84770 /*
84771  *  Tables generated with util/gennumdigits.py.
84772  *
84773  *  duk__str2num_digits_for_radix indicates, for each radix, how many input
84774  *  digits should be considered significant for string-to-number conversion.
84775  *  The input is also padded to this many digits to give the Dragon4
84776  *  conversion enough (apparent) precision to work with.
84777  *
84778  *  duk__str2num_exp_limits indicates, for each radix, the radix-specific
84779  *  minimum/maximum exponent values (for a Dragon4 integer mantissa)
84780  *  below and above which the number is guaranteed to underflow to zero
84781  *  or overflow to Infinity.  This allows parsing to keep bigint values
84782  *  bounded.
84783  */
84784 
84785 DUK_LOCAL const duk_uint8_t duk__str2num_digits_for_radix[] = {
84786 	69, 44, 35, 30, 27, 25, 23, 22, 20, 20,    /* 2 to 11 */
84787 	20, 19, 19, 18, 18, 17, 17, 17, 16, 16,    /* 12 to 21 */
84788 	16, 16, 16, 15, 15, 15, 15, 15, 15, 14,    /* 22 to 31 */
84789 	14, 14, 14, 14, 14                         /* 31 to 36 */
84790 };
84791 
84792 typedef struct {
84793 	duk_int16_t upper;
84794 	duk_int16_t lower;
84795 } duk__exp_limits;
84796 
84797 DUK_LOCAL const duk__exp_limits duk__str2num_exp_limits[] = {
84798 	{ 957, -1147 }, { 605, -725 },  { 479, -575 },  { 414, -496 },
84799 	{ 372, -446 },  { 342, -411 },  { 321, -384 },  { 304, -364 },
84800 	{ 291, -346 },  { 279, -334 },  { 268, -323 },  { 260, -312 },
84801 	{ 252, -304 },  { 247, -296 },  { 240, -289 },  { 236, -283 },
84802 	{ 231, -278 },  { 227, -273 },  { 223, -267 },  { 220, -263 },
84803 	{ 216, -260 },  { 213, -256 },  { 210, -253 },  { 208, -249 },
84804 	{ 205, -246 },  { 203, -244 },  { 201, -241 },  { 198, -239 },
84805 	{ 196, -237 },  { 195, -234 },  { 193, -232 },  { 191, -230 },
84806 	{ 190, -228 },  { 188, -226 },  { 187, -225 },
84807 };
84808 
84809 /*
84810  *  Limited functionality bigint implementation.
84811  *
84812  *  Restricted to non-negative numbers with less than 32 * DUK__BI_MAX_PARTS bits,
84813  *  with the caller responsible for ensuring this is never exceeded.  No memory
84814  *  allocation (except stack) is needed for bigint computation.  Operations
84815  *  have been tailored for number conversion needs.
84816  *
84817  *  Argument order is "assignment order", i.e. target first, then arguments:
84818  *  x <- y * z  -->  duk__bi_mul(x, y, z);
84819  */
84820 
84821 /* This upper value has been experimentally determined; debug build will check
84822  * bigint size with assertions.
84823  */
84824 #define DUK__BI_MAX_PARTS  37  /* 37x32 = 1184 bits */
84825 
84826 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
84827 #define DUK__BI_PRINT(name,x)  duk__bi_print((name),(x))
84828 #else
84829 #define DUK__BI_PRINT(name,x)
84830 #endif
84831 
84832 /* Current size is about 152 bytes. */
84833 typedef struct {
84834 	duk_small_int_t n;
84835 	duk_uint32_t v[DUK__BI_MAX_PARTS];  /* low to high */
84836 } duk__bigint;
84837 
84838 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
84839 DUK_LOCAL void duk__bi_print(const char *name, duk__bigint *x) {
84840 	/* Overestimate required size; debug code so not critical to be tight. */
84841 	char buf[DUK__BI_MAX_PARTS * 9 + 64];
84842 	char *p = buf;
84843 	duk_small_int_t i;
84844 
84845 	/* No NUL term checks in this debug code. */
84846 	p += DUK_SPRINTF(p, "%p n=%ld", (void *) x, (long) x->n);
84847 	if (x->n == 0) {
84848 		p += DUK_SPRINTF(p, " 0");
84849 	}
84850 	for (i = x->n - 1; i >= 0; i--) {
84851 		p += DUK_SPRINTF(p, " %08lx", (unsigned long) x->v[i]);
84852 	}
84853 
84854 	DUK_DDD(DUK_DDDPRINT("%s: %s", (const char *) name, (const char *) buf));
84855 }
84856 #endif
84857 
84858 #if defined(DUK_USE_ASSERTIONS)
84859 DUK_LOCAL duk_small_int_t duk__bi_is_valid(duk__bigint *x) {
84860 	return (duk_small_int_t)
84861 	       ( ((x->n >= 0) && (x->n <= DUK__BI_MAX_PARTS)) /* is valid size */ &&
84862 	         ((x->n == 0) || (x->v[x->n - 1] != 0)) /* is normalized */ );
84863 }
84864 #endif
84865 
84866 DUK_LOCAL void duk__bi_normalize(duk__bigint *x) {
84867 	duk_small_int_t i;
84868 
84869 	for (i = x->n - 1; i >= 0; i--) {
84870 		if (x->v[i] != 0) {
84871 			break;
84872 		}
84873 	}
84874 
84875 	/* Note: if 'x' is zero, x->n becomes 0 here */
84876 	x->n = i + 1;
84877 	DUK_ASSERT(duk__bi_is_valid(x));
84878 }
84879 
84880 /* x <- y */
84881 DUK_LOCAL void duk__bi_copy(duk__bigint *x, duk__bigint *y) {
84882 	duk_small_int_t n;
84883 
84884 	n = y->n;
84885 	x->n = n;
84886 	/* No need to special case n == 0. */
84887 	duk_memcpy((void *) x->v, (const void *) y->v, (size_t) (sizeof(duk_uint32_t) * (size_t) n));
84888 }
84889 
84890 DUK_LOCAL void duk__bi_set_small(duk__bigint *x, duk_uint32_t v) {
84891 	if (v == 0U) {
84892 		x->n = 0;
84893 	} else {
84894 		x->n = 1;
84895 		x->v[0] = v;
84896 	}
84897 	DUK_ASSERT(duk__bi_is_valid(x));
84898 }
84899 
84900 /* Return value: <0  <=>  x < y
84901  *                0  <=>  x == y
84902  *               >0  <=>  x > y
84903  */
84904 DUK_LOCAL int duk__bi_compare(duk__bigint *x, duk__bigint *y) {
84905 	duk_small_int_t i, nx, ny;
84906 	duk_uint32_t tx, ty;
84907 
84908 	DUK_ASSERT(duk__bi_is_valid(x));
84909 	DUK_ASSERT(duk__bi_is_valid(y));
84910 
84911 	nx = x->n;
84912 	ny = y->n;
84913 	if (nx > ny) {
84914 		goto ret_gt;
84915 	}
84916 	if (nx < ny) {
84917 		goto ret_lt;
84918 	}
84919 	for (i = nx - 1; i >= 0; i--) {
84920 		tx = x->v[i];
84921 		ty = y->v[i];
84922 
84923 		if (tx > ty) {
84924 			goto ret_gt;
84925 		}
84926 		if (tx < ty) {
84927 			goto ret_lt;
84928 		}
84929 	}
84930 
84931 	return 0;
84932 
84933  ret_gt:
84934 	return 1;
84935 
84936  ret_lt:
84937 	return -1;
84938 }
84939 
84940 /* x <- y + z */
84941 #if defined(DUK_USE_64BIT_OPS)
84942 DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
84943 	duk_uint64_t tmp;
84944 	duk_small_int_t i, ny, nz;
84945 
84946 	DUK_ASSERT(duk__bi_is_valid(y));
84947 	DUK_ASSERT(duk__bi_is_valid(z));
84948 
84949 	if (z->n > y->n) {
84950 		duk__bigint *t;
84951 		t = y; y = z; z = t;
84952 	}
84953 	DUK_ASSERT(y->n >= z->n);
84954 
84955 	ny = y->n; nz = z->n;
84956 	tmp = 0U;
84957 	for (i = 0; i < ny; i++) {
84958 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
84959 		tmp += y->v[i];
84960 		if (i < nz) {
84961 			tmp += z->v[i];
84962 		}
84963 		x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
84964 		tmp = tmp >> 32;
84965 	}
84966 	if (tmp != 0U) {
84967 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
84968 		x->v[i++] = (duk_uint32_t) tmp;
84969 	}
84970 	x->n = i;
84971 	DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);
84972 
84973 	/* no need to normalize */
84974 	DUK_ASSERT(duk__bi_is_valid(x));
84975 }
84976 #else  /* DUK_USE_64BIT_OPS */
84977 DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
84978 	duk_uint32_t carry, tmp1, tmp2;
84979 	duk_small_int_t i, ny, nz;
84980 
84981 	DUK_ASSERT(duk__bi_is_valid(y));
84982 	DUK_ASSERT(duk__bi_is_valid(z));
84983 
84984 	if (z->n > y->n) {
84985 		duk__bigint *t;
84986 		t = y; y = z; z = t;
84987 	}
84988 	DUK_ASSERT(y->n >= z->n);
84989 
84990 	ny = y->n; nz = z->n;
84991 	carry = 0U;
84992 	for (i = 0; i < ny; i++) {
84993 		/* Carry is detected based on wrapping which relies on exact 32-bit
84994 		 * types.
84995 		 */
84996 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
84997 		tmp1 = y->v[i];
84998 		tmp2 = tmp1;
84999 		if (i < nz) {
85000 			tmp2 += z->v[i];
85001 		}
85002 
85003 		/* Careful with carry condition:
85004 		 *  - If carry not added: 0x12345678 + 0 + 0xffffffff = 0x12345677 (< 0x12345678)
85005 		 *  - If carry added:     0x12345678 + 1 + 0xffffffff = 0x12345678 (== 0x12345678)
85006 		 */
85007 		if (carry) {
85008 			tmp2++;
85009 			carry = (tmp2 <= tmp1 ? 1U : 0U);
85010 		} else {
85011 			carry = (tmp2 < tmp1 ? 1U : 0U);
85012 		}
85013 
85014 		x->v[i] = tmp2;
85015 	}
85016 	if (carry) {
85017 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
85018 		DUK_ASSERT(carry == 1U);
85019 		x->v[i++] = carry;
85020 	}
85021 	x->n = i;
85022 	DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);
85023 
85024 	/* no need to normalize */
85025 	DUK_ASSERT(duk__bi_is_valid(x));
85026 }
85027 #endif  /* DUK_USE_64BIT_OPS */
85028 
85029 /* x <- y + z */
85030 DUK_LOCAL void duk__bi_add_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
85031 	duk__bigint tmp;
85032 
85033 	DUK_ASSERT(duk__bi_is_valid(y));
85034 
85035 	/* XXX: this could be optimized; there is only one call site now though */
85036 	duk__bi_set_small(&tmp, z);
85037 	duk__bi_add(x, y, &tmp);
85038 
85039 	DUK_ASSERT(duk__bi_is_valid(x));
85040 }
85041 
85042 #if 0  /* unused */
85043 /* x <- x + y, use t as temp */
85044 DUK_LOCAL void duk__bi_add_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
85045 	duk__bi_add(t, x, y);
85046 	duk__bi_copy(x, t);
85047 }
85048 #endif
85049 
85050 /* x <- y - z, require x >= y => z >= 0, i.e. y >= z */
85051 #if defined(DUK_USE_64BIT_OPS)
85052 DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
85053 	duk_small_int_t i, ny, nz;
85054 	duk_uint32_t ty, tz;
85055 	duk_int64_t tmp;
85056 
85057 	DUK_ASSERT(duk__bi_is_valid(y));
85058 	DUK_ASSERT(duk__bi_is_valid(z));
85059 	DUK_ASSERT(duk__bi_compare(y, z) >= 0);
85060 	DUK_ASSERT(y->n >= z->n);
85061 
85062 	ny = y->n; nz = z->n;
85063 	tmp = 0;
85064 	for (i = 0; i < ny; i++) {
85065 		ty = y->v[i];
85066 		if (i < nz) {
85067 			tz = z->v[i];
85068 		} else {
85069 			tz = 0;
85070 		}
85071 		tmp = (duk_int64_t) ty - (duk_int64_t) tz + tmp;
85072 		x->v[i] = (duk_uint32_t) ((duk_uint64_t) tmp & 0xffffffffUL);
85073 		tmp = tmp >> 32;  /* 0 or -1 */
85074 	}
85075 	DUK_ASSERT(tmp == 0);
85076 
85077 	x->n = i;
85078 	duk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */
85079 	DUK_ASSERT(duk__bi_is_valid(x));
85080 }
85081 #else
85082 DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
85083 	duk_small_int_t i, ny, nz;
85084 	duk_uint32_t tmp1, tmp2, borrow;
85085 
85086 	DUK_ASSERT(duk__bi_is_valid(y));
85087 	DUK_ASSERT(duk__bi_is_valid(z));
85088 	DUK_ASSERT(duk__bi_compare(y, z) >= 0);
85089 	DUK_ASSERT(y->n >= z->n);
85090 
85091 	ny = y->n; nz = z->n;
85092 	borrow = 0U;
85093 	for (i = 0; i < ny; i++) {
85094 		/* Borrow is detected based on wrapping which relies on exact 32-bit
85095 		 * types.
85096 		 */
85097 		tmp1 = y->v[i];
85098 		tmp2 = tmp1;
85099 		if (i < nz) {
85100 			tmp2 -= z->v[i];
85101 		}
85102 
85103 		/* Careful with borrow condition:
85104 		 *  - If borrow not subtracted: 0x12345678 - 0 - 0xffffffff = 0x12345679 (> 0x12345678)
85105 		 *  - If borrow subtracted:     0x12345678 - 1 - 0xffffffff = 0x12345678 (== 0x12345678)
85106 		 */
85107 		if (borrow) {
85108 			tmp2--;
85109 			borrow = (tmp2 >= tmp1 ? 1U : 0U);
85110 		} else {
85111 			borrow = (tmp2 > tmp1 ? 1U : 0U);
85112 		}
85113 
85114 		x->v[i] = tmp2;
85115 	}
85116 	DUK_ASSERT(borrow == 0U);
85117 
85118 	x->n = i;
85119 	duk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */
85120 	DUK_ASSERT(duk__bi_is_valid(x));
85121 }
85122 #endif
85123 
85124 #if 0  /* unused */
85125 /* x <- y - z */
85126 DUK_LOCAL void duk__bi_sub_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
85127 	duk__bigint tmp;
85128 
85129 	DUK_ASSERT(duk__bi_is_valid(y));
85130 
85131 	/* XXX: this could be optimized */
85132 	duk__bi_set_small(&tmp, z);
85133 	duk__bi_sub(x, y, &tmp);
85134 
85135 	DUK_ASSERT(duk__bi_is_valid(x));
85136 }
85137 #endif
85138 
85139 /* x <- x - y, use t as temp */
85140 DUK_LOCAL void duk__bi_sub_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
85141 	duk__bi_sub(t, x, y);
85142 	duk__bi_copy(x, t);
85143 }
85144 
85145 /* x <- y * z */
85146 DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
85147 	duk_small_int_t i, j, nx, nz;
85148 
85149 	DUK_ASSERT(duk__bi_is_valid(y));
85150 	DUK_ASSERT(duk__bi_is_valid(z));
85151 
85152 	nx = y->n + z->n;  /* max possible */
85153 	DUK_ASSERT(nx <= DUK__BI_MAX_PARTS);
85154 
85155 	if (nx == 0) {
85156 		/* Both inputs are zero; cases where only one is zero can go
85157 		 * through main algorithm.
85158 		 */
85159 		x->n = 0;
85160 		return;
85161 	}
85162 
85163 	duk_memzero((void *) x->v, (size_t) (sizeof(duk_uint32_t) * (size_t) nx));
85164 	x->n = nx;
85165 
85166 	nz = z->n;
85167 	for (i = 0; i < y->n; i++) {
85168 #if defined(DUK_USE_64BIT_OPS)
85169 		duk_uint64_t tmp = 0U;
85170 		for (j = 0; j < nz; j++) {
85171 			tmp += (duk_uint64_t) y->v[i] * (duk_uint64_t) z->v[j] + x->v[i+j];
85172 			x->v[i+j] = (duk_uint32_t) (tmp & 0xffffffffUL);
85173 			tmp = tmp >> 32;
85174 		}
85175 		if (tmp > 0) {
85176 			DUK_ASSERT(i + j < nx);
85177 			DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
85178 			DUK_ASSERT(x->v[i+j] == 0U);
85179 			x->v[i+j] = (duk_uint32_t) tmp;
85180 		}
85181 #else
85182 		/*
85183 		 *  Multiply + add + carry for 32-bit components using only 16x16->32
85184 		 *  multiplies and carry detection based on unsigned overflow.
85185 		 *
85186 		 *    1st mult, 32-bit: (A*2^16 + B)
85187 		 *    2nd mult, 32-bit: (C*2^16 + D)
85188 		 *    3rd add, 32-bit: E
85189 		 *    4th add, 32-bit: F
85190 		 *
85191 		 *      (AC*2^16 + B) * (C*2^16 + D) + E + F
85192 		 *    = AC*2^32 + AD*2^16 + BC*2^16 + BD + E + F
85193 		 *    = AC*2^32 + (AD + BC)*2^16 + (BD + E + F)
85194 		 *    = AC*2^32 + AD*2^16 + BC*2^16 + (BD + E + F)
85195 		 */
85196 		duk_uint32_t a, b, c, d, e, f;
85197 		duk_uint32_t r, s, t;
85198 
85199 		a = y->v[i]; b = a & 0xffffUL; a = a >> 16;
85200 
85201 		f = 0;
85202 		for (j = 0; j < nz; j++) {
85203 			c = z->v[j]; d = c & 0xffffUL; c = c >> 16;
85204 			e = x->v[i+j];
85205 
85206 			/* build result as: (r << 32) + s: start with (BD + E + F) */
85207 			r = 0;
85208 			s = b * d;
85209 
85210 			/* add E */
85211 			t = s + e;
85212 			if (t < s) { r++; }  /* carry */
85213 			s = t;
85214 
85215 			/* add F */
85216 			t = s + f;
85217 			if (t < s) { r++; }  /* carry */
85218 			s = t;
85219 
85220 			/* add BC*2^16 */
85221 			t = b * c;
85222 			r += (t >> 16);
85223 			t = s + ((t & 0xffffUL) << 16);
85224 			if (t < s) { r++; }  /* carry */
85225 			s = t;
85226 
85227 			/* add AD*2^16 */
85228 			t = a * d;
85229 			r += (t >> 16);
85230 			t = s + ((t & 0xffffUL) << 16);
85231 			if (t < s) { r++; }  /* carry */
85232 			s = t;
85233 
85234 			/* add AC*2^32 */
85235 			t = a * c;
85236 			r += t;
85237 
85238 			DUK_DDD(DUK_DDDPRINT("ab=%08lx cd=%08lx ef=%08lx -> rs=%08lx %08lx",
85239 			                     (unsigned long) y->v[i], (unsigned long) z->v[j],
85240 			                     (unsigned long) x->v[i+j], (unsigned long) r,
85241 			                     (unsigned long) s));
85242 
85243 			x->v[i+j] = s;
85244 			f = r;
85245 		}
85246 		if (f > 0U) {
85247 			DUK_ASSERT(i + j < nx);
85248 			DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
85249 			DUK_ASSERT(x->v[i+j] == 0U);
85250 			x->v[i+j] = (duk_uint32_t) f;
85251 		}
85252 #endif  /* DUK_USE_64BIT_OPS */
85253 	}
85254 
85255 	duk__bi_normalize(x);
85256 	DUK_ASSERT(duk__bi_is_valid(x));
85257 }
85258 
85259 /* x <- y * z */
85260 DUK_LOCAL void duk__bi_mul_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
85261 	duk__bigint tmp;
85262 
85263 	DUK_ASSERT(duk__bi_is_valid(y));
85264 
85265 	/* XXX: this could be optimized */
85266 	duk__bi_set_small(&tmp, z);
85267 	duk__bi_mul(x, y, &tmp);
85268 
85269 	DUK_ASSERT(duk__bi_is_valid(x));
85270 }
85271 
85272 /* x <- x * y, use t as temp */
85273 DUK_LOCAL void duk__bi_mul_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
85274 	duk__bi_mul(t, x, y);
85275 	duk__bi_copy(x, t);
85276 }
85277 
85278 /* x <- x * y, use t as temp */
85279 DUK_LOCAL void duk__bi_mul_small_copy(duk__bigint *x, duk_uint32_t y, duk__bigint *t) {
85280 	duk__bi_mul_small(t, x, y);
85281 	duk__bi_copy(x, t);
85282 }
85283 
85284 DUK_LOCAL int duk__bi_is_even(duk__bigint *x) {
85285 	DUK_ASSERT(duk__bi_is_valid(x));
85286 	return (x->n == 0) || ((x->v[0] & 0x01) == 0);
85287 }
85288 
85289 DUK_LOCAL int duk__bi_is_zero(duk__bigint *x) {
85290 	DUK_ASSERT(duk__bi_is_valid(x));
85291 	return (x->n == 0);  /* this is the case for normalized numbers */
85292 }
85293 
85294 /* Bigint is 2^52.  Used to detect normalized IEEE double mantissa values
85295  * which are at the lowest edge (next floating point value downwards has
85296  * a different exponent).  The lowest mantissa has the form:
85297  *
85298  *     1000........000    (52 zeroes; only "hidden bit" is set)
85299  */
85300 DUK_LOCAL duk_small_int_t duk__bi_is_2to52(duk__bigint *x) {
85301 	DUK_ASSERT(duk__bi_is_valid(x));
85302 	return (duk_small_int_t)
85303 	        (x->n == 2) && (x->v[0] == 0U) && (x->v[1] == (1U << (52-32)));
85304 }
85305 
85306 /* x <- (1<<y) */
85307 DUK_LOCAL void duk__bi_twoexp(duk__bigint *x, duk_small_int_t y) {
85308 	duk_small_int_t n, r;
85309 
85310 	n = (y / 32) + 1;
85311 	DUK_ASSERT(n > 0);
85312 	r = y % 32;
85313 	duk_memzero((void *) x->v, sizeof(duk_uint32_t) * (size_t) n);
85314 	x->n = n;
85315 	x->v[n - 1] = (((duk_uint32_t) 1) << r);
85316 }
85317 
85318 /* x <- b^y; use t1 and t2 as temps */
85319 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) {
85320 	/* Fast path the binary case */
85321 
85322 	DUK_ASSERT(x != t1 && x != t2 && t1 != t2);  /* distinct bignums, easy mistake to make */
85323 	DUK_ASSERT(b >= 0);
85324 	DUK_ASSERT(y >= 0);
85325 
85326 	if (b == 2) {
85327 		duk__bi_twoexp(x, y);
85328 		return;
85329 	}
85330 
85331 	/* http://en.wikipedia.org/wiki/Exponentiation_by_squaring */
85332 
85333 	DUK_DDD(DUK_DDDPRINT("exp_small: b=%ld, y=%ld", (long) b, (long) y));
85334 
85335 	duk__bi_set_small(x, 1);
85336 	duk__bi_set_small(t1, (duk_uint32_t) b);
85337 	for (;;) {
85338 		/* Loop structure ensures that we don't compute t1^2 unnecessarily
85339 		 * on the final round, as that might create a bignum exceeding the
85340 		 * current DUK__BI_MAX_PARTS limit.
85341 		 */
85342 		if (y & 0x01) {
85343 			duk__bi_mul_copy(x, t1, t2);
85344 		}
85345 		y = y >> 1;
85346 		if (y == 0) {
85347 			break;
85348 		}
85349 		duk__bi_mul_copy(t1, t1, t2);
85350 	}
85351 
85352 	DUK__BI_PRINT("exp_small result", x);
85353 }
85354 
85355 /*
85356  *  A Dragon4 number-to-string variant, based on:
85357  *
85358  *    Guy L. Steele Jr., Jon L. White: "How to Print Floating-Point Numbers
85359  *    Accurately"
85360  *
85361  *    Robert G. Burger, R. Kent Dybvig: "Printing Floating-Point Numbers
85362  *    Quickly and Accurately"
85363  *
85364  *  The current algorithm is based on Figure 1 of the Burger-Dybvig paper,
85365  *  i.e. the base implementation without logarithm estimation speedups
85366  *  (these would increase code footprint considerably).  Fixed-format output
85367  *  does not follow the suggestions in the paper; instead, we generate an
85368  *  extra digit and round-with-carry.
85369  *
85370  *  The same algorithm is used for number parsing (with b=10 and B=2)
85371  *  by generating one extra digit and doing rounding manually.
85372  *
85373  *  See doc/number-conversion.rst for limitations.
85374  */
85375 
85376 /* Maximum number of digits generated. */
85377 #define DUK__MAX_OUTPUT_DIGITS          1040  /* (Number.MAX_VALUE).toString(2).length == 1024, + slack */
85378 
85379 /* Maximum number of characters in formatted value. */
85380 #define DUK__MAX_FORMATTED_LENGTH       1040  /* (-Number.MAX_VALUE).toString(2).length == 1025, + slack */
85381 
85382 /* Number and (minimum) size of bigints in the nc_ctx structure. */
85383 #define DUK__NUMCONV_CTX_NUM_BIGINTS    7
85384 #define DUK__NUMCONV_CTX_BIGINTS_SIZE   (sizeof(duk__bigint) * DUK__NUMCONV_CTX_NUM_BIGINTS)
85385 
85386 typedef struct {
85387 	/* Currently about 7*152 = 1064 bytes.  The space for these
85388 	 * duk__bigints is used also as a temporary buffer for generating
85389 	 * the final string.  This is a bit awkard; a union would be
85390 	 * more correct.
85391 	 */
85392 	duk__bigint f, r, s, mp, mm, t1, t2;
85393 
85394 	duk_small_int_t is_s2n;        /* if 1, doing a string-to-number; else doing a number-to-string */
85395 	duk_small_int_t is_fixed;      /* if 1, doing a fixed format output (not free format) */
85396 	duk_small_int_t req_digits;    /* requested number of output digits; 0 = free-format */
85397 	duk_small_int_t abs_pos;       /* digit position is absolute, not relative */
85398 	duk_small_int_t e;             /* exponent for 'f' */
85399 	duk_small_int_t b;             /* input radix */
85400 	duk_small_int_t B;             /* output radix */
85401 	duk_small_int_t k;             /* see algorithm */
85402 	duk_small_int_t low_ok;        /* see algorithm */
85403 	duk_small_int_t high_ok;       /* see algorithm */
85404 	duk_small_int_t unequal_gaps;  /* m+ != m- (very rarely) */
85405 
85406 	/* Buffer used for generated digits, values are in the range [0,B-1]. */
85407 	duk_uint8_t digits[DUK__MAX_OUTPUT_DIGITS];
85408 	duk_small_int_t count;  /* digit count */
85409 } duk__numconv_stringify_ctx;
85410 
85411 /* Note: computes with 'idx' in assertions, so caller beware.
85412  * 'idx' is preincremented, i.e. '1' on first call, because it
85413  * is more convenient for the caller.
85414  */
85415 #define DUK__DRAGON4_OUTPUT_PREINC(nc_ctx,preinc_idx,x)  do { \
85416 		DUK_ASSERT((preinc_idx) - 1 >= 0); \
85417 		DUK_ASSERT((preinc_idx) - 1 < DUK__MAX_OUTPUT_DIGITS); \
85418 		((nc_ctx)->digits[(preinc_idx) - 1]) = (duk_uint8_t) (x); \
85419 	} while (0)
85420 
85421 DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x, duk_small_int_t radix) {
85422 	duk_uint8_t *p;
85423 	duk_size_t len;
85424 	duk_small_int_t dig;
85425 	duk_uint32_t t;
85426 
85427 	DUK_ASSERT(buf != NULL);
85428 	DUK_ASSERT(radix >= 2 && radix <= 36);
85429 
85430 	/* A 32-bit unsigned integer formats to at most 32 digits (the
85431 	 * worst case happens with radix == 2).  Output the digits backwards,
85432 	 * and use a memmove() to get them in the right place.
85433 	 */
85434 
85435 	p = buf + 32;
85436 	for (;;) {
85437 		t = x / (duk_uint32_t) radix;
85438 		dig = (duk_small_int_t) (x - t * (duk_uint32_t) radix);
85439 		x = t;
85440 
85441 		DUK_ASSERT(dig >= 0 && dig < 36);
85442 		*(--p) = DUK__DIGITCHAR(dig);
85443 
85444 		if (x == 0) {
85445 			break;
85446 		}
85447 	}
85448 	len = (duk_size_t) ((buf + 32) - p);
85449 
85450 	duk_memmove((void *) buf, (const void *) p, (size_t) len);
85451 
85452 	return len;
85453 }
85454 
85455 DUK_LOCAL void duk__dragon4_prepare(duk__numconv_stringify_ctx *nc_ctx) {
85456 	duk_small_int_t lowest_mantissa;
85457 
85458 #if 1
85459 	/* Assume IEEE round-to-even, so that shorter encoding can be used
85460 	 * when round-to-even would produce correct result.  By removing
85461 	 * this check (and having low_ok == high_ok == 0) the results would
85462 	 * still be accurate but in some cases longer than necessary.
85463 	 */
85464 	if (duk__bi_is_even(&nc_ctx->f)) {
85465 		DUK_DDD(DUK_DDDPRINT("f is even"));
85466 		nc_ctx->low_ok = 1;
85467 		nc_ctx->high_ok = 1;
85468 	} else {
85469 		DUK_DDD(DUK_DDDPRINT("f is odd"));
85470 		nc_ctx->low_ok = 0;
85471 		nc_ctx->high_ok = 0;
85472 	}
85473 #else
85474 	/* Note: not honoring round-to-even should work but now generates incorrect
85475 	 * results.  For instance, 1e23 serializes to "a000...", i.e. the first digit
85476 	 * equals the radix (10).  Scaling stops one step too early in this case.
85477 	 * Don't know why this is the case, but since this code path is unused, it
85478 	 * doesn't matter.
85479 	 */
85480 	nc_ctx->low_ok = 0;
85481 	nc_ctx->high_ok = 0;
85482 #endif
85483 
85484 	/* For string-to-number, pretend we never have the lowest mantissa as there
85485 	 * is no natural "precision" for inputs.  Having lowest_mantissa == 0, we'll
85486 	 * fall into the base cases for both e >= 0 and e < 0.
85487 	 */
85488 	if (nc_ctx->is_s2n) {
85489 		lowest_mantissa = 0;
85490 	} else {
85491 		lowest_mantissa = duk__bi_is_2to52(&nc_ctx->f);
85492 	}
85493 
85494 	nc_ctx->unequal_gaps = 0;
85495 	if (nc_ctx->e >= 0) {
85496 		/* exponent non-negative (and thus not minimum exponent) */
85497 
85498 		if (lowest_mantissa) {
85499 			/* (>= e 0) AND (= f (expt b (- p 1)))
85500 			 *
85501 			 * be <- (expt b e) == b^e
85502 			 * be1 <- (* be b) == (expt b (+ e 1)) == b^(e+1)
85503 			 * r <- (* f be1 2) == 2 * f * b^(e+1)    [if b==2 -> f * b^(e+2)]
85504 			 * s <- (* b 2)                           [if b==2 -> 4]
85505 			 * m+ <- be1 == b^(e+1)
85506 			 * m- <- be == b^e
85507 			 * k <- 0
85508 			 * B <- B
85509 			 * low_ok <- round
85510 			 * high_ok <- round
85511 			 */
85512 
85513 			DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
85514 			                     "lowest mantissa value for this exponent -> "
85515 			                     "unequal gaps"));
85516 
85517 			duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */
85518 			duk__bi_mul_small(&nc_ctx->mp, &nc_ctx->mm, (duk_uint32_t) nc_ctx->b);           /* mp <- b^(e+1) */
85519 			duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
85520 			duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);              /* r <- (2 * f) * b^(e+1) */
85521 			duk__bi_set_small(&nc_ctx->s, (duk_uint32_t) (nc_ctx->b * 2));  /* s <- 2 * b */
85522 			nc_ctx->unequal_gaps = 1;
85523 		} else {
85524 			/* (>= e 0) AND (not (= f (expt b (- p 1))))
85525 			 *
85526 			 * be <- (expt b e) == b^e
85527 			 * r <- (* f be 2) == 2 * f * b^e    [if b==2 -> f * b^(e+1)]
85528 			 * s <- 2
85529 			 * m+ <- be == b^e
85530 			 * m- <- be == b^e
85531 			 * k <- 0
85532 			 * B <- B
85533 			 * low_ok <- round
85534 			 * high_ok <- round
85535 			 */
85536 
85537 			DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
85538 			                     "not lowest mantissa for this exponent -> "
85539 			                     "equal gaps"));
85540 
85541 			duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */
85542 			duk__bi_copy(&nc_ctx->mp, &nc_ctx->mm);                /* mp <- b^e */
85543 			duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
85544 			duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);     /* r <- (2 * f) * b^e */
85545 			duk__bi_set_small(&nc_ctx->s, 2);                      /* s <- 2 */
85546 		}
85547 	} else {
85548 		/* When doing string-to-number, lowest_mantissa is always 0 so
85549 		 * the exponent check, while incorrect, won't matter.
85550 		 */
85551 		if (nc_ctx->e > DUK__IEEE_DOUBLE_EXP_MIN /*not minimum exponent*/ &&
85552 		    lowest_mantissa /* lowest mantissa for this exponent*/) {
85553 			/* r <- (* f b 2)                                [if b==2 -> (* f 4)]
85554 			 * s <- (* (expt b (- 1 e)) 2) == b^(1-e) * 2    [if b==2 -> b^(2-e)]
85555 			 * m+ <- b == 2
85556 			 * m- <- 1
85557 			 * k <- 0
85558 			 * B <- B
85559 			 * low_ok <- round
85560 			 * high_ok <- round
85561 			 */
85562 
85563 			DUK_DDD(DUK_DDDPRINT("negative exponent; not minimum exponent and "
85564 			                     "lowest mantissa for this exponent -> "
85565 			                     "unequal gaps"));
85566 
85567 			duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, (duk_uint32_t) (nc_ctx->b * 2));  /* r <- (2 * b) * f */
85568 			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 */
85569 			duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);             /* s <- b^(1-e) * 2 */
85570 			duk__bi_set_small(&nc_ctx->mp, 2);
85571 			duk__bi_set_small(&nc_ctx->mm, 1);
85572 			nc_ctx->unequal_gaps = 1;
85573 		} else {
85574 			/* r <- (* f 2)
85575 			 * s <- (* (expt b (- e)) 2) == b^(-e) * 2    [if b==2 -> b^(1-e)]
85576 			 * m+ <- 1
85577 			 * m- <- 1
85578 			 * k <- 0
85579 			 * B <- B
85580 			 * low_ok <- round
85581 			 * high_ok <- round
85582 			 */
85583 
85584 			DUK_DDD(DUK_DDDPRINT("negative exponent; minimum exponent or not "
85585 			                     "lowest mantissa for this exponent -> "
85586 			                     "equal gaps"));
85587 
85588 			duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, 2);            /* r <- 2 * f */
85589 			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 */
85590 			duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);           /* s <- b^(-e) * 2 */
85591 			duk__bi_set_small(&nc_ctx->mp, 1);
85592 			duk__bi_set_small(&nc_ctx->mm, 1);
85593 		}
85594 	}
85595 }
85596 
85597 DUK_LOCAL void duk__dragon4_scale(duk__numconv_stringify_ctx *nc_ctx) {
85598 	duk_small_int_t k = 0;
85599 
85600 	/* This is essentially the 'scale' algorithm, with recursion removed.
85601 	 * Note that 'k' is either correct immediately, or will move in one
85602 	 * direction in the loop.  There's no need to do the low/high checks
85603 	 * on every round (like the Scheme algorithm does).
85604 	 *
85605 	 * The scheme algorithm finds 'k' and updates 's' simultaneously,
85606 	 * while the logical algorithm finds 'k' with 's' having its initial
85607 	 * value, after which 's' is updated separately (see the Burger-Dybvig
85608 	 * paper, Section 3.1, steps 2 and 3).
85609 	 *
85610 	 * The case where m+ == m- (almost always) is optimized for, because
85611 	 * it reduces the bigint operations considerably and almost always
85612 	 * applies.  The scale loop only needs to work with m+, so this works.
85613 	 */
85614 
85615 	/* XXX: this algorithm could be optimized quite a lot by using e.g.
85616 	 * a logarithm based estimator for 'k' and performing B^n multiplication
85617 	 * using a lookup table or using some bit-representation based exp
85618 	 * algorithm.  Currently we just loop, with significant performance
85619 	 * impact for very large and very small numbers.
85620 	 */
85621 
85622 	DUK_DDD(DUK_DDDPRINT("scale: B=%ld, low_ok=%ld, high_ok=%ld",
85623 	                     (long) nc_ctx->B, (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
85624 	DUK__BI_PRINT("r(init)", &nc_ctx->r);
85625 	DUK__BI_PRINT("s(init)", &nc_ctx->s);
85626 	DUK__BI_PRINT("mp(init)", &nc_ctx->mp);
85627 	DUK__BI_PRINT("mm(init)", &nc_ctx->mm);
85628 
85629 	for (;;) {
85630 		DUK_DDD(DUK_DDDPRINT("scale loop (inc k), k=%ld", (long) k));
85631 		DUK__BI_PRINT("r", &nc_ctx->r);
85632 		DUK__BI_PRINT("s", &nc_ctx->s);
85633 		DUK__BI_PRINT("m+", &nc_ctx->mp);
85634 		DUK__BI_PRINT("m-", &nc_ctx->mm);
85635 
85636 		duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */
85637 		if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1)) {
85638 			DUK_DDD(DUK_DDDPRINT("k is too low"));
85639 			/* r <- r
85640 			 * s <- (* s B)
85641 			 * m+ <- m+
85642 			 * m- <- m-
85643 			 * k <- (+ k 1)
85644 			 */
85645 
85646 			duk__bi_mul_small_copy(&nc_ctx->s, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
85647 			k++;
85648 		} else {
85649 			break;
85650 		}
85651 	}
85652 
85653 	/* k > 0 -> k was too low, and cannot be too high */
85654 	if (k > 0) {
85655 		goto skip_dec_k;
85656 	}
85657 
85658 	for (;;) {
85659 		DUK_DDD(DUK_DDDPRINT("scale loop (dec k), k=%ld", (long) k));
85660 		DUK__BI_PRINT("r", &nc_ctx->r);
85661 		DUK__BI_PRINT("s", &nc_ctx->s);
85662 		DUK__BI_PRINT("m+", &nc_ctx->mp);
85663 		DUK__BI_PRINT("m-", &nc_ctx->mm);
85664 
85665 		duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */
85666 		duk__bi_mul_small(&nc_ctx->t2, &nc_ctx->t1, (duk_uint32_t) nc_ctx->B);   /* t2 = (* (+ r m+) B) */
85667 		if (duk__bi_compare(&nc_ctx->t2, &nc_ctx->s) <= (nc_ctx->high_ok ? -1 : 0)) {
85668 			DUK_DDD(DUK_DDDPRINT("k is too high"));
85669 			/* r <- (* r B)
85670 			 * s <- s
85671 			 * m+ <- (* m+ B)
85672 			 * m- <- (* m- B)
85673 			 * k <- (- k 1)
85674 			 */
85675 			duk__bi_mul_small_copy(&nc_ctx->r, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
85676 			duk__bi_mul_small_copy(&nc_ctx->mp, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
85677 			if (nc_ctx->unequal_gaps) {
85678 				DUK_DDD(DUK_DDDPRINT("m+ != m- -> need to update m- too"));
85679 				duk__bi_mul_small_copy(&nc_ctx->mm, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
85680 			}
85681 			k--;
85682 		} else {
85683 			break;
85684 		}
85685 	}
85686 
85687  skip_dec_k:
85688 
85689 	if (!nc_ctx->unequal_gaps) {
85690 		DUK_DDD(DUK_DDDPRINT("equal gaps, copy m- from m+"));
85691 		duk__bi_copy(&nc_ctx->mm, &nc_ctx->mp);  /* mm <- mp */
85692 	}
85693 	nc_ctx->k = k;
85694 
85695 	DUK_DDD(DUK_DDDPRINT("final k: %ld", (long) k));
85696 	DUK__BI_PRINT("r(final)", &nc_ctx->r);
85697 	DUK__BI_PRINT("s(final)", &nc_ctx->s);
85698 	DUK__BI_PRINT("mp(final)", &nc_ctx->mp);
85699 	DUK__BI_PRINT("mm(final)", &nc_ctx->mm);
85700 }
85701 
85702 DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {
85703 	duk_small_int_t tc1, tc2;    /* terminating conditions */
85704 	duk_small_int_t d;           /* current digit */
85705 	duk_small_int_t count = 0;   /* digit count */
85706 
85707 	/*
85708 	 *  Digit generation loop.
85709 	 *
85710 	 *  Different termination conditions:
85711 	 *
85712 	 *    1. Free format output.  Terminate when shortest accurate
85713 	 *       representation found.
85714 	 *
85715 	 *    2. Fixed format output, with specific number of digits.
85716 	 *       Ignore termination conditions, terminate when digits
85717 	 *       generated.  Caller requests an extra digit and rounds.
85718 	 *
85719 	 *    3. Fixed format output, with a specific absolute cut-off
85720 	 *       position (e.g. 10 digits after decimal point).  Note
85721 	 *       that we always generate at least one digit, even if
85722 	 *       the digit is below the cut-off point already.
85723 	 */
85724 
85725 	for (;;) {
85726 		DUK_DDD(DUK_DDDPRINT("generate loop, count=%ld, k=%ld, B=%ld, low_ok=%ld, high_ok=%ld",
85727 		                     (long) count, (long) nc_ctx->k, (long) nc_ctx->B,
85728 		                     (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
85729 		DUK__BI_PRINT("r", &nc_ctx->r);
85730 		DUK__BI_PRINT("s", &nc_ctx->s);
85731 		DUK__BI_PRINT("m+", &nc_ctx->mp);
85732 		DUK__BI_PRINT("m-", &nc_ctx->mm);
85733 
85734 		/* (quotient-remainder (* r B) s) using a dummy subtraction loop */
85735 		duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, (duk_uint32_t) nc_ctx->B);       /* t1 <- (* r B) */
85736 		d = 0;
85737 		for (;;) {
85738 			if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {
85739 				break;
85740 			}
85741 			duk__bi_sub_copy(&nc_ctx->t1, &nc_ctx->s, &nc_ctx->t2);  /* t1 <- t1 - s */
85742 			d++;
85743 		}
85744 		duk__bi_copy(&nc_ctx->r, &nc_ctx->t1);  /* r <- (remainder (* r B) s) */
85745 		                                        /* d <- (quotient (* r B) s)   (in range 0...B-1) */
85746 		DUK_DDD(DUK_DDDPRINT("-> d(quot)=%ld", (long) d));
85747 		DUK__BI_PRINT("r(rem)", &nc_ctx->r);
85748 
85749 		duk__bi_mul_small_copy(&nc_ctx->mp, (duk_uint32_t) nc_ctx->B, &nc_ctx->t2); /* m+ <- (* m+ B) */
85750 		duk__bi_mul_small_copy(&nc_ctx->mm, (duk_uint32_t) nc_ctx->B, &nc_ctx->t2); /* m- <- (* m- B) */
85751 		DUK__BI_PRINT("mp(upd)", &nc_ctx->mp);
85752 		DUK__BI_PRINT("mm(upd)", &nc_ctx->mm);
85753 
85754 		/* Terminating conditions.  For fixed width output, we just ignore the
85755 		 * terminating conditions (and pretend that tc1 == tc2 == false).  The
85756 		 * the current shortcut for fixed-format output is to generate a few
85757 		 * extra digits and use rounding (with carry) to finish the output.
85758 		 */
85759 
85760 		if (nc_ctx->is_fixed == 0) {
85761 			/* free-form */
85762 			tc1 = (duk__bi_compare(&nc_ctx->r, &nc_ctx->mm) <= (nc_ctx->low_ok ? 0 : -1));
85763 
85764 			duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 <- (+ r m+) */
85765 			tc2 = (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1));
85766 
85767 			DUK_DDD(DUK_DDDPRINT("tc1=%ld, tc2=%ld", (long) tc1, (long) tc2));
85768 		} else {
85769 			/* fixed-format */
85770 			tc1 = 0;
85771 			tc2 = 0;
85772 		}
85773 
85774 		/* Count is incremented before DUK__DRAGON4_OUTPUT_PREINC() call
85775 		 * on purpose, which is taken into account by the macro.
85776 		 */
85777 		count++;
85778 
85779 		if (tc1) {
85780 			if (tc2) {
85781 				/* tc1 = true, tc2 = true */
85782 				duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, 2);
85783 				if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {  /* (< (* r 2) s) */
85784 					DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r > s: output d --> %ld (k=%ld)",
85785 					                     (long) d, (long) nc_ctx->k));
85786 					DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
85787 				} else {
85788 					DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r <= s: output d+1 --> %ld (k=%ld)",
85789 					                     (long) (d + 1), (long) nc_ctx->k));
85790 					DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
85791 				}
85792 				break;
85793 			} else {
85794 				/* tc1 = true, tc2 = false */
85795 				DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=false: output d --> %ld (k=%ld)",
85796 				                     (long) d, (long) nc_ctx->k));
85797 				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
85798 				break;
85799 			}
85800 		} else {
85801 			if (tc2) {
85802 				/* tc1 = false, tc2 = true */
85803 				DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=true: output d+1 --> %ld (k=%ld)",
85804 				                     (long) (d + 1), (long) nc_ctx->k));
85805 				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
85806 				break;
85807 			} else {
85808 				/* tc1 = false, tc2 = false */
85809 				DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=false: output d --> %ld (k=%ld)",
85810 				                     (long) d, (long) nc_ctx->k));
85811 				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
85812 
85813 				/* r <- r    (updated above: r <- (remainder (* r B) s)
85814 				 * s <- s
85815 				 * m+ <- m+  (updated above: m+ <- (* m+ B)
85816 				 * m- <- m-  (updated above: m- <- (* m- B)
85817 				 * B, low_ok, high_ok are fixed
85818 				 */
85819 
85820 				/* fall through and continue for-loop */
85821 			}
85822 		}
85823 
85824 		/* fixed-format termination conditions */
85825 		if (nc_ctx->is_fixed) {
85826 			if (nc_ctx->abs_pos) {
85827 				int pos = nc_ctx->k - count + 1;  /* count is already incremented, take into account */
85828 				DUK_DDD(DUK_DDDPRINT("fixed format, absolute: abs pos=%ld, k=%ld, count=%ld, req=%ld",
85829 				                     (long) pos, (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
85830 				if (pos <= nc_ctx->req_digits) {
85831 					DUK_DDD(DUK_DDDPRINT("digit position reached req_digits, end generate loop"));
85832 					break;
85833 				}
85834 			} else {
85835 				DUK_DDD(DUK_DDDPRINT("fixed format, relative: k=%ld, count=%ld, req=%ld",
85836 				                     (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
85837 				if (count >= nc_ctx->req_digits) {
85838 					DUK_DDD(DUK_DDDPRINT("digit count reached req_digits, end generate loop"));
85839 					break;
85840 				}
85841 			}
85842 		}
85843 	}  /* for */
85844 
85845 	nc_ctx->count = count;
85846 
85847 	DUK_DDD(DUK_DDDPRINT("generate finished"));
85848 
85849 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
85850 	{
85851 		duk_uint8_t buf[2048];
85852 		duk_small_int_t i, t;
85853 		duk_memzero(buf, sizeof(buf));
85854 		for (i = 0; i < nc_ctx->count; i++) {
85855 			t = nc_ctx->digits[i];
85856 			if (t < 0 || t > 36) {
85857 				buf[i] = (duk_uint8_t) '?';
85858 			} else {
85859 				buf[i] = (duk_uint8_t) DUK__DIGITCHAR(t);
85860 			}
85861 		}
85862 		DUK_DDD(DUK_DDDPRINT("-> generated digits; k=%ld, digits='%s'",
85863 		                     (long) nc_ctx->k, (const char *) buf));
85864 	}
85865 #endif
85866 }
85867 
85868 /* Round up digits to a given position.  If position is out-of-bounds,
85869  * does nothing.  If carry propagates over the first digit, a '1' is
85870  * prepended to digits and 'k' will be updated.  Return value indicates
85871  * whether carry propagated over the first digit.
85872  *
85873  * Note that nc_ctx->count is NOT updated based on the rounding position
85874  * (it is updated only if carry overflows over the first digit and an
85875  * extra digit is prepended).
85876  */
85877 DUK_LOCAL duk_small_int_t duk__dragon4_fixed_format_round(duk__numconv_stringify_ctx *nc_ctx, duk_small_int_t round_idx) {
85878 	duk_small_int_t t;
85879 	duk_uint8_t *p;
85880 	duk_uint8_t roundup_limit;
85881 	duk_small_int_t ret = 0;
85882 
85883 	/*
85884 	 *  round_idx points to the digit which is considered for rounding; the
85885 	 *  digit to its left is the final digit of the rounded value.  If round_idx
85886 	 *  is zero, rounding will be performed; the result will either be an empty
85887 	 *  rounded value or if carry happens a '1' digit is generated.
85888 	 */
85889 
85890 	if (round_idx >= nc_ctx->count) {
85891 		DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld >= %ld (count)) -> no rounding",
85892 		                     (long) round_idx, (long) nc_ctx->count));
85893 		return 0;
85894 	} else if (round_idx < 0) {
85895 		DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld < 0) -> no rounding",
85896 		                     (long) round_idx));
85897 		return 0;
85898 	}
85899 
85900 	/*
85901 	 *  Round-up limit.
85902 	 *
85903 	 *  For even values, divides evenly, e.g. 10 -> roundup_limit=5.
85904 	 *
85905 	 *  For odd values, rounds up, e.g. 3 -> roundup_limit=2.
85906 	 *  If radix is 3, 0/3 -> down, 1/3 -> down, 2/3 -> up.
85907 	 */
85908 	roundup_limit = (duk_uint8_t) ((nc_ctx->B + 1) / 2);
85909 
85910 	p = &nc_ctx->digits[round_idx];
85911 	if (*p >= roundup_limit) {
85912 		DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry required"));
85913 		/* carry */
85914 		for (;;) {
85915 			*p = 0;
85916 			if (p == &nc_ctx->digits[0]) {
85917 				DUK_DDD(DUK_DDDPRINT("carry propagated to first digit -> special case handling"));
85918 				duk_memmove((void *) (&nc_ctx->digits[1]),
85919 				            (const void *) (&nc_ctx->digits[0]),
85920 				            (size_t) (sizeof(char) * (size_t) nc_ctx->count));
85921 				nc_ctx->digits[0] = 1;  /* don't increase 'count' */
85922 				nc_ctx->k++;  /* position of highest digit changed */
85923 				nc_ctx->count++;  /* number of digits changed */
85924 				ret = 1;
85925 				break;
85926 			}
85927 
85928 			DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry: B=%ld, roundup_limit=%ld, p=%p, digits=%p",
85929 			                     (long) nc_ctx->B, (long) roundup_limit, (void *) p, (void *) nc_ctx->digits));
85930 			p--;
85931 			t = *p;
85932 			DUK_DDD(DUK_DDDPRINT("digit before carry: %ld", (long) t));
85933 			if (++t < nc_ctx->B) {
85934 				DUK_DDD(DUK_DDDPRINT("rounding carry terminated"));
85935 				*p = (duk_uint8_t) t;
85936 				break;
85937 			}
85938 
85939 			DUK_DDD(DUK_DDDPRINT("wraps, carry to next digit"));
85940 		}
85941 	}
85942 
85943 	return ret;
85944 }
85945 
85946 #define DUK__NO_EXP  (65536)  /* arbitrary marker, outside valid exp range */
85947 
85948 DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx,
85949                                              duk_hthread *thr,
85950                                              duk_small_int_t radix,
85951                                              duk_small_int_t digits,
85952                                              duk_small_uint_t flags,
85953                                              duk_small_int_t neg) {
85954 	duk_small_int_t k;
85955 	duk_small_int_t pos, pos_end;
85956 	duk_small_int_t expt;
85957 	duk_small_int_t dig;
85958 	duk_uint8_t *q;
85959 	duk_uint8_t *buf;
85960 
85961 	/*
85962 	 *  The string conversion here incorporates all the necessary ECMAScript
85963 	 *  semantics without attempting to be generic.  nc_ctx->digits contains
85964 	 *  nc_ctx->count digits (>= 1), with the topmost digit's 'position'
85965 	 *  indicated by nc_ctx->k as follows:
85966 	 *
85967 	 *    digits="123" count=3 k=0   -->   0.123
85968 	 *    digits="123" count=3 k=1   -->   1.23
85969 	 *    digits="123" count=3 k=5   -->   12300
85970 	 *    digits="123" count=3 k=-1  -->   0.0123
85971 	 *
85972 	 *  Note that the identifier names used for format selection are different
85973 	 *  in Burger-Dybvig paper and ECMAScript specification (quite confusingly
85974 	 *  so, because e.g. 'k' has a totally different meaning in each).  See
85975 	 *  documentation for discussion.
85976 	 *
85977 	 *  ECMAScript doesn't specify any specific behavior for format selection
85978 	 *  (e.g. when to use exponent notation) for non-base-10 numbers.
85979 	 *
85980 	 *  The bigint space in the context is reused for string output, as there
85981 	 *  is more than enough space for that (>1kB at the moment), and we avoid
85982 	 *  allocating even more stack.
85983 	 */
85984 
85985 	DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= DUK__MAX_FORMATTED_LENGTH);
85986 	DUK_ASSERT(nc_ctx->count >= 1);
85987 
85988 	k = nc_ctx->k;
85989 	buf = (duk_uint8_t *) &nc_ctx->f;  /* XXX: union would be more correct */
85990 	q = buf;
85991 
85992 	/* Exponent handling: if exponent format is used, record exponent value and
85993 	 * fake k such that one leading digit is generated (e.g. digits=123 -> "1.23").
85994 	 *
85995 	 * toFixed() prevents exponent use; otherwise apply a set of criteria to
85996 	 * match the other API calls (toString(), toPrecision, etc).
85997 	 */
85998 
85999 	expt = DUK__NO_EXP;
86000 	if (!nc_ctx->abs_pos /* toFixed() */) {
86001 		if ((flags & DUK_N2S_FLAG_FORCE_EXP) ||             /* exponential notation forced */
86002 		    ((flags & DUK_N2S_FLAG_NO_ZERO_PAD) &&          /* fixed precision and zero padding would be required */
86003 	             (k - digits >= 1)) ||                          /* (e.g. k=3, digits=2 -> "12X") */
86004 		    ((k > 21 || k <= -6) && (radix == 10))) {       /* toString() conditions */
86005 			DUK_DDD(DUK_DDDPRINT("use exponential notation: k=%ld -> expt=%ld",
86006 			                     (long) k, (long) (k - 1)));
86007 			expt = k - 1;  /* e.g. 12.3 -> digits="123" k=2 -> 1.23e1 */
86008 			k = 1;  /* generate mantissa with a single leading whole number digit */
86009 		}
86010 	}
86011 
86012 	if (neg) {
86013 		*q++ = '-';
86014 	}
86015 
86016 	/* Start position (inclusive) and end position (exclusive) */
86017 	pos = (k >= 1 ? k : 1);
86018 	if (nc_ctx->is_fixed) {
86019 		if (nc_ctx->abs_pos) {
86020 			/* toFixed() */
86021 			pos_end = -digits;
86022 		} else {
86023 			pos_end = k - digits;
86024 		}
86025 	} else {
86026 		pos_end = k - nc_ctx->count;
86027 	}
86028 	if (pos_end > 0) {
86029 		pos_end = 0;
86030 	}
86031 
86032 	DUK_DDD(DUK_DDDPRINT("expt=%ld, k=%ld, count=%ld, pos=%ld, pos_end=%ld, is_fixed=%ld, "
86033 	                     "digits=%ld, abs_pos=%ld",
86034 	                     (long) expt, (long) k, (long) nc_ctx->count, (long) pos, (long) pos_end,
86035 	                     (long) nc_ctx->is_fixed, (long) digits, (long) nc_ctx->abs_pos));
86036 
86037 	/* Digit generation */
86038 	while (pos > pos_end) {
86039 		DUK_DDD(DUK_DDDPRINT("digit generation: pos=%ld, pos_end=%ld",
86040 		                     (long) pos, (long) pos_end));
86041 		if (pos == 0) {
86042 			*q++ = (duk_uint8_t) '.';
86043 		}
86044 		if (pos > k) {
86045 			*q++ = (duk_uint8_t) '0';
86046 		} else if (pos <= k - nc_ctx->count) {
86047 			*q++ = (duk_uint8_t) '0';
86048 		} else {
86049 			dig = nc_ctx->digits[k - pos];
86050 			DUK_ASSERT(dig >= 0 && dig < nc_ctx->B);
86051 			*q++ = (duk_uint8_t) DUK__DIGITCHAR(dig);
86052 		}
86053 
86054 		pos--;
86055 	}
86056 	DUK_ASSERT(pos <= 1);
86057 
86058 	/* Exponent */
86059 	if (expt != DUK__NO_EXP) {
86060 		/*
86061 		 *  Exponent notation for non-base-10 numbers isn't specified in ECMAScript
86062 		 *  specification, as it never explicitly turns up: non-decimal numbers can
86063 		 *  only be formatted with Number.prototype.toString([radix]) and for that,
86064 		 *  behavior is not explicitly specified.
86065 		 *
86066 		 *  Logical choices include formatting the exponent as decimal (e.g. binary
86067 		 *  100000 as 1e+5) or in current radix (e.g. binary 100000 as 1e+101).
86068 		 *  The Dragon4 algorithm (in the original paper) prints the exponent value
86069 		 *  in the target radix B.  However, for radix values 15 and above, the
86070 		 *  exponent separator 'e' is no longer easily parseable.  Consider, for
86071 		 *  instance, the number "1.faecee+1c".
86072 		 */
86073 
86074 		duk_size_t len;
86075 		char expt_sign;
86076 
86077 		*q++ = 'e';
86078 		if (expt >= 0) {
86079 			expt_sign = '+';
86080 		} else {
86081 			expt_sign = '-';
86082 			expt = -expt;
86083 		}
86084 		*q++ = (duk_uint8_t) expt_sign;
86085 		len = duk__dragon4_format_uint32(q, (duk_uint32_t) expt, radix);
86086 		q += len;
86087 	}
86088 
86089 	duk_push_lstring(thr, (const char *) buf, (size_t) (q - buf));
86090 }
86091 
86092 /*
86093  *  Conversion helpers
86094  */
86095 
86096 DUK_LOCAL void duk__dragon4_double_to_ctx(duk__numconv_stringify_ctx *nc_ctx, duk_double_t x) {
86097 	duk_double_union u;
86098 	duk_uint32_t tmp;
86099 	duk_small_int_t expt;
86100 
86101 	/*
86102 	 *    seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
86103 	 *       A        B        C        D        E        F        G        H
86104 	 *
86105 	 *    s       sign bit
86106 	 *    eee...  exponent field
86107 	 *    fff...  fraction
86108 	 *
86109 	 *    ieee value = 1.ffff... * 2^(e - 1023)  (normal)
86110 	 *               = 0.ffff... * 2^(-1022)     (denormal)
86111 	 *
86112 	 *    algorithm v = f * b^e
86113 	 */
86114 
86115 	DUK_DBLUNION_SET_DOUBLE(&u, x);
86116 
86117 	nc_ctx->f.n = 2;
86118 
86119 	tmp = DUK_DBLUNION_GET_LOW32(&u);
86120 	nc_ctx->f.v[0] = tmp;
86121 	tmp = DUK_DBLUNION_GET_HIGH32(&u);
86122 	nc_ctx->f.v[1] = tmp & 0x000fffffUL;
86123 	expt = (duk_small_int_t) ((tmp >> 20) & 0x07ffUL);
86124 
86125 	if (expt == 0) {
86126 		/* denormal */
86127 		expt = DUK__IEEE_DOUBLE_EXP_MIN - 52;
86128 		duk__bi_normalize(&nc_ctx->f);
86129 	} else {
86130 		/* normal: implicit leading 1-bit */
86131 		nc_ctx->f.v[1] |= 0x00100000UL;
86132 		expt = expt - DUK__IEEE_DOUBLE_EXP_BIAS - 52;
86133 		DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));  /* true, because v[1] has at least one bit set */
86134 	}
86135 
86136 	DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));
86137 
86138 	nc_ctx->e = expt;
86139 }
86140 
86141 DUK_LOCAL void duk__dragon4_ctx_to_double(duk__numconv_stringify_ctx *nc_ctx, duk_double_t *x) {
86142 	duk_double_union u;
86143 	duk_small_int_t expt;
86144 	duk_small_int_t i;
86145 	duk_small_int_t bitstart;
86146 	duk_small_int_t bitround;
86147 	duk_small_int_t bitidx;
86148 	duk_small_int_t skip_round;
86149 	duk_uint32_t t, v;
86150 
86151 	DUK_ASSERT(nc_ctx->count == 53 + 1);
86152 
86153 	/* Sometimes this assert is not true right now; it will be true after
86154 	 * rounding.  See: test-bug-numconv-mantissa-assert.js.
86155 	 */
86156 	DUK_ASSERT_DISABLE(nc_ctx->digits[0] == 1);  /* zero handled by caller */
86157 
86158 	/* Should not be required because the code below always sets both high
86159 	 * and low parts, but at least gcc-4.4.5 fails to deduce this correctly
86160 	 * (perhaps because the low part is set (seemingly) conditionally in a
86161 	 * loop), so this is here to avoid the bogus warning.
86162 	 */
86163 	duk_memzero((void *) &u, sizeof(u));
86164 
86165 	/*
86166 	 *  Figure out how generated digits match up with the mantissa,
86167 	 *  and then perform rounding.  If mantissa overflows, need to
86168 	 *  recompute the exponent (it is bumped and may overflow to
86169 	 *  infinity).
86170 	 *
86171 	 *  For normal numbers the leading '1' is hidden and ignored,
86172 	 *  and the last bit is used for rounding:
86173 	 *
86174 	 *                          rounding pt
86175 	 *       <--------52------->|
86176 	 *     1 x x x x ... x x x x|y  ==>  x x x x ... x x x x
86177 	 *
86178 	 *  For denormals, the leading '1' is included in the number,
86179 	 *  and the rounding point is different:
86180 	 *
86181 	 *                      rounding pt
86182 	 *     <--52 or less--->|
86183 	 *     1 x x x x ... x x|x x y  ==>  0 0 ... 1 x x ... x x
86184 	 *
86185 	 *  The largest denormals will have a mantissa beginning with
86186 	 *  a '1' (the explicit leading bit); smaller denormals will
86187 	 *  have leading zero bits.
86188 	 *
86189 	 *  If the exponent would become too high, the result becomes
86190 	 *  Infinity.  If the exponent is so small that the entire
86191 	 *  mantissa becomes zero, the result becomes zero.
86192 	 *
86193 	 *  Note: the Dragon4 'k' is off-by-one with respect to the IEEE
86194 	 *  exponent.  For instance, k==0 indicates that the leading '1'
86195 	 *  digit is at the first binary fraction position (0.1xxx...);
86196 	 *  the corresponding IEEE exponent would be -1.
86197 	 */
86198 
86199 	skip_round = 0;
86200 
86201  recheck_exp:
86202 
86203 	expt = nc_ctx->k - 1;   /* IEEE exp without bias */
86204 	if (expt > 1023) {
86205 		/* Infinity */
86206 		bitstart = -255;  /* needed for inf: causes mantissa to become zero,
86207 		                   * and rounding to be skipped.
86208 		                   */
86209 		expt = 2047;
86210 	} else if (expt >= -1022) {
86211 		/* normal */
86212 		bitstart = 1;  /* skip leading digit */
86213 		expt += DUK__IEEE_DOUBLE_EXP_BIAS;
86214 		DUK_ASSERT(expt >= 1 && expt <= 2046);
86215 	} else {
86216 		/* denormal or zero */
86217 		bitstart = 1023 + expt;  /* expt==-1023 -> bitstart=0 (leading 1);
86218 		                          * expt==-1024 -> bitstart=-1 (one left of leading 1), etc
86219 		                          */
86220 		expt = 0;
86221 	}
86222 	bitround = bitstart + 52;
86223 
86224 	DUK_DDD(DUK_DDDPRINT("ieee expt=%ld, bitstart=%ld, bitround=%ld",
86225 	                     (long) expt, (long) bitstart, (long) bitround));
86226 
86227 	if (!skip_round) {
86228 		if (duk__dragon4_fixed_format_round(nc_ctx, bitround)) {
86229 			/* Corner case: see test-numconv-parse-mant-carry.js.  We could
86230 			 * just bump the exponent and update bitstart, but it's more robust
86231 			 * to recompute (but avoid rounding twice).
86232 			 */
86233 			DUK_DDD(DUK_DDDPRINT("rounding caused exponent to be bumped, recheck exponent"));
86234 			skip_round = 1;
86235 			goto recheck_exp;
86236 		}
86237 	}
86238 
86239 	/*
86240 	 *  Create mantissa
86241 	 */
86242 
86243 	t = 0;
86244 	for (i = 0; i < 52; i++) {
86245 		bitidx = bitstart + 52 - 1 - i;
86246 		if (bitidx >= nc_ctx->count) {
86247 			v = 0;
86248 		} else if (bitidx < 0) {
86249 			v = 0;
86250 		} else {
86251 			v = nc_ctx->digits[bitidx];
86252 		}
86253 		DUK_ASSERT(v == 0 || v == 1);
86254 		t += v << (i % 32);
86255 		if (i == 31) {
86256 			/* low 32 bits is complete */
86257 			DUK_DBLUNION_SET_LOW32(&u, t);
86258 			t = 0;
86259 		}
86260 	}
86261 	/* t has high mantissa */
86262 
86263 	DUK_DDD(DUK_DDDPRINT("mantissa is complete: %08lx %08lx",
86264 	                     (unsigned long) t,
86265 	                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
86266 
86267 	DUK_ASSERT(expt >= 0 && expt <= 0x7ffL);
86268 	t += ((duk_uint32_t) expt) << 20;
86269 #if 0  /* caller handles sign change */
86270 	if (negative) {
86271 		t |= 0x80000000U;
86272 	}
86273 #endif
86274 	DUK_DBLUNION_SET_HIGH32(&u, t);
86275 
86276 	DUK_DDD(DUK_DDDPRINT("number is complete: %08lx %08lx",
86277 	                     (unsigned long) DUK_DBLUNION_GET_HIGH32(&u),
86278 	                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
86279 
86280 	*x = DUK_DBLUNION_GET_DOUBLE(&u);
86281 }
86282 
86283 /*
86284  *  Exposed number-to-string API
86285  *
86286  *  Input: [ number ]
86287  *  Output: [ string ]
86288  */
86289 
86290 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) {
86291 	duk_double_t x;
86292 	duk_small_int_t c;
86293 	duk_small_int_t neg;
86294 	duk_uint32_t uval;
86295 	duk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */
86296 	duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
86297 
86298 	x = (duk_double_t) duk_require_number(thr, -1);
86299 	duk_pop(thr);
86300 
86301 	/*
86302 	 *  Handle special cases (NaN, infinity, zero).
86303 	 */
86304 
86305 	c = (duk_small_int_t) DUK_FPCLASSIFY(x);
86306 	if (DUK_SIGNBIT((double) x)) {
86307 		x = -x;
86308 		neg = 1;
86309 	} else {
86310 		neg = 0;
86311 	}
86312 
86313 	/* NaN sign bit is platform specific with unpacked, un-normalized NaNs */
86314 	DUK_ASSERT(c == DUK_FP_NAN || DUK_SIGNBIT((double) x) == 0);
86315 
86316 	if (c == DUK_FP_NAN) {
86317 		duk_push_hstring_stridx(thr, DUK_STRIDX_NAN);
86318 		return;
86319 	} else if (c == DUK_FP_INFINITE) {
86320 		if (neg) {
86321 			/* -Infinity */
86322 			duk_push_hstring_stridx(thr, DUK_STRIDX_MINUS_INFINITY);
86323 		} else {
86324 			/* Infinity */
86325 			duk_push_hstring_stridx(thr, DUK_STRIDX_INFINITY);
86326 		}
86327 		return;
86328 	} else if (c == DUK_FP_ZERO) {
86329 		/* We can't shortcut zero here if it goes through special formatting
86330 		 * (such as forced exponential notation).
86331 		 */
86332 		;
86333 	}
86334 
86335 	/*
86336 	 *  Handle integers in 32-bit range (that is, [-(2**32-1),2**32-1])
86337 	 *  specially, as they're very likely for embedded programs.  This
86338 	 *  is now done for all radix values.  We must be careful not to use
86339 	 *  the fast path when special formatting (e.g. forced exponential)
86340 	 *  is in force.
86341 	 *
86342 	 *  XXX: could save space by supporting radix 10 only and using
86343 	 *  sprintf "%lu" for the fast path and for exponent formatting.
86344 	 */
86345 
86346 	uval = duk_double_to_uint32_t(x);
86347 	if (((double) uval) == x &&  /* integer number in range */
86348 	    flags == 0) {            /* no special formatting */
86349 		/* use bigint area as a temp */
86350 		duk_uint8_t *buf = (duk_uint8_t *) (&nc_ctx->f);
86351 		duk_uint8_t *p = buf;
86352 
86353 		DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= 32 + 1);  /* max size: radix=2 + sign */
86354 		if (neg && uval != 0) {
86355 			/* no negative sign for zero */
86356 			*p++ = (duk_uint8_t) '-';
86357 		}
86358 		p += duk__dragon4_format_uint32(p, uval, radix);
86359 		duk_push_lstring(thr, (const char *) buf, (duk_size_t) (p - buf));
86360 		return;
86361 	}
86362 
86363 	/*
86364 	 *  Dragon4 setup.
86365 	 *
86366 	 *  Convert double from IEEE representation for conversion;
86367 	 *  normal finite values have an implicit leading 1-bit.  The
86368 	 *  slow path algorithm doesn't handle zero, so zero is special
86369 	 *  cased here but still creates a valid nc_ctx, and goes
86370 	 *  through normal formatting in case special formatting has
86371 	 *  been requested (e.g. forced exponential format: 0 -> "0e+0").
86372 	 */
86373 
86374 	/* Would be nice to bulk clear the allocation, but the context
86375 	 * is 1-2 kilobytes and nothing should rely on it being zeroed.
86376 	 */
86377 #if 0
86378 	duk_memzero((void *) nc_ctx, sizeof(*nc_ctx));  /* slow init, do only for slow path cases */
86379 #endif
86380 
86381 	nc_ctx->is_s2n = 0;
86382 	nc_ctx->b = 2;
86383 	nc_ctx->B = radix;
86384 	nc_ctx->abs_pos = 0;
86385 	if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
86386 		nc_ctx->is_fixed = 1;
86387 		if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
86388 			/* absolute req_digits; e.g. digits = 1 -> last digit is 0,
86389 			 * but add an extra digit for rounding.
86390 			 */
86391 			nc_ctx->abs_pos = 1;
86392 			nc_ctx->req_digits = (-digits + 1) - 1;
86393 		} else {
86394 			nc_ctx->req_digits = digits + 1;
86395 		}
86396 	} else {
86397 		nc_ctx->is_fixed = 0;
86398 		nc_ctx->req_digits = 0;
86399 	}
86400 
86401 	if (c == DUK_FP_ZERO) {
86402 		/* Zero special case: fake requested number of zero digits; ensure
86403 		 * no sign bit is printed.  Relative and absolute fixed format
86404 		 * require separate handling.
86405 		 */
86406 		duk_small_int_t count;
86407 		if (nc_ctx->is_fixed) {
86408 			if (nc_ctx->abs_pos) {
86409 				count = digits + 2;  /* lead zero + 'digits' fractions + 1 for rounding */
86410 			} else {
86411 				count = digits + 1;  /* + 1 for rounding */
86412 			}
86413 		} else {
86414 			count = 1;
86415 		}
86416 		DUK_DDD(DUK_DDDPRINT("count=%ld", (long) count));
86417 		DUK_ASSERT(count >= 1);
86418 		duk_memzero((void *) nc_ctx->digits, (size_t) count);
86419 		nc_ctx->count = count;
86420 		nc_ctx->k = 1;  /* 0.000... */
86421 		neg = 0;
86422 		goto zero_skip;
86423 	}
86424 
86425 	duk__dragon4_double_to_ctx(nc_ctx, x);   /* -> sets 'f' and 'e' */
86426 	DUK__BI_PRINT("f", &nc_ctx->f);
86427 	DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
86428 
86429 	/*
86430 	 *  Dragon4 slow path digit generation.
86431 	 */
86432 
86433 	duk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */
86434 
86435 	DUK_DDD(DUK_DDDPRINT("after prepare:"));
86436 	DUK__BI_PRINT("r", &nc_ctx->r);
86437 	DUK__BI_PRINT("s", &nc_ctx->s);
86438 	DUK__BI_PRINT("mp", &nc_ctx->mp);
86439 	DUK__BI_PRINT("mm", &nc_ctx->mm);
86440 
86441 	duk__dragon4_scale(nc_ctx);
86442 
86443 	DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
86444 	DUK__BI_PRINT("r", &nc_ctx->r);
86445 	DUK__BI_PRINT("s", &nc_ctx->s);
86446 	DUK__BI_PRINT("mp", &nc_ctx->mp);
86447 	DUK__BI_PRINT("mm", &nc_ctx->mm);
86448 
86449 	duk__dragon4_generate(nc_ctx);
86450 
86451 	/*
86452 	 *  Convert and push final string.
86453 	 */
86454 
86455  zero_skip:
86456 
86457 	if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
86458 		/* Perform fixed-format rounding. */
86459 		duk_small_int_t roundpos;
86460 		if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
86461 			/* 'roundpos' is relative to nc_ctx->k and increases to the right
86462 			 * (opposite of how 'k' changes).
86463 			 */
86464 			roundpos = -digits;  /* absolute position for digit considered for rounding */
86465 			roundpos = nc_ctx->k - roundpos;
86466 		} else {
86467 			roundpos = digits;
86468 		}
86469 		DUK_DDD(DUK_DDDPRINT("rounding: k=%ld, count=%ld, digits=%ld, roundpos=%ld",
86470 		                     (long) nc_ctx->k, (long) nc_ctx->count, (long) digits, (long) roundpos));
86471 		(void) duk__dragon4_fixed_format_round(nc_ctx, roundpos);
86472 
86473 		/* Note: 'count' is currently not adjusted by rounding (i.e. the
86474 		 * digits are not "chopped off".  That shouldn't matter because
86475 		 * the digit position (absolute or relative) is passed on to the
86476 		 * convert-and-push function.
86477 		 */
86478 	}
86479 
86480 	duk__dragon4_convert_and_push(nc_ctx, thr, radix, digits, flags, neg);
86481 }
86482 
86483 DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags) {
86484 	duk_native_stack_check(thr);
86485 	duk__numconv_stringify_raw(thr, radix, digits, flags);
86486 }
86487 
86488 /*
86489  *  Exposed string-to-number API
86490  *
86491  *  Input: [ string ]
86492  *  Output: [ number ]
86493  *
86494  *  If number parsing fails, a NaN is pushed as the result.  If number parsing
86495  *  fails due to an internal error, an InternalError is thrown.
86496  */
86497 
86498 DUK_LOCAL DUK_NOINLINE void duk__numconv_parse_raw(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags) {
86499 	duk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */
86500 	duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
86501 	duk_double_t res;
86502 	duk_hstring *h_str;
86503 	duk_int_t expt;
86504 	duk_bool_t expt_neg;
86505 	duk_small_int_t expt_adj;
86506 	duk_small_int_t neg;
86507 	duk_small_int_t dig;
86508 	duk_small_int_t dig_whole;
86509 	duk_small_int_t dig_lzero;
86510 	duk_small_int_t dig_frac;
86511 	duk_small_int_t dig_expt;
86512 	duk_small_int_t dig_prec;
86513 	const duk__exp_limits *explim;
86514 	const duk_uint8_t *p;
86515 	duk_small_int_t ch;
86516 
86517 	DUK_DDD(DUK_DDDPRINT("parse number: %!T, radix=%ld, flags=0x%08lx",
86518 	                     (duk_tval *) duk_get_tval(thr, -1),
86519 	                     (long) radix, (unsigned long) flags));
86520 
86521 	DUK_ASSERT(radix >= 2 && radix <= 36);
86522 	DUK_ASSERT(radix - 2 < (duk_small_int_t) sizeof(duk__str2num_digits_for_radix));
86523 
86524 	/*
86525 	 *  Preliminaries: trim, sign, Infinity check
86526 	 *
86527 	 *  We rely on the interned string having a NUL terminator, which will
86528 	 *  cause a parse failure wherever it is encountered.  As a result, we
86529 	 *  don't need separate pointer checks.
86530 	 *
86531 	 *  There is no special parsing for 'NaN' in the specification although
86532 	 *  'Infinity' (with an optional sign) is allowed in some contexts.
86533 	 *  Some contexts allow plus/minus sign, while others only allow the
86534 	 *  minus sign (like JSON.parse()).
86535 	 *
86536 	 *  Automatic hex number detection (leading '0x' or '0X') and octal
86537 	 *  number detection (leading '0' followed by at least one octal digit)
86538 	 *  is done here too.
86539 	 *
86540 	 *  Symbols are not explicitly rejected here (that's up to the caller).
86541 	 *  If a symbol were passed here, it should ultimately safely fail
86542 	 *  parsing due to a syntax error.
86543 	 */
86544 
86545 	if (flags & DUK_S2N_FLAG_TRIM_WHITE) {
86546 		/* Leading / trailing whitespace is sometimes accepted and
86547 		 * sometimes not.  After white space trimming, all valid input
86548 		 * characters are pure ASCII.
86549 		 */
86550 		duk_trim(thr, -1);
86551 	}
86552 	h_str = duk_require_hstring(thr, -1);
86553 	DUK_ASSERT(h_str != NULL);
86554 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_str);
86555 
86556 	neg = 0;
86557 	ch = *p;
86558 	if (ch == (duk_small_int_t) '+') {
86559 		if ((flags & DUK_S2N_FLAG_ALLOW_PLUS) == 0) {
86560 			DUK_DDD(DUK_DDDPRINT("parse failed: leading plus sign not allowed"));
86561 			goto parse_fail;
86562 		}
86563 		p++;
86564 	} else if (ch == (duk_small_int_t) '-') {
86565 		if ((flags & DUK_S2N_FLAG_ALLOW_MINUS) == 0) {
86566 			DUK_DDD(DUK_DDDPRINT("parse failed: leading minus sign not allowed"));
86567 			goto parse_fail;
86568 		}
86569 		p++;
86570 		neg = 1;
86571 	}
86572 
86573 	if ((flags & DUK_S2N_FLAG_ALLOW_INF) && DUK_STRNCMP((const char *) p, "Infinity", 8) == 0) {
86574 		/* Don't check for Infinity unless the context allows it.
86575 		 * 'Infinity' is a valid integer literal in e.g. base-36:
86576 		 *
86577 		 *   parseInt('Infinity', 36)
86578 		 *   1461559270678
86579 		 */
86580 
86581 		if ((flags & DUK_S2N_FLAG_ALLOW_GARBAGE) == 0 && p[8] != DUK_ASC_NUL) {
86582 			DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage after matching 'Infinity' not allowed"));
86583 			goto parse_fail;
86584 		} else {
86585 			res = DUK_DOUBLE_INFINITY;
86586 			goto negcheck_and_ret;
86587 		}
86588 	}
86589 	ch = *p;
86590 	if (ch == (duk_small_int_t) '0') {
86591 		duk_small_int_t detect_radix = 0;
86592 		ch = DUK_LOWERCASE_CHAR_ASCII(p[1]);  /* 'x' or 'X' -> 'x' */
86593 		if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT) && ch == DUK_ASC_LC_X) {
86594 			DUK_DDD(DUK_DDDPRINT("detected 0x/0X hex prefix, changing radix and preventing fractions and exponent"));
86595 			detect_radix = 16;
86596 #if 0
86597 		} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT) &&
86598 		           (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9')) {
86599 			DUK_DDD(DUK_DDDPRINT("detected 0n oct prefix, changing radix and preventing fractions and exponent"));
86600 			detect_radix = 8;
86601 
86602 			/* NOTE: if this legacy octal case is added back, it has
86603 			 * different flags and 'p' advance so this needs to be
86604 			 * reworked.
86605 			 */
86606 			flags |= DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO;  /* interpret e.g. '09' as '0', not NaN */
86607 			p += 1;
86608 #endif
86609 		} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT) && ch == DUK_ASC_LC_O) {
86610 			DUK_DDD(DUK_DDDPRINT("detected 0o oct prefix, changing radix and preventing fractions and exponent"));
86611 			detect_radix = 8;
86612 		} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT) && ch == DUK_ASC_LC_B) {
86613 			DUK_DDD(DUK_DDDPRINT("detected 0b bin prefix, changing radix and preventing fractions and exponent"));
86614 			detect_radix = 2;
86615 		}
86616 		if (detect_radix > 0) {
86617 			radix = detect_radix;
86618 			/* Clear empty as zero flag: interpret e.g. '0x' and '0xg' as a NaN (= parse error) */
86619 			flags &= ~(DUK_S2N_FLAG_ALLOW_EXP | DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
86620 			           DUK_S2N_FLAG_ALLOW_FRAC | DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
86621 			           DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO);
86622 			flags |= DUK_S2N_FLAG_ALLOW_LEADING_ZERO;  /* allow e.g. '0x0009' and '0b00010001' */
86623 			p += 2;
86624 		}
86625 	}
86626 
86627 	/*
86628 	 *  Scan number and setup for Dragon4.
86629 	 *
86630 	 *  The fast path case is detected during setup: an integer which
86631 	 *  can be converted without rounding, no net exponent.  The fast
86632 	 *  path could be implemented as a separate scan, but may not really
86633 	 *  be worth it: the multiplications for building 'f' are not
86634 	 *  expensive when 'f' is small.
86635 	 *
86636 	 *  The significand ('f') must contain enough bits of (apparent)
86637 	 *  accuracy, so that Dragon4 will generate enough binary output digits.
86638 	 *  For decimal numbers, this means generating a 20-digit significand,
86639 	 *  which should yield enough practical accuracy to parse IEEE doubles.
86640 	 *  In fact, the ECMAScript specification explicitly allows an
86641 	 *  implementation to treat digits beyond 20 as zeroes (and even
86642 	 *  to round the 20th digit upwards).  For non-decimal numbers, the
86643 	 *  appropriate number of digits has been precomputed for comparable
86644 	 *  accuracy.
86645 	 *
86646 	 *  Digit counts:
86647 	 *
86648 	 *    [ dig_lzero ]
86649 	 *      |
86650 	 *     .+-..---[ dig_prec ]----.
86651 	 *     |  ||                   |
86652 	 *     0000123.456789012345678901234567890e+123456
86653 	 *     |     | |                         |  |    |
86654 	 *     `--+--' `------[ dig_frac ]-------'  `-+--'
86655 	 *        |                                   |
86656 	 *    [ dig_whole ]                       [ dig_expt ]
86657 	 *
86658 	 *    dig_frac and dig_expt are -1 if not present
86659 	 *    dig_lzero is only computed for whole number part
86660 	 *
86661 	 *  Parsing state
86662 	 *
86663 	 *     Parsing whole part      dig_frac < 0 AND dig_expt < 0
86664 	 *     Parsing fraction part   dig_frac >= 0 AND dig_expt < 0
86665 	 *     Parsing exponent part   dig_expt >= 0   (dig_frac may be < 0 or >= 0)
86666 	 *
86667 	 *  Note: in case we hit an implementation limit (like exponent range),
86668 	 *  we should throw an error, NOT return NaN or Infinity.  Even with
86669 	 *  very large exponent (or significand) values the final result may be
86670 	 *  finite, so NaN/Infinity would be incorrect.
86671 	 */
86672 
86673 	duk__bi_set_small(&nc_ctx->f, 0);
86674 	dig_prec = 0;
86675 	dig_lzero = 0;
86676 	dig_whole = 0;
86677 	dig_frac = -1;
86678 	dig_expt = -1;
86679 	expt = 0;
86680 	expt_adj = 0;  /* essentially tracks digit position of lowest 'f' digit */
86681 	expt_neg = 0;
86682 	for (;;) {
86683 		ch = *p++;
86684 
86685 		DUK_DDD(DUK_DDDPRINT("parse digits: p=%p, ch='%c' (%ld), expt=%ld, expt_adj=%ld, "
86686 		                     "dig_whole=%ld, dig_frac=%ld, dig_expt=%ld, dig_lzero=%ld, dig_prec=%ld",
86687 		                     (const void *) p, (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : '?'), (long) ch,
86688 		                     (long) expt, (long) expt_adj, (long) dig_whole, (long) dig_frac,
86689 		                     (long) dig_expt, (long) dig_lzero, (long) dig_prec));
86690 		DUK__BI_PRINT("f", &nc_ctx->f);
86691 
86692 		/* Most common cases first. */
86693 		if (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9') {
86694 			dig = (duk_small_int_t) ch - '0' + 0;
86695 		} else if (ch == (duk_small_int_t) '.') {
86696 			/* A leading digit is not required in some cases, e.g. accept ".123".
86697 			 * In other cases (JSON.parse()) a leading digit is required.  This
86698 			 * is checked for after the loop.
86699 			 */
86700 			if (dig_frac >= 0 || dig_expt >= 0) {
86701 				if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
86702 					DUK_DDD(DUK_DDDPRINT("garbage termination (invalid period)"));
86703 					break;
86704 				} else {
86705 					DUK_DDD(DUK_DDDPRINT("parse failed: period not allowed"));
86706 					goto parse_fail;
86707 				}
86708 			}
86709 
86710 			if ((flags & DUK_S2N_FLAG_ALLOW_FRAC) == 0) {
86711 				/* Some contexts don't allow fractions at all; this can't be a
86712 				 * post-check because the state ('f' and expt) would be incorrect.
86713 				 */
86714 				if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
86715 					DUK_DDD(DUK_DDDPRINT("garbage termination (invalid first period)"));
86716 					break;
86717 				} else {
86718 					DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed"));
86719 				}
86720 			}
86721 
86722 			DUK_DDD(DUK_DDDPRINT("start fraction part"));
86723 			dig_frac = 0;
86724 			continue;
86725 		} else if (ch == (duk_small_int_t) 0) {
86726 			DUK_DDD(DUK_DDDPRINT("NUL termination"));
86727 			break;
86728 		} else if ((flags & DUK_S2N_FLAG_ALLOW_EXP) &&
86729 		           dig_expt < 0 && (ch == (duk_small_int_t) 'e' || ch == (duk_small_int_t) 'E')) {
86730 			/* Note: we don't parse back exponent notation for anything else
86731 			 * than radix 10, so this is not an ambiguous check (e.g. hex
86732 			 * exponent values may have 'e' either as a significand digit
86733 			 * or as an exponent separator).
86734 			 *
86735 			 * If the exponent separator occurs twice, 'e' will be interpreted
86736 			 * as a digit (= 14) and will be rejected as an invalid decimal
86737 			 * digit.
86738 			 */
86739 
86740 			DUK_DDD(DUK_DDDPRINT("start exponent part"));
86741 
86742 			/* Exponent without a sign or with a +/- sign is accepted
86743 			 * by all call sites (even JSON.parse()).
86744 			 */
86745 			ch = *p;
86746 			if (ch == (duk_small_int_t) '-') {
86747 				expt_neg = 1;
86748 				p++;
86749 			} else if (ch == (duk_small_int_t) '+') {
86750 				p++;
86751 			}
86752 			dig_expt = 0;
86753 			continue;
86754 		} else if (ch >= (duk_small_int_t) 'a' && ch <= (duk_small_int_t) 'z') {
86755 			dig = (duk_small_int_t) (ch - (duk_small_int_t) 'a' + 0x0a);
86756 		} else if (ch >= (duk_small_int_t) 'A' && ch <= (duk_small_int_t) 'Z') {
86757 			dig = (duk_small_int_t) (ch - (duk_small_int_t) 'A' + 0x0a);
86758 		} else {
86759 			dig = 255;  /* triggers garbage digit check below */
86760 		}
86761 		DUK_ASSERT((dig >= 0 && dig <= 35) || dig == 255);
86762 
86763 		if (dig >= radix) {
86764 			if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
86765 				DUK_DDD(DUK_DDDPRINT("garbage termination"));
86766 				break;
86767 			} else {
86768 				DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage or invalid digit"));
86769 				goto parse_fail;
86770 			}
86771 		}
86772 
86773 		if (dig_expt < 0) {
86774 			/* whole or fraction digit */
86775 
86776 			if (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
86777 				/* significant from precision perspective */
86778 
86779 				duk_small_int_t f_zero = duk__bi_is_zero(&nc_ctx->f);
86780 				if (f_zero && dig == 0) {
86781 					/* Leading zero is not counted towards precision digits; not
86782 					 * in the integer part, nor in the fraction part.
86783 					 */
86784 					if (dig_frac < 0) {
86785 						dig_lzero++;
86786 					}
86787 				} else {
86788 					/* XXX: join these ops (multiply-accumulate), but only if
86789 					 * code footprint decreases.
86790 					 */
86791 					duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, (duk_uint32_t) radix);
86792 					duk__bi_add_small(&nc_ctx->f, &nc_ctx->t1, (duk_uint32_t) dig);
86793 					dig_prec++;
86794 				}
86795 			} else {
86796 				/* Ignore digits beyond a radix-specific limit, but note them
86797 				 * in expt_adj.
86798 				 */
86799 				expt_adj++;
86800 			}
86801 
86802 			if (dig_frac >= 0) {
86803 				dig_frac++;
86804 				expt_adj--;
86805 			} else {
86806 				dig_whole++;
86807 			}
86808 		} else {
86809 			/* exponent digit */
86810 
86811 			DUK_ASSERT(radix == 10);
86812 			expt = expt * radix + dig;
86813 			if (expt > DUK_S2N_MAX_EXPONENT) {
86814 				/* Impose a reasonable exponent limit, so that exp
86815 				 * doesn't need to get tracked using a bigint.
86816 				 */
86817 				DUK_DDD(DUK_DDDPRINT("parse failed: exponent too large"));
86818 				goto parse_explimit_error;
86819 			}
86820 			dig_expt++;
86821 		}
86822 	}
86823 
86824 	/* Leading zero. */
86825 
86826 	if (dig_lzero > 0 && dig_whole > 1) {
86827 		if ((flags & DUK_S2N_FLAG_ALLOW_LEADING_ZERO) == 0) {
86828 			DUK_DDD(DUK_DDDPRINT("parse failed: leading zeroes not allowed in integer part"));
86829 			goto parse_fail;
86830 		}
86831 	}
86832 
86833 	/* Validity checks for various fraction formats ("0.1", ".1", "1.", "."). */
86834 
86835 	if (dig_whole == 0) {
86836 		if (dig_frac == 0) {
86837 			/* "." is not accepted in any format */
86838 			DUK_DDD(DUK_DDDPRINT("parse failed: plain period without leading or trailing digits"));
86839 			goto parse_fail;
86840 		} else if (dig_frac > 0) {
86841 			/* ".123" */
86842 			if ((flags & DUK_S2N_FLAG_ALLOW_NAKED_FRAC) == 0) {
86843 				DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed without "
86844 				                     "leading integer digit(s)"));
86845 				goto parse_fail;
86846 			}
86847 		} else {
86848 			/* Empty ("") is allowed in some formats (e.g. Number(''), as zero,
86849 			 * but it must not have a leading +/- sign (GH-2019).  Note that
86850 			 * for Number(), h_str is already trimmed so we can check for zero
86851 			 * length and still get Number('  +  ') == NaN.
86852 			 */
86853 			if ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO) == 0) {
86854 				DUK_DDD(DUK_DDDPRINT("parse failed: empty string not allowed (as zero)"));
86855 				goto parse_fail;
86856 			} else if (DUK_HSTRING_GET_BYTELEN(h_str) != 0) {
86857 				DUK_DDD(DUK_DDDPRINT("parse failed: no digits, but not empty (had a +/- sign)"));
86858 				goto parse_fail;
86859 			}
86860 		}
86861 	} else {
86862 		if (dig_frac == 0) {
86863 			/* "123." is allowed in some formats */
86864 			if ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_FRAC) == 0) {
86865 				DUK_DDD(DUK_DDDPRINT("parse failed: empty fractions"));
86866 				goto parse_fail;
86867 			}
86868 		} else if (dig_frac > 0) {
86869 			/* "123.456" */
86870 			;
86871 		} else {
86872 			/* "123" */
86873 			;
86874 		}
86875 	}
86876 
86877 	/* Exponent without digits (e.g. "1e" or "1e+").  If trailing garbage is
86878 	 * allowed, ignore exponent part as garbage (= parse as "1", i.e. exp 0).
86879 	 */
86880 
86881 	if (dig_expt == 0) {
86882 		if ((flags & DUK_S2N_FLAG_ALLOW_GARBAGE) == 0) {
86883 			DUK_DDD(DUK_DDDPRINT("parse failed: empty exponent"));
86884 			goto parse_fail;
86885 		}
86886 		DUK_ASSERT(expt == 0);
86887 	}
86888 
86889 	if (expt_neg) {
86890 		expt = -expt;
86891 	}
86892 	DUK_DDD(DUK_DDDPRINT("expt=%ld, expt_adj=%ld, net exponent -> %ld",
86893 	                     (long) expt, (long) expt_adj, (long) (expt + expt_adj)));
86894 	expt += expt_adj;
86895 
86896 	/* Fast path check. */
86897 
86898 	if (nc_ctx->f.n <= 1 &&   /* 32-bit value */
86899 	    expt == 0    /* no net exponent */) {
86900 		/* Fast path is triggered for no exponent and also for balanced exponent
86901 		 * and fraction parts, e.g. for "1.23e2" == "123".  Remember to respect
86902 		 * zero sign.
86903 		 */
86904 
86905 		/* XXX: could accept numbers larger than 32 bits, e.g. up to 53 bits? */
86906 		DUK_DDD(DUK_DDDPRINT("fast path number parse"));
86907 		if (nc_ctx->f.n == 1) {
86908 			res = (double) nc_ctx->f.v[0];
86909 		} else {
86910 			res = 0.0;
86911 		}
86912 		goto negcheck_and_ret;
86913 	}
86914 
86915 	/* Significand ('f') padding. */
86916 
86917 	while (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
86918 		/* Pad significand with "virtual" zero digits so that Dragon4 will
86919 		 * have enough (apparent) precision to work with.
86920 		 */
86921 		DUK_DDD(DUK_DDDPRINT("dig_prec=%ld, pad significand with zero", (long) dig_prec));
86922 		duk__bi_mul_small_copy(&nc_ctx->f, (duk_uint32_t) radix, &nc_ctx->t1);
86923 		DUK__BI_PRINT("f", &nc_ctx->f);
86924 		expt--;
86925 		dig_prec++;
86926 	}
86927 
86928 	DUK_DDD(DUK_DDDPRINT("final exponent: %ld", (long) expt));
86929 
86930 	/* Detect zero special case. */
86931 
86932 	if (nc_ctx->f.n == 0) {
86933 		/* This may happen even after the fast path check, if exponent is
86934 		 * not balanced (e.g. "0e1").  Remember to respect zero sign.
86935 		 */
86936 		DUK_DDD(DUK_DDDPRINT("significand is zero"));
86937 		res = 0.0;
86938 		goto negcheck_and_ret;
86939 	}
86940 
86941 
86942 	/* Quick reject of too large or too small exponents.  This check
86943 	 * would be incorrect for zero (e.g. "0e1000" is zero, not Infinity)
86944 	 * so zero check must be above.
86945 	 */
86946 
86947 	explim = &duk__str2num_exp_limits[radix - 2];
86948 	if (expt > explim->upper) {
86949 		DUK_DDD(DUK_DDDPRINT("exponent too large -> infinite"));
86950 		res = (duk_double_t) DUK_DOUBLE_INFINITY;
86951 		goto negcheck_and_ret;
86952 	} else if (expt < explim->lower) {
86953 		DUK_DDD(DUK_DDDPRINT("exponent too small -> zero"));
86954 		res = (duk_double_t) 0.0;
86955 		goto negcheck_and_ret;
86956 	}
86957 
86958 	nc_ctx->is_s2n = 1;
86959 	nc_ctx->e = expt;
86960 	nc_ctx->b = radix;
86961 	nc_ctx->B = 2;
86962 	nc_ctx->is_fixed = 1;
86963 	nc_ctx->abs_pos = 0;
86964 	nc_ctx->req_digits = 53 + 1;
86965 
86966 	DUK__BI_PRINT("f", &nc_ctx->f);
86967 	DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
86968 
86969 	/*
86970 	 *  Dragon4 slow path (binary) digit generation.
86971 	 *  An extra digit is generated for rounding.
86972 	 */
86973 
86974 	duk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */
86975 
86976 	DUK_DDD(DUK_DDDPRINT("after prepare:"));
86977 	DUK__BI_PRINT("r", &nc_ctx->r);
86978 	DUK__BI_PRINT("s", &nc_ctx->s);
86979 	DUK__BI_PRINT("mp", &nc_ctx->mp);
86980 	DUK__BI_PRINT("mm", &nc_ctx->mm);
86981 
86982 	duk__dragon4_scale(nc_ctx);
86983 
86984 	DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
86985 	DUK__BI_PRINT("r", &nc_ctx->r);
86986 	DUK__BI_PRINT("s", &nc_ctx->s);
86987 	DUK__BI_PRINT("mp", &nc_ctx->mp);
86988 	DUK__BI_PRINT("mm", &nc_ctx->mm);
86989 
86990 	duk__dragon4_generate(nc_ctx);
86991 
86992 	DUK_ASSERT(nc_ctx->count == 53 + 1);
86993 
86994 	/*
86995 	 *  Convert binary digits into an IEEE double.  Need to handle
86996 	 *  denormals and rounding correctly.
86997 	 *
86998 	 *  Some call sites currently assume the result is always a
86999 	 *  non-fastint double.  If this is changed, check all call
87000 	 *  sites.
87001 	 */
87002 
87003 	duk__dragon4_ctx_to_double(nc_ctx, &res);
87004 	goto negcheck_and_ret;
87005 
87006  negcheck_and_ret:
87007 	if (neg) {
87008 		res = -res;
87009 	}
87010 	duk_pop(thr);
87011 	duk_push_number(thr, (double) res);
87012 	DUK_DDD(DUK_DDDPRINT("result: %!T", (duk_tval *) duk_get_tval(thr, -1)));
87013 	return;
87014 
87015  parse_fail:
87016 	DUK_DDD(DUK_DDDPRINT("parse failed"));
87017 	duk_pop(thr);
87018 	duk_push_nan(thr);
87019 	return;
87020 
87021  parse_explimit_error:
87022 	DUK_DDD(DUK_DDDPRINT("parse failed, internal error, can't return a value"));
87023 	DUK_ERROR_RANGE(thr, "exponent too large");
87024 	DUK_WO_NORETURN(return;);
87025 }
87026 
87027 DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags) {
87028 	duk_native_stack_check(thr);
87029 	duk__numconv_parse_raw(thr, radix, flags);
87030 }
87031 
87032 /* automatic undefs */
87033 #undef DUK__BI_MAX_PARTS
87034 #undef DUK__BI_PRINT
87035 #undef DUK__DIGITCHAR
87036 #undef DUK__DRAGON4_OUTPUT_PREINC
87037 #undef DUK__IEEE_DOUBLE_EXP_BIAS
87038 #undef DUK__IEEE_DOUBLE_EXP_MIN
87039 #undef DUK__MAX_FORMATTED_LENGTH
87040 #undef DUK__MAX_OUTPUT_DIGITS
87041 #undef DUK__NO_EXP
87042 #undef DUK__NUMCONV_CTX_BIGINTS_SIZE
87043 #undef DUK__NUMCONV_CTX_NUM_BIGINTS
87044 /*
87045  *  Regexp compilation.
87046  *
87047  *  See doc/regexp.rst for a discussion of the compilation approach and
87048  *  current limitations.
87049  *
87050  *  Regexp bytecode assumes jumps can be expressed with signed 32-bit
87051  *  integers.  Consequently the bytecode size must not exceed 0x7fffffffL.
87052  *  The implementation casts duk_size_t (buffer size) to duk_(u)int32_t
87053  *  in many places.  Although this could be changed, the bytecode format
87054  *  limit would still prevent regexps exceeding the signed 32-bit limit
87055  *  from working.
87056  *
87057  *  XXX: The implementation does not prevent bytecode from exceeding the
87058  *  maximum supported size.  This could be done by limiting the maximum
87059  *  input string size (assuming an upper bound can be computed for number
87060  *  of bytecode bytes emitted per input byte) or checking buffer maximum
87061  *  size when emitting bytecode (slower).
87062  */
87063 
87064 /* #include duk_internal.h -> already included */
87065 
87066 #if defined(DUK_USE_REGEXP_SUPPORT)
87067 
87068 /*
87069  *  Helper macros
87070  */
87071 
87072 #define DUK__RE_INITIAL_BUFSIZE 64
87073 
87074 #define DUK__RE_BUFLEN(re_ctx) \
87075 	DUK_BW_GET_SIZE(re_ctx->thr, &re_ctx->bw)
87076 
87077 /*
87078  *  Disjunction struct: result of parsing a disjunction
87079  */
87080 
87081 typedef struct {
87082 	/* Number of characters that the atom matches (e.g. 3 for 'abc'),
87083 	 * -1 if atom is complex and number of matched characters either
87084 	 * varies or is not known.
87085 	 */
87086 	duk_int32_t charlen;
87087 
87088 #if 0
87089 	/* These are not needed to implement quantifier capture handling,
87090 	 * but might be needed at some point.
87091 	 */
87092 
87093 	/* re_ctx->captures at start and end of atom parsing.
87094 	 * Since 'captures' indicates highest capture number emitted
87095 	 * so far in a DUK_REOP_SAVE, the captures numbers saved by
87096 	 * the atom are: ]start_captures,end_captures].
87097 	 */
87098 	duk_uint32_t start_captures;
87099 	duk_uint32_t end_captures;
87100 #endif
87101 } duk__re_disjunction_info;
87102 
87103 /*
87104  *  Encoding helpers
87105  *
87106  *  Some of the typing is bytecode based, e.g. slice sizes are unsigned 32-bit
87107  *  even though the buffer operations will use duk_size_t.
87108  */
87109 
87110 /* XXX: the insert helpers should ensure that the bytecode result is not
87111  * larger than expected (or at least assert for it).  Many things in the
87112  * bytecode, like skip offsets, won't work correctly if the bytecode is
87113  * larger than say 2G.
87114  */
87115 
87116 DUK_LOCAL duk_uint32_t duk__encode_i32(duk_int32_t x) {
87117 	if (x < 0) {
87118 		return ((duk_uint32_t) (-x)) * 2 + 1;
87119 	} else {
87120 		return ((duk_uint32_t) x) * 2;
87121 	}
87122 }
87123 
87124 /* XXX: return type should probably be duk_size_t, or explicit checks are needed for
87125  * maximum size.
87126  */
87127 DUK_LOCAL duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x) {
87128 	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
87129 	duk_small_int_t len;
87130 
87131 	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) x, buf);
87132 	DUK_ASSERT(len >= 0);
87133 	DUK_BW_INSERT_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, offset, buf, (duk_size_t) len);
87134 	return (duk_uint32_t) len;
87135 }
87136 
87137 DUK_LOCAL void duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
87138 	DUK_BW_WRITE_ENSURE_XUTF8(re_ctx->thr, &re_ctx->bw, x);
87139 }
87140 
87141 DUK_LOCAL void duk__append_7bit(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
87142 #if defined(DUK_USE_PREFER_SIZE)
87143 	duk__append_u32(re_ctx, x);
87144 #else
87145 	DUK_ASSERT(x <= 0x7fU);
87146 	DUK_BW_WRITE_ENSURE_U8(re_ctx->thr, &re_ctx->bw, (duk_uint8_t) x);
87147 #endif
87148 }
87149 
87150 #if 0
87151 DUK_LOCAL void duk__append_2bytes(duk_re_compiler_ctx *re_ctx, duk_uint8_t x, duk_uint8_t y) {
87152 	DUK_BW_WRITE_ENSURE_U8_2(re_ctx->thr, &re_ctx->bw, x, y);
87153 }
87154 #endif
87155 
87156 DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x) {
87157 	return duk__insert_u32(re_ctx, offset, duk__encode_i32(x));
87158 }
87159 
87160 DUK_LOCAL void duk__append_reop(duk_re_compiler_ctx *re_ctx, duk_uint32_t reop) {
87161 	DUK_ASSERT(reop <= 0x7fU);
87162 	(void) duk__append_7bit(re_ctx, reop);
87163 }
87164 
87165 #if 0  /* unused */
87166 DUK_LOCAL void duk__append_i32(duk_re_compiler_ctx *re_ctx, duk_int32_t x) {
87167 	duk__append_u32(re_ctx, duk__encode_i32(x));
87168 }
87169 #endif
87170 
87171 /* special helper for emitting u16 lists (used for character ranges for built-in char classes) */
87172 DUK_LOCAL void duk__append_u16_list(duk_re_compiler_ctx *re_ctx, const duk_uint16_t *values, duk_uint32_t count) {
87173 	/* Call sites don't need the result length so it's not accumulated. */
87174 	while (count-- > 0) {
87175 		duk__append_u32(re_ctx, (duk_uint32_t) (*values++));
87176 	}
87177 }
87178 
87179 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) {
87180 	DUK_BW_INSERT_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, offset, data_offset, data_length);
87181 }
87182 
87183 DUK_LOCAL void duk__append_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
87184 	DUK_BW_WRITE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
87185 }
87186 
87187 DUK_LOCAL void duk__remove_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
87188 	DUK_BW_REMOVE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
87189 }
87190 
87191 /*
87192  *  Insert a jump offset at 'offset' to complete an instruction
87193  *  (the jump offset is always the last component of an instruction).
87194  *  The 'skip' argument must be computed relative to 'offset',
87195  *  -without- taking into account the skip field being inserted.
87196  *
87197  *       ... A B C ins X Y Z ...   (ins may be a JUMP, SPLIT1/SPLIT2, etc)
87198  *   =>  ... A B C ins SKIP X Y Z
87199  *
87200  *  Computing the final (adjusted) skip value, which is relative to the
87201  *  first byte of the next instruction, is a bit tricky because of the
87202  *  variable length UTF-8 encoding.  See doc/regexp.rst for discussion.
87203  */
87204 DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t skip) {
87205 #if 0
87206 	/* Iterative solution. */
87207 	if (skip < 0) {
87208 		duk_small_int_t len;
87209 		/* two encoding attempts suffices */
87210 		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip));
87211 		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip - (duk_int32_t) len));
87212 		DUK_ASSERT(duk_unicode_get_xutf8_length(duk__encode_i32(skip - (duk_int32_t) len)) == len);  /* no change */
87213 		skip -= (duk_int32_t) len;
87214 	}
87215 #endif
87216 
87217 #if defined(DUK_USE_PREFER_SIZE)
87218 	/* Closed form solution, this produces smallest code.
87219 	 * See re_neg_jump_offset (closed2).
87220 	 */
87221 	if (skip < 0) {
87222 		skip--;
87223 		if (skip < -0x3fL) {
87224 			skip--;
87225 		}
87226 		if (skip < -0x3ffL) {
87227 			skip--;
87228 		}
87229 		if (skip < -0x7fffL) {
87230 			skip--;
87231 		}
87232 		if (skip < -0xfffffL) {
87233 			skip--;
87234 		}
87235 		if (skip < -0x1ffffffL) {
87236 			skip--;
87237 		}
87238 		if (skip < -0x3fffffffL) {
87239 			skip--;
87240 		}
87241 	}
87242 #else  /* DUK_USE_PREFER_SIZE */
87243 	/* Closed form solution, this produces fastest code.
87244 	 * See re_neg_jump_offset (closed1).
87245 	 */
87246 	if (skip < 0) {
87247 		if (skip >= -0x3eL) {
87248 			skip -= 1;
87249 		} else if (skip >= -0x3fdL) {
87250 			skip -= 2;
87251 		} else if (skip >= -0x7ffcL) {
87252 			skip -= 3;
87253 		} else if (skip >= -0xffffbL) {
87254 			skip -= 4;
87255 		} else if (skip >= -0x1fffffaL) {
87256 			skip -= 5;
87257 		} else if (skip >= -0x3ffffff9L) {
87258 			skip -= 6;
87259 		} else {
87260 			skip -= 7;
87261 		}
87262 	}
87263 #endif  /* DUK_USE_PREFER_SIZE */
87264 
87265 	return duk__insert_i32(re_ctx, offset, skip);
87266 }
87267 
87268 DUK_LOCAL duk_uint32_t duk__append_jump_offset(duk_re_compiler_ctx *re_ctx, duk_int32_t skip) {
87269 	return (duk_uint32_t) duk__insert_jump_offset(re_ctx, (duk_uint32_t) DUK__RE_BUFLEN(re_ctx), skip);
87270 }
87271 
87272 /*
87273  *  duk_re_range_callback for generating character class ranges.
87274  *
87275  *  When ignoreCase is false, the range is simply emitted as is.  We don't,
87276  *  for instance, eliminate duplicates or overlapping ranges in a character
87277  *  class.
87278  *
87279  *  When ignoreCase is true but the 'direct' flag is set, the caller knows
87280  *  that the range canonicalizes to itself for case insensitive matching,
87281  *  so the range is emitted as is.  This is mainly useful for built-in ranges
87282  *  like \W.
87283  *
87284  *  Otherwise, when ignoreCase is true, the range needs to be normalized
87285  *  through canonicalization.  Unfortunately a canonicalized version of a
87286  *  continuous range is not necessarily continuous (e.g. [x-{] is continuous
87287  *  but [X-{] is not).  As a result, a single input range may expand to a lot
87288  *  of output ranges.  The current algorithm creates the canonicalized ranges
87289  *  footprint efficiently at the cost of compile time execution time; see
87290  *  doc/regexp.rst for discussion, and some more details below.
87291  *
87292  *  Note that the ctx->nranges is a context-wide temporary value.  This is OK
87293  *  because there cannot be multiple character classes being parsed
87294  *  simultaneously.
87295  *
87296  *  More detail on canonicalization:
87297  *
87298  *  Conceptually, a range is canonicalized by scanning the entire range,
87299  *  normalizing each codepoint by converting it to uppercase, and generating
87300  *  a set of result ranges.
87301  *
87302  *  Ideally a minimal set of output ranges would be emitted by merging all
87303  *  possible ranges even if they're emitted out of sequence.  Because the
87304  *  input string is also case normalized during matching, some codepoints
87305  *  never occur at runtime; these "don't care" codepoints can be included or
87306  *  excluded from ranges when merging/optimizing ranges.
87307  *
87308  *  The current algorithm does not do optimal range merging.  Rather, output
87309  *  codepoints are generated in sequence, and when the output codepoints are
87310  *  continuous (CP, CP+1, CP+2, ...), they are merged locally into as large a
87311  *  range as possible.  A small canonicalization bitmap is used to reduce
87312  *  actual codepoint canonicalizations which are quite slow at present.  The
87313  *  bitmap provides a "codepoint block is continuous with respect to
87314  *  canonicalization" for N-codepoint blocks.  This allows blocks to be
87315  *  skipped quickly.
87316  *
87317  *  There are a number of shortcomings and future work here:
87318  *
87319  *    - Individual codepoint normalizations are slow because they involve
87320  *      walking bit-packed rules without a lookup index.
87321  *
87322  *    - The conceptual algorithm needs to canonicalize every codepoint in the
87323  *      input range to figure out the output range(s).  Even with the small
87324  *      canonicalization bitmap the algorithm runs quite slowly for worst case
87325  *      inputs.  There are many data structure alternatives to improve this.
87326  *
87327  *    - While the current algorithm generates maximal output ranges when the
87328  *      output codepoints are emitted linearly, output ranges are not sorted or
87329  *      merged otherwise.  In the worst case a lot of ranges are emitted when
87330  *      most of the ranges could be merged.  In this process one could take
87331  *      advantage of "don't care" codepoints, which are never matched against at
87332  *      runtime due to canonicalization of input codepoints before comparison,
87333  *      to merge otherwise discontinuous output ranges.
87334  *
87335  *    - The runtime data structure is just a linear list of ranges to match
87336  *      against.  This can be quite slow if there are a lot of output ranges.
87337  *      There are various ways to make matching against the ranges faster,
87338  *      e.g. sorting the ranges and using a binary search; skip lists; tree
87339  *      based representations; full or approximate codepoint bitmaps, etc.
87340  *
87341  *    - Only BMP is supported, codepoints above BMP are assumed to canonicalize
87342  *      to themselves.  For now this is one place where we don't want to
87343  *      support chars outside the BMP, because the exhaustive search would be
87344  *      massively larger.  It would be possible to support non-BMP with a
87345  *      different algorithm, or perhaps doing case normalization only at match
87346  *      time.
87347  */
87348 
87349 DUK_LOCAL void duk__regexp_emit_range(duk_re_compiler_ctx *re_ctx, duk_codepoint_t r1, duk_codepoint_t r2) {
87350 	DUK_ASSERT(r2 >= r1);
87351 	duk__append_u32(re_ctx, (duk_uint32_t) r1);
87352 	duk__append_u32(re_ctx, (duk_uint32_t) r2);
87353 	re_ctx->nranges++;
87354 }
87355 
87356 #if defined(DUK_USE_REGEXP_CANON_BITMAP)
87357 /* Find next canonicalization discontinuity (conservative estimate) starting
87358  * from 'start', not exceeding 'end'.  If continuity is fine up to 'end'
87359  * inclusive, returns end.  Minimum possible return value is start.
87360  */
87361 DUK_LOCAL duk_codepoint_t duk__re_canon_next_discontinuity(duk_codepoint_t start, duk_codepoint_t end) {
87362 	duk_uint_t start_blk;
87363 	duk_uint_t end_blk;
87364 	duk_uint_t blk;
87365 	duk_uint_t offset;
87366 	duk_uint8_t mask;
87367 
87368 	/* Inclusive block range. */
87369 	DUK_ASSERT(start >= 0);
87370 	DUK_ASSERT(end >= 0);
87371 	DUK_ASSERT(end >= start);
87372 	start_blk = (duk_uint_t) (start >> DUK_CANON_BITMAP_BLKSHIFT);
87373 	end_blk = (duk_uint_t) (end >> DUK_CANON_BITMAP_BLKSHIFT);
87374 
87375 	for (blk = start_blk; blk <= end_blk; blk++) {
87376 		offset = blk >> 3;
87377 		mask = 1U << (blk & 0x07);
87378 		if (offset >= sizeof(duk_unicode_re_canon_bitmap)) {
87379 			/* Reached non-BMP range which is assumed continuous. */
87380 			return end;
87381 		}
87382 		DUK_ASSERT(offset < sizeof(duk_unicode_re_canon_bitmap));
87383 		if ((duk_unicode_re_canon_bitmap[offset] & mask) == 0) {
87384 			/* Block is discontinuous, continuity is guaranteed
87385 			 * only up to end of previous block (+1 for exclusive
87386 			 * return value => start of current block).  Start
87387 			 * block requires special handling.
87388 			 */
87389 			if (blk > start_blk) {
87390 				return (duk_codepoint_t) (blk << DUK_CANON_BITMAP_BLKSHIFT);
87391 			} else {
87392 				return start;
87393 			}
87394 		}
87395 	}
87396 	DUK_ASSERT(blk == end_blk + 1);  /* Reached end block which is continuous. */
87397 	return end;
87398 }
87399 #else  /* DUK_USE_REGEXP_CANON_BITMAP */
87400 DUK_LOCAL duk_codepoint_t duk__re_canon_next_discontinuity(duk_codepoint_t start, duk_codepoint_t end) {
87401 	DUK_ASSERT(start >= 0);
87402 	DUK_ASSERT(end >= 0);
87403 	DUK_ASSERT(end >= start);
87404 	if (start >= 0x10000) {
87405 		/* Even without the bitmap, treat non-BMP as continuous. */
87406 		return end;
87407 	}
87408 	return start;
87409 }
87410 #endif  /* DUK_USE_REGEXP_CANON_BITMAP */
87411 
87412 DUK_LOCAL void duk__regexp_generate_ranges(void *userdata, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct) {
87413 	duk_re_compiler_ctx *re_ctx = (duk_re_compiler_ctx *) userdata;
87414 	duk_codepoint_t r_start;
87415 	duk_codepoint_t r_end;
87416 	duk_codepoint_t i;
87417 	duk_codepoint_t t;
87418 	duk_codepoint_t r_disc;
87419 
87420 	DUK_DD(DUK_DDPRINT("duk__regexp_generate_ranges(): re_ctx=%p, range=[%ld,%ld] direct=%ld",
87421 	                   (void *) re_ctx, (long) r1, (long) r2, (long) direct));
87422 
87423 	DUK_ASSERT(r2 >= r1);  /* SyntaxError for out of order range. */
87424 
87425 	if (direct || (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) == 0) {
87426 		DUK_DD(DUK_DDPRINT("direct or not case sensitive, emit range: [%ld,%ld]", (long) r1, (long) r2));
87427 		duk__regexp_emit_range(re_ctx, r1, r2);
87428 		return;
87429 	}
87430 
87431 	DUK_DD(DUK_DDPRINT("case sensitive, process range: [%ld,%ld]", (long) r1, (long) r2));
87432 
87433 	r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
87434 	r_end = r_start;
87435 
87436 	for (i = r1 + 1; i <= r2;) {
87437 		/* Input codepoint space processed up to i-1, and
87438 		 * current range in r_{start,end} is up-to-date
87439 		 * (inclusive) and may either break or continue.
87440 		 */
87441 		r_disc = duk__re_canon_next_discontinuity(i, r2);
87442 		DUK_ASSERT(r_disc >= i);
87443 		DUK_ASSERT(r_disc <= r2);
87444 
87445 		r_end += r_disc - i;  /* May be zero. */
87446 		t = duk_unicode_re_canonicalize_char(re_ctx->thr, r_disc);
87447 		if (t == r_end + 1) {
87448 			/* Not actually a discontinuity, continue range
87449 			 * to r_disc and recheck.
87450 			 */
87451 			r_end = t;
87452 		} else {
87453 			duk__regexp_emit_range(re_ctx, r_start, r_end);
87454 			r_start = t;
87455 			r_end = t;
87456 		}
87457 		i = r_disc + 1;  /* Guarantees progress. */
87458 	}
87459 	duk__regexp_emit_range(re_ctx, r_start, r_end);
87460 
87461 #if 0  /* Exhaustive search, very slow. */
87462 	r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
87463 	r_end = r_start;
87464 	for (i = r1 + 1; i <= r2; i++) {
87465 		t = duk_unicode_re_canonicalize_char(re_ctx->thr, i);
87466 		if (t == r_end + 1) {
87467 			r_end = t;
87468 		} else {
87469 			DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
87470 			duk__append_u32(re_ctx, (duk_uint32_t) r_start);
87471 			duk__append_u32(re_ctx, (duk_uint32_t) r_end);
87472 			re_ctx->nranges++;
87473 			r_start = t;
87474 			r_end = t;
87475 		}
87476 	}
87477 	DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
87478 	duk__append_u32(re_ctx, (duk_uint32_t) r_start);
87479 	duk__append_u32(re_ctx, (duk_uint32_t) r_end);
87480 	re_ctx->nranges++;
87481 #endif
87482 }
87483 
87484 /*
87485  *  Parse regexp Disjunction.  Most of regexp compilation happens here.
87486  *
87487  *  Handles Disjunction, Alternative, and Term productions directly without
87488  *  recursion.  The only constructs requiring recursion are positive/negative
87489  *  lookaheads, capturing parentheses, and non-capturing parentheses.
87490  *
87491  *  The function determines whether the entire disjunction is a 'simple atom'
87492  *  (see doc/regexp.rst discussion on 'simple quantifiers') and if so,
87493  *  returns the atom character length which is needed by the caller to keep
87494  *  track of its own atom character length.  A disjunction with more than one
87495  *  alternative is never considered a simple atom (although in some cases
87496  *  that might be the case).
87497  *
87498  *  Return value: simple atom character length or < 0 if not a simple atom.
87499  *  Appends the bytecode for the disjunction matcher to the end of the temp
87500  *  buffer.
87501  *
87502  *  Regexp top level structure is:
87503  *
87504  *    Disjunction = Term*
87505  *                | Term* | Disjunction
87506  *
87507  *    Term = Assertion
87508  *         | Atom
87509  *         | Atom Quantifier
87510  *
87511  *  An empty Term sequence is a valid disjunction alternative (e.g. /|||c||/).
87512  *
87513  *  Notes:
87514  *
87515  *    * Tracking of the 'simple-ness' of the current atom vs. the entire
87516  *      disjunction are separate matters.  For instance, the disjunction
87517  *      may be complex, but individual atoms may be simple.  Furthermore,
87518  *      simple quantifiers are used whenever possible, even if the
87519  *      disjunction as a whole is complex.
87520  *
87521  *    * The estimate of whether an atom is simple is conservative now,
87522  *      and it would be possible to expand it.  For instance, captures
87523  *      cause the disjunction to be marked complex, even though captures
87524  *      -can- be handled by simple quantifiers with some minor modifications.
87525  *
87526  *    * Disjunction 'tainting' as 'complex' is handled at the end of the
87527  *      main for loop collectively for atoms.  Assertions, quantifiers,
87528  *      and '|' tokens need to taint the result manually if necessary.
87529  *      Assertions cannot add to result char length, only atoms (and
87530  *      quantifiers) can; currently quantifiers will taint the result
87531  *      as complex though.
87532  */
87533 
87534 DUK_LOCAL const duk_uint16_t * const duk__re_range_lookup1[3] = {
87535 	duk_unicode_re_ranges_digit,
87536 	duk_unicode_re_ranges_white,
87537 	duk_unicode_re_ranges_wordchar
87538 };
87539 DUK_LOCAL const duk_uint8_t duk__re_range_lookup2[3] = {
87540 	sizeof(duk_unicode_re_ranges_digit) / (2 * sizeof(duk_uint16_t)),
87541 	sizeof(duk_unicode_re_ranges_white) / (2 * sizeof(duk_uint16_t)),
87542 	sizeof(duk_unicode_re_ranges_wordchar) / (2 * sizeof(duk_uint16_t))
87543 };
87544 
87545 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) {
87546 #if 0
87547 	DUK_ASSERT(re_op <= 0x7fUL);
87548 	DUK_ASSERT(count <= 0x7fUL);
87549 	duk__append_2bytes(re_ctx, (duk_uint8_t) re_op, (duk_uint8_t) count);
87550 #endif
87551 	duk__append_reop(re_ctx, re_op);
87552 	duk__append_7bit(re_ctx, count);
87553 	duk__append_u16_list(re_ctx, ranges, count * 2);
87554 }
87555 
87556 DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t expect_eof, duk__re_disjunction_info *out_atom_info) {
87557 	duk_int32_t atom_start_offset = -1;                   /* negative -> no atom matched on previous round */
87558 	duk_int32_t atom_char_length = 0;                     /* negative -> complex atom */
87559 	duk_uint32_t atom_start_captures = re_ctx->captures;  /* value of re_ctx->captures at start of atom */
87560 	duk_int32_t unpatched_disjunction_split = -1;
87561 	duk_int32_t unpatched_disjunction_jump = -1;
87562 	duk_uint32_t entry_offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
87563 	duk_int32_t res_charlen = 0;  /* -1 if disjunction is complex, char length if simple */
87564 	duk__re_disjunction_info tmp_disj;
87565 
87566 	DUK_ASSERT(out_atom_info != NULL);
87567 
87568 	duk_native_stack_check(re_ctx->thr);
87569 	if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
87570 		DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT);
87571 		DUK_WO_NORETURN(return;);
87572 	}
87573 	re_ctx->recursion_depth++;
87574 
87575 #if 0
87576 	out_atom_info->start_captures = re_ctx->captures;
87577 #endif
87578 
87579 	for (;;) {
87580 		/* atom_char_length, atom_start_offset, atom_start_offset reflect the
87581 		 * atom matched on the previous loop.  If a quantifier is encountered
87582 		 * on this loop, these are needed to handle the quantifier correctly.
87583 		 * new_atom_char_length etc are for the atom parsed on this round;
87584 		 * they're written to atom_char_length etc at the end of the round.
87585 		 */
87586 		duk_int32_t new_atom_char_length;   /* char length of the atom parsed in this loop */
87587 		duk_int32_t new_atom_start_offset;  /* bytecode start offset of the atom parsed in this loop
87588 		                                     * (allows quantifiers to copy the atom bytecode)
87589 		                                     */
87590 		duk_uint32_t new_atom_start_captures;  /* re_ctx->captures at the start of the atom parsed in this loop */
87591 
87592 		duk_lexer_parse_re_token(&re_ctx->lex, &re_ctx->curr_token);
87593 
87594 		DUK_DD(DUK_DDPRINT("re token: %ld (num=%ld, char=%c)",
87595 		                   (long) re_ctx->curr_token.t,
87596 		                   (long) re_ctx->curr_token.num,
87597 		                   (re_ctx->curr_token.num >= 0x20 && re_ctx->curr_token.num <= 0x7e) ?
87598 		                   (int) re_ctx->curr_token.num : (int) '?'));
87599 
87600 		/* set by atom case clauses */
87601 		new_atom_start_offset = -1;
87602 		new_atom_char_length = -1;
87603 		new_atom_start_captures = re_ctx->captures;
87604 
87605 		switch (re_ctx->curr_token.t) {
87606 		case DUK_RETOK_DISJUNCTION: {
87607 			/*
87608 			 *  The handling here is a bit tricky.  If a previous '|' has been processed,
87609 			 *  we have a pending split1 and a pending jump (for a previous match).  These
87610 			 *  need to be back-patched carefully.  See docs for a detailed example.
87611 			 */
87612 
87613 			/* patch pending jump and split */
87614 			if (unpatched_disjunction_jump >= 0) {
87615 				duk_uint32_t offset;
87616 
87617 				DUK_ASSERT(unpatched_disjunction_split >= 0);
87618 				offset = (duk_uint32_t) unpatched_disjunction_jump;
87619 				offset += duk__insert_jump_offset(re_ctx,
87620 				                                  offset,
87621 				                                  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
87622 				/* offset is now target of the pending split (right after jump) */
87623 				duk__insert_jump_offset(re_ctx,
87624 				                        (duk_uint32_t) unpatched_disjunction_split,
87625 				                        (duk_int32_t) offset - unpatched_disjunction_split);
87626 			}
87627 
87628 			/* add a new pending split to the beginning of the entire disjunction */
87629 			(void) duk__insert_u32(re_ctx,
87630 			                       entry_offset,
87631 			                       DUK_REOP_SPLIT1);   /* prefer direct execution */
87632 			unpatched_disjunction_split = (duk_int32_t) (entry_offset + 1);   /* +1 for opcode */
87633 
87634 			/* add a new pending match jump for latest finished alternative */
87635 			duk__append_reop(re_ctx, DUK_REOP_JUMP);
87636 			unpatched_disjunction_jump = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87637 
87638 			/* 'taint' result as complex */
87639 			res_charlen = -1;
87640 			break;
87641 		}
87642 		case DUK_RETOK_QUANTIFIER: {
87643 			if (atom_start_offset < 0) {
87644 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_NO_ATOM);
87645 				DUK_WO_NORETURN(return;);
87646 			}
87647 			if (re_ctx->curr_token.qmin > re_ctx->curr_token.qmax) {
87648 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_VALUES);
87649 				DUK_WO_NORETURN(return;);
87650 			}
87651 			if (atom_char_length >= 0) {
87652 				/*
87653 				 *  Simple atom
87654 				 *
87655 				 *  If atom_char_length is zero, we'll have unbounded execution time for e.g.
87656 				 *  /()*x/.exec('x').  We can't just skip the match because it might have some
87657 				 *  side effects (for instance, if we allowed captures in simple atoms, the
87658 				 *  capture needs to happen).  The simple solution below is to force the
87659 				 *  quantifier to match at most once, since the additional matches have no effect.
87660 				 *
87661 				 *  With a simple atom there can be no capture groups, so no captures need
87662 				 *  to be reset.
87663 				 */
87664 				duk_int32_t atom_code_length;
87665 				duk_uint32_t offset;
87666 				duk_uint32_t qmin, qmax;
87667 
87668 				qmin = re_ctx->curr_token.qmin;
87669 				qmax = re_ctx->curr_token.qmax;
87670 				if (atom_char_length == 0) {
87671 					/* qmin and qmax will be 0 or 1 */
87672 					if (qmin > 1) {
87673 						qmin = 1;
87674 					}
87675 					if (qmax > 1) {
87676 						qmax = 1;
87677 					}
87678 				}
87679 
87680 				duk__append_reop(re_ctx, DUK_REOP_MATCH);   /* complete 'sub atom' */
87681 				atom_code_length = (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (duk_size_t) atom_start_offset);
87682 
87683 				offset = (duk_uint32_t) atom_start_offset;
87684 				if (re_ctx->curr_token.greedy) {
87685 					offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQGREEDY);
87686 					offset += duk__insert_u32(re_ctx, offset, qmin);
87687 					offset += duk__insert_u32(re_ctx, offset, qmax);
87688 					offset += duk__insert_u32(re_ctx, offset, (duk_uint32_t) atom_char_length);
87689 					offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
87690 				} else {
87691 					offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQMINIMAL);
87692 					offset += duk__insert_u32(re_ctx, offset, qmin);
87693 					offset += duk__insert_u32(re_ctx, offset, qmax);
87694 					offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
87695 				}
87696 				DUK_UNREF(offset);  /* silence scan-build warning */
87697 			} else {
87698 				/*
87699 				 *  Complex atom
87700 				 *
87701 				 *  The original code is used as a template, and removed at the end
87702 				 *  (this differs from the handling of simple quantifiers).
87703 				 *
87704 				 *  NOTE: there is no current solution for empty atoms in complex
87705 				 *  quantifiers.  This would need some sort of a 'progress' instruction.
87706 				 *
87707 				 *  XXX: impose limit on maximum result size, i.e. atom_code_len * atom_copies?
87708 				 */
87709 				duk_int32_t atom_code_length;
87710 				duk_uint32_t atom_copies;
87711 				duk_uint32_t tmp_qmin, tmp_qmax;
87712 
87713 				/* pre-check how many atom copies we're willing to make (atom_copies not needed below) */
87714 				atom_copies = (re_ctx->curr_token.qmax == DUK_RE_QUANTIFIER_INFINITE) ?
87715 				              re_ctx->curr_token.qmin : re_ctx->curr_token.qmax;
87716 				if (atom_copies > DUK_RE_MAX_ATOM_COPIES) {
87717 					DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_QUANTIFIER_TOO_MANY_COPIES);
87718 					DUK_WO_NORETURN(return;);
87719 				}
87720 
87721 				/* wipe the capture range made by the atom (if any) */
87722 				DUK_ASSERT(atom_start_captures <= re_ctx->captures);
87723 				if (atom_start_captures != re_ctx->captures) {
87724 					DUK_ASSERT(atom_start_captures < re_ctx->captures);
87725 					DUK_DDD(DUK_DDDPRINT("must wipe ]atom_start_captures,re_ctx->captures]: ]%ld,%ld]",
87726 					                     (long) atom_start_captures, (long) re_ctx->captures));
87727 
87728 					/* insert (DUK_REOP_WIPERANGE, start, count) in reverse order so the order ends up right */
87729 					duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, (re_ctx->captures - atom_start_captures) * 2U);
87730 					duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, (atom_start_captures + 1) * 2);
87731 					duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, DUK_REOP_WIPERANGE);
87732 				} else {
87733 					DUK_DDD(DUK_DDDPRINT("no need to wipe captures: atom_start_captures == re_ctx->captures == %ld",
87734 					                     (long) atom_start_captures));
87735 				}
87736 
87737 				atom_code_length = (duk_int32_t) DUK__RE_BUFLEN(re_ctx) - atom_start_offset;
87738 
87739 				/* insert the required matches (qmin) by copying the atom */
87740 				tmp_qmin = re_ctx->curr_token.qmin;
87741 				tmp_qmax = re_ctx->curr_token.qmax;
87742 				while (tmp_qmin > 0) {
87743 					duk__append_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
87744 					tmp_qmin--;
87745 					if (tmp_qmax != DUK_RE_QUANTIFIER_INFINITE) {
87746 						tmp_qmax--;
87747 					}
87748 				}
87749 				DUK_ASSERT(tmp_qmin == 0);
87750 
87751 				/* insert code for matching the remainder - infinite or finite */
87752 				if (tmp_qmax == DUK_RE_QUANTIFIER_INFINITE) {
87753 					/* reuse last emitted atom for remaining 'infinite' quantifier */
87754 
87755 					if (re_ctx->curr_token.qmin == 0) {
87756 						/* Special case: original qmin was zero so there is nothing
87757 						 * to repeat.  Emit an atom copy but jump over it here.
87758 						 */
87759 						duk__append_reop(re_ctx, DUK_REOP_JUMP);
87760 						duk__append_jump_offset(re_ctx, atom_code_length);
87761 						duk__append_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
87762 					}
87763 					if (re_ctx->curr_token.greedy) {
87764 						duk__append_reop(re_ctx, DUK_REOP_SPLIT2);   /* prefer jump */
87765 					} else {
87766 						duk__append_reop(re_ctx, DUK_REOP_SPLIT1);   /* prefer direct */
87767 					}
87768 					duk__append_jump_offset(re_ctx, -atom_code_length - 1);  /* -1 for opcode */
87769 				} else {
87770 					/*
87771 					 *  The remaining matches are emitted as sequence of SPLITs and atom
87772 					 *  copies; the SPLITs skip the remaining copies and match the sequel.
87773 					 *  This sequence needs to be emitted starting from the last copy
87774 					 *  because the SPLITs are variable length due to the variable length
87775 					 *  skip offset.  This causes a lot of memory copying now.
87776 					 *
87777 					 *  Example structure (greedy, match maximum # atoms):
87778 					 *
87779 					 *      SPLIT1 LSEQ
87780 					 *      (atom)
87781 					 *      SPLIT1 LSEQ    ; <- the byte length of this instruction is needed
87782 					 *      (atom)         ; to encode the above SPLIT1 correctly
87783 					 *      ...
87784 					 *   LSEQ:
87785 					 */
87786 					duk_uint32_t offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
87787 					while (tmp_qmax > 0) {
87788 						duk__insert_slice(re_ctx, offset, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
87789 						if (re_ctx->curr_token.greedy) {
87790 							duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT1);   /* prefer direct */
87791 						} else {
87792 							duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT2);   /* prefer jump */
87793 						}
87794 						duk__insert_jump_offset(re_ctx,
87795 						                        offset + 1,   /* +1 for opcode */
87796 						                        (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
87797 						tmp_qmax--;
87798 					}
87799 				}
87800 
87801 				/* remove the original 'template' atom */
87802 				duk__remove_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
87803 			}
87804 
87805 			/* 'taint' result as complex */
87806 			res_charlen = -1;
87807 			break;
87808 		}
87809 		case DUK_RETOK_ASSERT_START: {
87810 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_START);
87811 			break;
87812 		}
87813 		case DUK_RETOK_ASSERT_END: {
87814 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_END);
87815 			break;
87816 		}
87817 		case DUK_RETOK_ASSERT_WORD_BOUNDARY: {
87818 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_WORD_BOUNDARY);
87819 			break;
87820 		}
87821 		case DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY: {
87822 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
87823 			break;
87824 		}
87825 		case DUK_RETOK_ASSERT_START_POS_LOOKAHEAD:
87826 		case DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD: {
87827 			duk_uint32_t offset;
87828 			duk_uint32_t opcode = (re_ctx->curr_token.t == DUK_RETOK_ASSERT_START_POS_LOOKAHEAD) ?
87829 			                      DUK_REOP_LOOKPOS : DUK_REOP_LOOKNEG;
87830 
87831 			offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
87832 			duk__parse_disjunction(re_ctx, 0, &tmp_disj);
87833 			duk__append_reop(re_ctx, DUK_REOP_MATCH);
87834 
87835 			(void) duk__insert_u32(re_ctx, offset, opcode);
87836 			(void) duk__insert_jump_offset(re_ctx,
87837 			                               offset + 1,   /* +1 for opcode */
87838 			                               (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
87839 
87840 			/* 'taint' result as complex -- this is conservative,
87841 			 * as lookaheads do not backtrack.
87842 			 */
87843 			res_charlen = -1;
87844 			break;
87845 		}
87846 		case DUK_RETOK_ATOM_PERIOD: {
87847 			new_atom_char_length = 1;
87848 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87849 			duk__append_reop(re_ctx, DUK_REOP_PERIOD);
87850 			break;
87851 		}
87852 		case DUK_RETOK_ATOM_CHAR: {
87853 			/* Note: successive characters could be joined into string matches
87854 			 * but this is not trivial (consider e.g. '/xyz+/); see docs for
87855 			 * more discussion.
87856 			 *
87857 			 * No support for \u{H+} yet.  While only BMP Unicode escapes are
87858 			 * supported for RegExps at present, 'ch' may still be a non-BMP
87859 			 * codepoint if it is decoded straight from source text UTF-8.
87860 			 * There's no non-BMP support yet so this is handled simply by
87861 			 * matching the non-BMP character (which is custom behavior).
87862 			 */
87863 			duk_uint32_t ch;
87864 
87865 			new_atom_char_length = 1;
87866 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87867 			duk__append_reop(re_ctx, DUK_REOP_CHAR);
87868 			ch = re_ctx->curr_token.num;
87869 			if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
87870 				ch = (duk_uint32_t) duk_unicode_re_canonicalize_char(re_ctx->thr, (duk_codepoint_t) ch);
87871 			}
87872 			duk__append_u32(re_ctx, ch);
87873 			break;
87874 		}
87875 		case DUK_RETOK_ATOM_DIGIT:
87876 		case DUK_RETOK_ATOM_NOT_DIGIT:
87877 		case DUK_RETOK_ATOM_WHITE:
87878 		case DUK_RETOK_ATOM_NOT_WHITE:
87879 		case DUK_RETOK_ATOM_WORD_CHAR:
87880 		case DUK_RETOK_ATOM_NOT_WORD_CHAR: {
87881 			duk_small_uint_t re_op;
87882 			duk_small_uint_t idx;
87883 
87884 			new_atom_char_length = 1;
87885 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87886 
87887 			DUK_ASSERT((DUK_RETOK_ATOM_DIGIT & 0x01) != 0);
87888 			DUK_ASSERT((DUK_RETOK_ATOM_WHITE & 0x01) != 0);
87889 			DUK_ASSERT((DUK_RETOK_ATOM_WORD_CHAR & 0x01) != 0);
87890 			DUK_ASSERT((DUK_RETOK_ATOM_NOT_DIGIT & 0x01) == 0);
87891 			DUK_ASSERT((DUK_RETOK_ATOM_NOT_WHITE & 0x01) == 0);
87892 			DUK_ASSERT((DUK_RETOK_ATOM_NOT_WORD_CHAR & 0x01) == 0);
87893 			re_op = (re_ctx->curr_token.t & 0x01) ? DUK_REOP_RANGES : DUK_REOP_INVRANGES;
87894 
87895 			DUK_ASSERT(DUK_RETOK_ATOM_WHITE == DUK_RETOK_ATOM_DIGIT + 2);
87896 			DUK_ASSERT(DUK_RETOK_ATOM_WORD_CHAR == DUK_RETOK_ATOM_DIGIT + 4);
87897 			idx = (duk_small_uint_t) ((re_ctx->curr_token.t - DUK_RETOK_ATOM_DIGIT) >> 1U);
87898 			DUK_ASSERT(idx <= 2U);  /* Assume continuous token numbers; also checks negative underflow. */
87899 
87900 			duk__append_range_atom_matcher(re_ctx, re_op, duk__re_range_lookup1[idx], duk__re_range_lookup2[idx]);
87901 			break;
87902 		}
87903 		case DUK_RETOK_ATOM_BACKREFERENCE: {
87904 			duk_uint32_t backref = (duk_uint32_t) re_ctx->curr_token.num;
87905 			if (backref > re_ctx->highest_backref) {
87906 				re_ctx->highest_backref = backref;
87907 			}
87908 			new_atom_char_length = -1;   /* mark as complex */
87909 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87910 			duk__append_reop(re_ctx, DUK_REOP_BACKREFERENCE);
87911 			duk__append_u32(re_ctx, backref);
87912 			break;
87913 		}
87914 		case DUK_RETOK_ATOM_START_CAPTURE_GROUP: {
87915 			duk_uint32_t cap;
87916 
87917 			new_atom_char_length = -1;   /* mark as complex (capture handling) */
87918 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87919 			cap = ++re_ctx->captures;
87920 			duk__append_reop(re_ctx, DUK_REOP_SAVE);
87921 			duk__append_u32(re_ctx, cap * 2);
87922 			duk__parse_disjunction(re_ctx, 0, &tmp_disj);  /* retval (sub-atom char length) unused, tainted as complex above */
87923 			duk__append_reop(re_ctx, DUK_REOP_SAVE);
87924 			duk__append_u32(re_ctx, cap * 2 + 1);
87925 			break;
87926 		}
87927 		case DUK_RETOK_ATOM_START_NONCAPTURE_GROUP: {
87928 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87929 			duk__parse_disjunction(re_ctx, 0, &tmp_disj);
87930 			new_atom_char_length = tmp_disj.charlen;
87931 			break;
87932 		}
87933 		case DUK_RETOK_ATOM_START_CHARCLASS:
87934 		case DUK_RETOK_ATOM_START_CHARCLASS_INVERTED: {
87935 			/*
87936 			 *  Range parsing is done with a special lexer function which calls
87937 			 *  us for every range parsed.  This is different from how rest of
87938 			 *  the parsing works, but avoids a heavy, arbitrary size intermediate
87939 			 *  value type to hold the ranges.
87940 			 *
87941 			 *  Another complication is the handling of character ranges when
87942 			 *  case insensitive matching is used (see docs for discussion).
87943 			 *  The range handler callback given to the lexer takes care of this
87944 			 *  as well.
87945 			 *
87946 			 *  Note that duplicate ranges are not eliminated when parsing character
87947 			 *  classes, so that canonicalization of
87948 			 *
87949 			 *    [0-9a-fA-Fx-{]
87950 			 *
87951 			 *  creates the result (note the duplicate ranges):
87952 			 *
87953 			 *    [0-9A-FA-FX-Z{-{]
87954 			 *
87955 			 *  where [x-{] is split as a result of canonicalization.  The duplicate
87956 			 *  ranges are not a semantics issue: they work correctly.
87957 			 */
87958 
87959 			duk_uint32_t offset;
87960 
87961 			DUK_DD(DUK_DDPRINT("character class"));
87962 
87963 			/* insert ranges instruction, range count patched in later */
87964 			new_atom_char_length = 1;
87965 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87966 			duk__append_reop(re_ctx,
87967 			                 (re_ctx->curr_token.t == DUK_RETOK_ATOM_START_CHARCLASS) ?
87968 			                 DUK_REOP_RANGES : DUK_REOP_INVRANGES);
87969 			offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);    /* patch in range count later */
87970 
87971 			/* parse ranges until character class ends */
87972 			re_ctx->nranges = 0;    /* note: ctx-wide temporary */
87973 			duk_lexer_parse_re_ranges(&re_ctx->lex, duk__regexp_generate_ranges, (void *) re_ctx);
87974 
87975 			/* insert range count */
87976 			duk__insert_u32(re_ctx, offset, re_ctx->nranges);
87977 			break;
87978 		}
87979 		case DUK_RETOK_ATOM_END_GROUP: {
87980 			if (expect_eof) {
87981 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_CLOSING_PAREN);
87982 				DUK_WO_NORETURN(return;);
87983 			}
87984 			goto done;
87985 		}
87986 		case DUK_RETOK_EOF: {
87987 			if (!expect_eof) {
87988 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_END_OF_PATTERN);
87989 				DUK_WO_NORETURN(return;);
87990 			}
87991 			goto done;
87992 		}
87993 		default: {
87994 			DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_REGEXP_TOKEN);
87995 			DUK_WO_NORETURN(return;);
87996 		}
87997 		}
87998 
87999 		/* a complex (new) atom taints the result */
88000 		if (new_atom_start_offset >= 0) {
88001 			if (new_atom_char_length < 0) {
88002 				res_charlen = -1;
88003 			} else if (res_charlen >= 0) {
88004 				/* only advance if not tainted */
88005 				res_charlen += new_atom_char_length;
88006 			}
88007 		}
88008 
88009 		/* record previous atom info in case next token is a quantifier */
88010 		atom_start_offset = new_atom_start_offset;
88011 		atom_char_length = new_atom_char_length;
88012 		atom_start_captures = new_atom_start_captures;
88013 	}
88014 
88015  done:
88016 
88017 	/* finish up pending jump and split for last alternative */
88018 	if (unpatched_disjunction_jump >= 0) {
88019 		duk_uint32_t offset;
88020 
88021 		DUK_ASSERT(unpatched_disjunction_split >= 0);
88022 		offset = (duk_uint32_t) unpatched_disjunction_jump;
88023 		offset += duk__insert_jump_offset(re_ctx,
88024 		                                  offset,
88025 		                                  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
88026 		/* offset is now target of the pending split (right after jump) */
88027 		duk__insert_jump_offset(re_ctx,
88028 		                        (duk_uint32_t) unpatched_disjunction_split,
88029 		                        (duk_int32_t) offset - unpatched_disjunction_split);
88030 	}
88031 
88032 #if 0
88033 	out_atom_info->end_captures = re_ctx->captures;
88034 #endif
88035 	out_atom_info->charlen = res_charlen;
88036 	DUK_DDD(DUK_DDDPRINT("parse disjunction finished: charlen=%ld",
88037 	                     (long) out_atom_info->charlen));
88038 
88039 	re_ctx->recursion_depth--;
88040 }
88041 
88042 /*
88043  *  Flags parsing (see E5 Section 15.10.4.1).
88044  */
88045 
88046 DUK_LOCAL duk_uint32_t duk__parse_regexp_flags(duk_hthread *thr, duk_hstring *h) {
88047 	const duk_uint8_t *p;
88048 	const duk_uint8_t *p_end;
88049 	duk_uint32_t flags = 0;
88050 
88051 	p = DUK_HSTRING_GET_DATA(h);
88052 	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
88053 
88054 	/* Note: can be safely scanned as bytes (undecoded) */
88055 
88056 	while (p < p_end) {
88057 		duk_uint8_t c = *p++;
88058 		switch (c) {
88059 		case (duk_uint8_t) 'g': {
88060 			if (flags & DUK_RE_FLAG_GLOBAL) {
88061 				goto flags_error;
88062 			}
88063 			flags |= DUK_RE_FLAG_GLOBAL;
88064 			break;
88065 		}
88066 		case (duk_uint8_t) 'i': {
88067 			if (flags & DUK_RE_FLAG_IGNORE_CASE) {
88068 				goto flags_error;
88069 			}
88070 			flags |= DUK_RE_FLAG_IGNORE_CASE;
88071 			break;
88072 		}
88073 		case (duk_uint8_t) 'm': {
88074 			if (flags & DUK_RE_FLAG_MULTILINE) {
88075 				goto flags_error;
88076 			}
88077 			flags |= DUK_RE_FLAG_MULTILINE;
88078 			break;
88079 		}
88080 		default: {
88081 			goto flags_error;
88082 		}
88083 		}
88084 	}
88085 
88086 	return flags;
88087 
88088  flags_error:
88089 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_REGEXP_FLAGS);
88090 	DUK_WO_NORETURN(return 0U;);
88091 }
88092 
88093 /*
88094  *  Create escaped RegExp source (E5 Section 15.10.3).
88095  *
88096  *  The current approach is to special case the empty RegExp
88097  *  ('' -> '(?:)') and otherwise replace unescaped '/' characters
88098  *  with '\/' regardless of where they occur in the regexp.
88099  *
88100  *  Note that normalization does not seem to be necessary for
88101  *  RegExp literals (e.g. '/foo/') because to be acceptable as
88102  *  a RegExp literal, the text between forward slashes must
88103  *  already match the escaping requirements (e.g. must not contain
88104  *  unescaped forward slashes or be empty).  Escaping IS needed
88105  *  for expressions like 'new Regexp("...", "")' however.
88106  *  Currently, we re-escape in either case.
88107  *
88108  *  Also note that we process the source here in UTF-8 encoded
88109  *  form.  This is correct, because any non-ASCII characters are
88110  *  passed through without change.
88111  */
88112 
88113 DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) {
88114 	duk_hstring *h;
88115 	const duk_uint8_t *p;
88116 	duk_bufwriter_ctx bw_alloc;
88117 	duk_bufwriter_ctx *bw;
88118 	duk_uint8_t *q;
88119 	duk_size_t i, n;
88120 	duk_uint_fast8_t c_prev, c;
88121 
88122 	h = duk_known_hstring(thr, idx_pattern);
88123 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
88124 	n = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
88125 
88126 	if (n == 0) {
88127 		duk_push_literal(thr, "(?:)");
88128 		return;
88129 	}
88130 
88131 	bw = &bw_alloc;
88132 	DUK_BW_INIT_PUSHBUF(thr, bw, n);
88133 	q = DUK_BW_GET_PTR(thr, bw);
88134 
88135 	c_prev = (duk_uint_fast8_t) 0;
88136 
88137 	for (i = 0; i < n; i++) {
88138 		c = p[i];
88139 
88140 		q = DUK_BW_ENSURE_RAW(thr, bw, 2, q);
88141 
88142 		if (c == (duk_uint_fast8_t) '/' && c_prev != (duk_uint_fast8_t) '\\') {
88143 			/* Unescaped '/' ANYWHERE in the regexp (in disjunction,
88144 			 * inside a character class, ...) => same escape works.
88145 			 */
88146 			*q++ = DUK_ASC_BACKSLASH;
88147 		}
88148 		*q++ = (duk_uint8_t) c;
88149 
88150 		c_prev = c;
88151 	}
88152 
88153 	DUK_BW_SETPTR_AND_COMPACT(thr, bw, q);
88154 	(void) duk_buffer_to_string(thr, -1);  /* Safe if input is safe. */
88155 
88156 	/* [ ... escaped_source ] */
88157 }
88158 
88159 /*
88160  *  Exposed regexp compilation primitive.
88161  *
88162  *  Sets up a regexp compilation context, and calls duk__parse_disjunction() to do the
88163  *  actual parsing.  Handles generation of the compiled regexp header and the
88164  *  "boilerplate" capture of the matching substring (save 0 and 1).  Also does some
88165  *  global level regexp checks after recursive compilation has finished.
88166  *
88167  *  An escaped version of the regexp source, suitable for use as a RegExp instance
88168  *  'source' property (see E5 Section 15.10.3), is also left on the stack.
88169  *
88170  *  Input stack:  [ pattern flags ]
88171  *  Output stack: [ bytecode escaped_source ]  (both as strings)
88172  */
88173 
88174 DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) {
88175 	duk_re_compiler_ctx re_ctx;
88176 	duk_lexer_point lex_point;
88177 	duk_hstring *h_pattern;
88178 	duk_hstring *h_flags;
88179 	duk__re_disjunction_info ign_disj;
88180 
88181 	DUK_ASSERT(thr != NULL);
88182 
88183 	/*
88184 	 *  Args validation
88185 	 */
88186 
88187 	/* TypeError if fails */
88188 	h_pattern = duk_require_hstring_notsymbol(thr, -2);
88189 	h_flags = duk_require_hstring_notsymbol(thr, -1);
88190 
88191 	/*
88192 	 *  Create normalized 'source' property (E5 Section 15.10.3).
88193 	 */
88194 
88195 	/* [ ... pattern flags ] */
88196 
88197 	duk__create_escaped_source(thr, -2);
88198 
88199 	/* [ ... pattern flags escaped_source ] */
88200 
88201 	/*
88202 	 *  Init compilation context
88203 	 */
88204 
88205 	/* [ ... pattern flags escaped_source buffer ] */
88206 
88207 	duk_memzero(&re_ctx, sizeof(re_ctx));
88208 	DUK_LEXER_INITCTX(&re_ctx.lex);  /* duplicate zeroing, expect for (possible) NULL inits */
88209 	re_ctx.thr = thr;
88210 	re_ctx.lex.thr = thr;
88211 	re_ctx.lex.input = DUK_HSTRING_GET_DATA(h_pattern);
88212 	re_ctx.lex.input_length = DUK_HSTRING_GET_BYTELEN(h_pattern);
88213 	re_ctx.lex.token_limit = DUK_RE_COMPILE_TOKEN_LIMIT;
88214 	re_ctx.recursion_limit = DUK_USE_REGEXP_COMPILER_RECLIMIT;
88215 	re_ctx.re_flags = duk__parse_regexp_flags(thr, h_flags);
88216 
88217 	DUK_BW_INIT_PUSHBUF(thr, &re_ctx.bw, DUK__RE_INITIAL_BUFSIZE);
88218 
88219 	DUK_DD(DUK_DDPRINT("regexp compiler ctx initialized, flags=0x%08lx, recursion_limit=%ld",
88220 	                   (unsigned long) re_ctx.re_flags, (long) re_ctx.recursion_limit));
88221 
88222 	/*
88223 	 *  Init lexer
88224 	 */
88225 
88226 	lex_point.offset = 0;  /* expensive init, just want to fill window */
88227 	lex_point.line = 1;
88228 	DUK_LEXER_SETPOINT(&re_ctx.lex, &lex_point);
88229 
88230 	/*
88231 	 *  Compilation
88232 	 */
88233 
88234 	DUK_DD(DUK_DDPRINT("starting regexp compilation"));
88235 
88236 	duk__append_reop(&re_ctx, DUK_REOP_SAVE);
88237 	duk__append_7bit(&re_ctx, 0);
88238 	duk__parse_disjunction(&re_ctx, 1 /*expect_eof*/, &ign_disj);
88239 	duk__append_reop(&re_ctx, DUK_REOP_SAVE);
88240 	duk__append_7bit(&re_ctx, 1);
88241 	duk__append_reop(&re_ctx, DUK_REOP_MATCH);
88242 
88243 	/*
88244 	 *  Check for invalid backreferences; note that it is NOT an error
88245 	 *  to back-reference a capture group which has not yet been introduced
88246 	 *  in the pattern (as in /\1(foo)/); in fact, the backreference will
88247 	 *  always match!  It IS an error to back-reference a capture group
88248 	 *  which will never be introduced in the pattern.  Thus, we can check
88249 	 *  for such references only after parsing is complete.
88250 	 */
88251 
88252 	if (re_ctx.highest_backref > re_ctx.captures) {
88253 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BACKREFS);
88254 		DUK_WO_NORETURN(return;);
88255 	}
88256 
88257 	/*
88258 	 *  Emit compiled regexp header: flags, ncaptures
88259 	 *  (insertion order inverted on purpose)
88260 	 */
88261 
88262 	duk__insert_u32(&re_ctx, 0, (re_ctx.captures + 1) * 2);
88263 	duk__insert_u32(&re_ctx, 0, re_ctx.re_flags);
88264 
88265 	/* [ ... pattern flags escaped_source buffer ] */
88266 
88267 	DUK_BW_COMPACT(thr, &re_ctx.bw);
88268 	(void) duk_buffer_to_string(thr, -1);  /* Safe because flags is at most 7 bit. */
88269 
88270 	/* [ ... pattern flags escaped_source bytecode ] */
88271 
88272 	/*
88273 	 *  Finalize stack
88274 	 */
88275 
88276 	duk_remove(thr, -4);     /* -> [ ... flags escaped_source bytecode ] */
88277 	duk_remove(thr, -3);     /* -> [ ... escaped_source bytecode ] */
88278 
88279 	DUK_DD(DUK_DDPRINT("regexp compilation successful, bytecode: %!T, escaped source: %!T",
88280 	                   (duk_tval *) duk_get_tval(thr, -1), (duk_tval *) duk_get_tval(thr, -2)));
88281 }
88282 
88283 /*
88284  *  Create a RegExp instance (E5 Section 15.10.7).
88285  *
88286  *  Note: the output stack left by duk_regexp_compile() is directly compatible
88287  *  with the input here.
88288  *
88289  *  Input stack:  [ escaped_source bytecode ]  (both as strings)
88290  *  Output stack: [ RegExp ]
88291  */
88292 
88293 DUK_INTERNAL void duk_regexp_create_instance(duk_hthread *thr) {
88294 	duk_hobject *h;
88295 
88296 	/* [ ... escaped_source bytecode ] */
88297 
88298 	duk_push_object(thr);
88299 	h = duk_known_hobject(thr, -1);
88300 	duk_insert(thr, -3);
88301 
88302 	/* [ ... regexp_object escaped_source bytecode ] */
88303 
88304 	DUK_HOBJECT_SET_CLASS_NUMBER(h, DUK_HOBJECT_CLASS_REGEXP);
88305 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]);
88306 
88307 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_BYTECODE, DUK_PROPDESC_FLAGS_NONE);
88308 
88309 	/* [ ... regexp_object escaped_source ] */
88310 
88311 	/* In ES2015 .source, and the .global, .multiline, etc flags are
88312 	 * inherited getters.  Store the escaped source as an internal
88313 	 * property for the getter.
88314 	 */
88315 
88316 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);
88317 
88318 	/* [ ... regexp_object ] */
88319 
88320 	duk_push_int(thr, 0);
88321 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LAST_INDEX, DUK_PROPDESC_FLAGS_W);
88322 
88323 	/* [ ... regexp_object ] */
88324 }
88325 
88326 #else  /* DUK_USE_REGEXP_SUPPORT */
88327 
88328 /* regexp support disabled */
88329 
88330 #endif  /* DUK_USE_REGEXP_SUPPORT */
88331 
88332 /* automatic undefs */
88333 #undef DUK__RE_BUFLEN
88334 #undef DUK__RE_INITIAL_BUFSIZE
88335 /*
88336  *  Regexp executor.
88337  *
88338  *  Safety: the ECMAScript executor should prevent user from reading and
88339  *  replacing regexp bytecode.  Even so, the executor must validate all
88340  *  memory accesses etc.  When an invalid access is detected (e.g. a 'save'
88341  *  opcode to invalid, unallocated index) it should fail with an internal
88342  *  error but not cause a segmentation fault.
88343  *
88344  *  Notes:
88345  *
88346  *    - Backtrack counts are limited to unsigned 32 bits but should
88347  *      technically be duk_size_t for strings longer than 4G chars.
88348  *      This also requires a regexp bytecode change.
88349  */
88350 
88351 /* #include duk_internal.h -> already included */
88352 
88353 #if defined(DUK_USE_REGEXP_SUPPORT)
88354 
88355 /*
88356  *  Helpers for UTF-8 handling
88357  *
88358  *  For bytecode readers the duk_uint32_t and duk_int32_t types are correct
88359  *  because they're used for more than just codepoints.
88360  */
88361 
88362 DUK_LOCAL duk_uint32_t duk__bc_get_u32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
88363 	return (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
88364 }
88365 
88366 DUK_LOCAL duk_int32_t duk__bc_get_i32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
88367 	duk_uint32_t t;
88368 
88369 	/* signed integer encoding needed to work with UTF-8 */
88370 	t = (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
88371 	if (t & 1) {
88372 		return -((duk_int32_t) (t >> 1));
88373 	} else {
88374 		return (duk_int32_t) (t >> 1);
88375 	}
88376 }
88377 
88378 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) {
88379 	const duk_uint8_t *p;
88380 
88381 	/* Note: allow backtracking from p == ptr_end */
88382 	p = *ptr;
88383 	if (p < ptr_start || p > ptr_end) {
88384 		goto fail;
88385 	}
88386 
88387 	while (count > 0) {
88388 		for (;;) {
88389 			p--;
88390 			if (p < ptr_start) {
88391 				goto fail;
88392 			}
88393 			if ((*p & 0xc0) != 0x80) {
88394 				/* utf-8 continuation bytes have the form 10xx xxxx */
88395 				break;
88396 			}
88397 		}
88398 		count--;
88399 	}
88400 	*ptr = p;
88401 	return p;
88402 
88403  fail:
88404 	DUK_ERROR_INTERNAL(thr);
88405 	DUK_WO_NORETURN(return NULL;);
88406 }
88407 
88408 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) {
88409 	const duk_uint8_t *p;
88410 
88411 	p = *ptr;
88412 	if (p < ptr_start || p >= ptr_end) {
88413 		goto fail;
88414 	}
88415 
88416 	while (count > 0) {
88417 		for (;;) {
88418 			p++;
88419 
88420 			/* Note: if encoding ends by hitting end of input, we don't check that
88421 			 * the encoding is valid, we just assume it is.
88422 			 */
88423 			if (p >= ptr_end || ((*p & 0xc0) != 0x80)) {
88424 				/* utf-8 continuation bytes have the form 10xx xxxx */
88425 				break;
88426 			}
88427 		}
88428 		count--;
88429 	}
88430 
88431 	*ptr = p;
88432 	return p;
88433 
88434  fail:
88435 	DUK_ERROR_INTERNAL(thr);
88436 	DUK_WO_NORETURN(return NULL;);
88437 }
88438 
88439 /*
88440  *  Helpers for dealing with the input string
88441  */
88442 
88443 /* Get a (possibly canonicalized) input character from current sp.  The input
88444  * itself is never modified, and captures always record non-canonicalized
88445  * characters even in case-insensitive matching.  Return <0 if out of input.
88446  */
88447 DUK_LOCAL duk_codepoint_t duk__inp_get_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp) {
88448 	duk_codepoint_t res;
88449 
88450 	if (*sp >= re_ctx->input_end) {
88451 		return -1;
88452 	}
88453 	res = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end);
88454 	if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
88455 		res = duk_unicode_re_canonicalize_char(re_ctx->thr, res);
88456 	}
88457 	return res;
88458 }
88459 
88460 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) {
88461 	return duk__utf8_backtrack(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end, count);
88462 }
88463 
88464 /* Backtrack utf-8 input and return a (possibly canonicalized) input character. */
88465 DUK_LOCAL duk_codepoint_t duk__inp_get_prev_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *sp) {
88466 	/* note: caller 'sp' is intentionally not updated here */
88467 	(void) duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) 1);
88468 	return duk__inp_get_cp(re_ctx, &sp);
88469 }
88470 
88471 /*
88472  *  Regexp recursive matching function.
88473  *
88474  *  Returns 'sp' on successful match (points to character after last matched one),
88475  *  NULL otherwise.
88476  *
88477  *  The C recursion depth limit check is only performed in this function, this
88478  *  suffices because the function is present in all true recursion required by
88479  *  regexp execution.
88480  */
88481 
88482 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) {
88483 	duk_native_stack_check(re_ctx->thr);
88484 	if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
88485 		DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT);
88486 		DUK_WO_NORETURN(return NULL;);
88487 	}
88488 	re_ctx->recursion_depth++;
88489 
88490 	for (;;) {
88491 		duk_small_int_t op;
88492 
88493 		if (re_ctx->steps_count >= re_ctx->steps_limit) {
88494 			DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT);
88495 			DUK_WO_NORETURN(return NULL;);
88496 		}
88497 		re_ctx->steps_count++;
88498 
88499 		/* Opcodes are at most 7 bits now so they encode to one byte.  If this
88500 		 * were not the case or 'pc' is invalid here (due to a bug etc) we'll
88501 		 * still fail safely through the switch default case.
88502 		 */
88503 		DUK_ASSERT(pc[0] <= 0x7fU);
88504 #if 0
88505 		op = (duk_small_int_t) duk__bc_get_u32(re_ctx, &pc);
88506 #endif
88507 		op = *pc++;
88508 
88509 		DUK_DDD(DUK_DDDPRINT("match: rec=%ld, steps=%ld, pc (after op)=%ld, sp=%ld, op=%ld",
88510 		                     (long) re_ctx->recursion_depth,
88511 		                     (long) re_ctx->steps_count,
88512 		                     (long) (pc - re_ctx->bytecode),
88513 		                     (long) (sp - re_ctx->input),
88514 		                     (long) op));
88515 
88516 		switch (op) {
88517 		case DUK_REOP_MATCH: {
88518 			goto match;
88519 		}
88520 		case DUK_REOP_CHAR: {
88521 			/*
88522 			 *  Byte-based matching would be possible for case-sensitive
88523 			 *  matching but not for case-insensitive matching.  So, we
88524 			 *  match by decoding the input and bytecode character normally.
88525 			 *
88526 			 *  Bytecode characters are assumed to be already canonicalized.
88527 			 *  Input characters are canonicalized automatically by
88528 			 *  duk__inp_get_cp() if necessary.
88529 			 *
88530 			 *  There is no opcode for matching multiple characters.  The
88531 			 *  regexp compiler has trouble joining strings efficiently
88532 			 *  during compilation.  See doc/regexp.rst for more discussion.
88533 			 */
88534 			duk_codepoint_t c1, c2;
88535 
88536 			c1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
88537 			DUK_ASSERT(!(re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) ||
88538 			           c1 == duk_unicode_re_canonicalize_char(re_ctx->thr, c1));  /* canonicalized by compiler */
88539 			c2 = duk__inp_get_cp(re_ctx, &sp);
88540 			/* No need to check for c2 < 0 (end of input): because c1 >= 0, it
88541 			 * will fail the match below automatically and cause goto fail.
88542 			 */
88543 #if 0
88544 			if (c2 < 0) {
88545 				goto fail;
88546 			}
88547 #endif
88548 			DUK_ASSERT(c1 >= 0);
88549 
88550 			DUK_DDD(DUK_DDDPRINT("char match, c1=%ld, c2=%ld", (long) c1, (long) c2));
88551 			if (c1 != c2) {
88552 				goto fail;
88553 			}
88554 			break;
88555 		}
88556 		case DUK_REOP_PERIOD: {
88557 			duk_codepoint_t c;
88558 
88559 			c = duk__inp_get_cp(re_ctx, &sp);
88560 			if (c < 0 || duk_unicode_is_line_terminator(c)) {
88561 				/* E5 Sections 15.10.2.8, 7.3 */
88562 				goto fail;
88563 			}
88564 			break;
88565 		}
88566 		case DUK_REOP_RANGES:
88567 		case DUK_REOP_INVRANGES: {
88568 			duk_uint32_t n;
88569 			duk_codepoint_t c;
88570 			duk_small_int_t match;
88571 
88572 			n = duk__bc_get_u32(re_ctx, &pc);
88573 			c = duk__inp_get_cp(re_ctx, &sp);
88574 			if (c < 0) {
88575 				goto fail;
88576 			}
88577 
88578 			match = 0;
88579 			while (n) {
88580 				duk_codepoint_t r1, r2;
88581 				r1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
88582 				r2 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
88583 				DUK_DDD(DUK_DDDPRINT("matching ranges/invranges, n=%ld, r1=%ld, r2=%ld, c=%ld",
88584 				                     (long) n, (long) r1, (long) r2, (long) c));
88585 				if (c >= r1 && c <= r2) {
88586 					/* Note: don't bail out early, we must read all the ranges from
88587 					 * bytecode.  Another option is to skip them efficiently after
88588 					 * breaking out of here.  Prefer smallest code.
88589 					 */
88590 					match = 1;
88591 				}
88592 				n--;
88593 			}
88594 
88595 			if (op == DUK_REOP_RANGES) {
88596 				if (!match) {
88597 					goto fail;
88598 				}
88599 			} else {
88600 				DUK_ASSERT(op == DUK_REOP_INVRANGES);
88601 				if (match) {
88602 					goto fail;
88603 				}
88604 			}
88605 			break;
88606 		}
88607 		case DUK_REOP_ASSERT_START: {
88608 			duk_codepoint_t c;
88609 
88610 			if (sp <= re_ctx->input) {
88611 				break;
88612 			}
88613 			if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
88614 				goto fail;
88615 			}
88616 			c = duk__inp_get_prev_cp(re_ctx, sp);
88617 			if (duk_unicode_is_line_terminator(c)) {
88618 				/* E5 Sections 15.10.2.8, 7.3 */
88619 				break;
88620 			}
88621 			goto fail;
88622 		}
88623 		case DUK_REOP_ASSERT_END: {
88624 			duk_codepoint_t c;
88625 			const duk_uint8_t *tmp_sp;
88626 
88627 			tmp_sp = sp;
88628 			c = duk__inp_get_cp(re_ctx, &tmp_sp);
88629 			if (c < 0) {
88630 				break;
88631 			}
88632 			if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
88633 				goto fail;
88634 			}
88635 			if (duk_unicode_is_line_terminator(c)) {
88636 				/* E5 Sections 15.10.2.8, 7.3 */
88637 				break;
88638 			}
88639 			goto fail;
88640 		}
88641 		case DUK_REOP_ASSERT_WORD_BOUNDARY:
88642 		case DUK_REOP_ASSERT_NOT_WORD_BOUNDARY: {
88643 			/*
88644 			 *  E5 Section 15.10.2.6.  The previous and current character
88645 			 *  should -not- be canonicalized as they are now.  However,
88646 			 *  canonicalization does not affect the result of IsWordChar()
88647 			 *  (which depends on Unicode characters never canonicalizing
88648 			 *  into ASCII characters) so this does not matter.
88649 			 */
88650 			duk_small_int_t w1, w2;
88651 
88652 			if (sp <= re_ctx->input) {
88653 				w1 = 0;  /* not a wordchar */
88654 			} else {
88655 				duk_codepoint_t c;
88656 				c = duk__inp_get_prev_cp(re_ctx, sp);
88657 				w1 = duk_unicode_re_is_wordchar(c);
88658 			}
88659 			if (sp >= re_ctx->input_end) {
88660 				w2 = 0;  /* not a wordchar */
88661 			} else {
88662 				const duk_uint8_t *tmp_sp = sp;  /* dummy so sp won't get updated */
88663 				duk_codepoint_t c;
88664 				c = duk__inp_get_cp(re_ctx, &tmp_sp);
88665 				w2 = duk_unicode_re_is_wordchar(c);
88666 			}
88667 
88668 			if (op == DUK_REOP_ASSERT_WORD_BOUNDARY) {
88669 				if (w1 == w2) {
88670 					goto fail;
88671 				}
88672 			} else {
88673 				DUK_ASSERT(op == DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
88674 				if (w1 != w2) {
88675 					goto fail;
88676 				}
88677 			}
88678 			break;
88679 		}
88680 		case DUK_REOP_JUMP: {
88681 			duk_int32_t skip;
88682 
88683 			skip = duk__bc_get_i32(re_ctx, &pc);
88684 			pc += skip;
88685 			break;
88686 		}
88687 		case DUK_REOP_SPLIT1: {
88688 			/* split1: prefer direct execution (no jump) */
88689 			const duk_uint8_t *sub_sp;
88690 			duk_int32_t skip;
88691 
88692 			skip = duk__bc_get_i32(re_ctx, &pc);
88693 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
88694 			if (sub_sp) {
88695 				sp = sub_sp;
88696 				goto match;
88697 			}
88698 			pc += skip;
88699 			break;
88700 		}
88701 		case DUK_REOP_SPLIT2: {
88702 			/* split2: prefer jump execution (not direct) */
88703 			const duk_uint8_t *sub_sp;
88704 			duk_int32_t skip;
88705 
88706 			skip = duk__bc_get_i32(re_ctx, &pc);
88707 			sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
88708 			if (sub_sp) {
88709 				sp = sub_sp;
88710 				goto match;
88711 			}
88712 			break;
88713 		}
88714 		case DUK_REOP_SQMINIMAL: {
88715 			duk_uint32_t q, qmin, qmax;
88716 			duk_int32_t skip;
88717 			const duk_uint8_t *sub_sp;
88718 
88719 			qmin = duk__bc_get_u32(re_ctx, &pc);
88720 			qmax = duk__bc_get_u32(re_ctx, &pc);
88721 			skip = duk__bc_get_i32(re_ctx, &pc);
88722 			DUK_DDD(DUK_DDDPRINT("minimal quantifier, qmin=%lu, qmax=%lu, skip=%ld",
88723 			                     (unsigned long) qmin, (unsigned long) qmax, (long) skip));
88724 
88725 			q = 0;
88726 			while (q <= qmax) {
88727 				if (q >= qmin) {
88728 					sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
88729 					if (sub_sp) {
88730 						sp = sub_sp;
88731 						goto match;
88732 					}
88733 				}
88734 				sub_sp = duk__match_regexp(re_ctx, pc, sp);
88735 				if (!sub_sp) {
88736 					break;
88737 				}
88738 				sp = sub_sp;
88739 				q++;
88740 			}
88741 			goto fail;
88742 		}
88743 		case DUK_REOP_SQGREEDY: {
88744 			duk_uint32_t q, qmin, qmax, atomlen;
88745 			duk_int32_t skip;
88746 			const duk_uint8_t *sub_sp;
88747 
88748 			qmin = duk__bc_get_u32(re_ctx, &pc);
88749 			qmax = duk__bc_get_u32(re_ctx, &pc);
88750 			atomlen = duk__bc_get_u32(re_ctx, &pc);
88751 			skip = duk__bc_get_i32(re_ctx, &pc);
88752 			DUK_DDD(DUK_DDDPRINT("greedy quantifier, qmin=%lu, qmax=%lu, atomlen=%lu, skip=%ld",
88753 			                     (unsigned long) qmin, (unsigned long) qmax, (unsigned long) atomlen, (long) skip));
88754 
88755 			q = 0;
88756 			while (q < qmax) {
88757 				sub_sp = duk__match_regexp(re_ctx, pc, sp);
88758 				if (!sub_sp) {
88759 					break;
88760 				}
88761 				sp = sub_sp;
88762 				q++;
88763 			}
88764 			while (q >= qmin) {
88765 				sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
88766 				if (sub_sp) {
88767 					sp = sub_sp;
88768 					goto match;
88769 				}
88770 				if (q == qmin) {
88771 					break;
88772 				}
88773 
88774 				/* Note: if atom were to contain e.g. captures, we would need to
88775 				 * re-match the atom to get correct captures.  Simply quantifiers
88776 				 * do not allow captures in their atom now, so this is not an issue.
88777 				 */
88778 
88779 				DUK_DDD(DUK_DDDPRINT("greedy quantifier, backtrack %ld characters (atomlen)",
88780 				                     (long) atomlen));
88781 				sp = duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) atomlen);
88782 				q--;
88783 			}
88784 			goto fail;
88785 		}
88786 		case DUK_REOP_SAVE: {
88787 			duk_uint32_t idx;
88788 			const duk_uint8_t *old;
88789 			const duk_uint8_t *sub_sp;
88790 
88791 			idx = duk__bc_get_u32(re_ctx, &pc);
88792 			if (idx >= re_ctx->nsaved) {
88793 				/* idx is unsigned, < 0 check is not necessary */
88794 				DUK_D(DUK_DPRINT("internal error, regexp save index insane: idx=%ld", (long) idx));
88795 				goto internal_error;
88796 			}
88797 			old = re_ctx->saved[idx];
88798 			re_ctx->saved[idx] = sp;
88799 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
88800 			if (sub_sp) {
88801 				sp = sub_sp;
88802 				goto match;
88803 			}
88804 			re_ctx->saved[idx] = old;
88805 			goto fail;
88806 		}
88807 		case DUK_REOP_WIPERANGE: {
88808 			/* Wipe capture range and save old values for backtracking.
88809 			 *
88810 			 * XXX: this typically happens with a relatively small idx_count.
88811 			 * It might be useful to handle cases where the count is small
88812 			 * (say <= 8) by saving the values in stack instead.  This would
88813 			 * reduce memory churn and improve performance, at the cost of a
88814 			 * slightly higher code footprint.
88815 			 */
88816 			duk_uint32_t idx_start, idx_count;
88817 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
88818 			duk_uint32_t idx_end, idx;
88819 #endif
88820 			duk_uint8_t **range_save;
88821 			const duk_uint8_t *sub_sp;
88822 
88823 			idx_start = duk__bc_get_u32(re_ctx, &pc);
88824 			idx_count = duk__bc_get_u32(re_ctx, &pc);
88825 			DUK_DDD(DUK_DDDPRINT("wipe saved range: start=%ld, count=%ld -> [%ld,%ld] (captures [%ld,%ld])",
88826 			                     (long) idx_start, (long) idx_count,
88827 			                     (long) idx_start, (long) (idx_start + idx_count - 1),
88828 			                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
88829 			if (idx_start + idx_count > re_ctx->nsaved || idx_count == 0) {
88830 				/* idx is unsigned, < 0 check is not necessary */
88831 				DUK_D(DUK_DPRINT("internal error, regexp wipe indices insane: idx_start=%ld, idx_count=%ld",
88832 				                 (long) idx_start, (long) idx_count));
88833 				goto internal_error;
88834 			}
88835 			DUK_ASSERT(idx_count > 0);
88836 
88837 			duk_require_stack(re_ctx->thr, 1);
88838 			range_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr,
88839 			                                                           sizeof(duk_uint8_t *) * idx_count);
88840 			DUK_ASSERT(range_save != NULL);
88841 			duk_memcpy(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count);
88842 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
88843 			idx_end = idx_start + idx_count;
88844 			for (idx = idx_start; idx < idx_end; idx++) {
88845 				re_ctx->saved[idx] = NULL;
88846 			}
88847 #else
88848 			duk_memzero((void *) (re_ctx->saved + idx_start), sizeof(duk_uint8_t *) * idx_count);
88849 #endif
88850 
88851 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
88852 			if (sub_sp) {
88853 				/* match: keep wiped/resaved values */
88854 				DUK_DDD(DUK_DDDPRINT("match: keep wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
88855 				                     (long) idx_start, (long) (idx_start + idx_count - 1),
88856 			                             (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
88857 				duk_pop_unsafe(re_ctx->thr);
88858 				sp = sub_sp;
88859 				goto match;
88860 			}
88861 
88862 			/* fail: restore saves */
88863 			DUK_DDD(DUK_DDDPRINT("fail: restore wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
88864 			                     (long) idx_start, (long) (idx_start + idx_count - 1),
88865 			                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
88866 			duk_memcpy((void *) (re_ctx->saved + idx_start),
88867 			           (const void *) range_save,
88868 			           sizeof(duk_uint8_t *) * idx_count);
88869 			duk_pop_unsafe(re_ctx->thr);
88870 			goto fail;
88871 		}
88872 		case DUK_REOP_LOOKPOS:
88873 		case DUK_REOP_LOOKNEG: {
88874 			/*
88875 			 *  Needs a save of multiple saved[] entries depending on what range
88876 			 *  may be overwritten.  Because the regexp parser does no such analysis,
88877 			 *  we currently save the entire saved array here.  Lookaheads are thus
88878 			 *  a bit expensive.  Note that the saved array is not needed for just
88879 			 *  the lookahead sub-match, but for the matching of the entire sequel.
88880 			 *
88881 			 *  The temporary save buffer is pushed on to the valstack to handle
88882 			 *  errors correctly.  Each lookahead causes a C recursion and pushes
88883 			 *  more stuff on the value stack.  If the C recursion limit is less
88884 			 *  than the value stack slack, there is no need to check the stack.
88885 			 *  We do so regardless, just in case.
88886 			 */
88887 
88888 			duk_int32_t skip;
88889 			duk_uint8_t **full_save;
88890 			const duk_uint8_t *sub_sp;
88891 
88892 			DUK_ASSERT(re_ctx->nsaved > 0);
88893 
88894 			duk_require_stack(re_ctx->thr, 1);
88895 			full_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr,
88896 			                                                          sizeof(duk_uint8_t *) * re_ctx->nsaved);
88897 			DUK_ASSERT(full_save != NULL);
88898 			duk_memcpy(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved);
88899 
88900 			skip = duk__bc_get_i32(re_ctx, &pc);
88901 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
88902 			if (op == DUK_REOP_LOOKPOS) {
88903 				if (!sub_sp) {
88904 					goto lookahead_fail;
88905 				}
88906 			} else {
88907 				if (sub_sp) {
88908 					goto lookahead_fail;
88909 				}
88910 			}
88911 			sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
88912 			if (sub_sp) {
88913 				/* match: keep saves */
88914 				duk_pop_unsafe(re_ctx->thr);
88915 				sp = sub_sp;
88916 				goto match;
88917 			}
88918 
88919 			/* fall through */
88920 
88921 		 lookahead_fail:
88922 			/* fail: restore saves */
88923 			duk_memcpy((void *) re_ctx->saved,
88924 			           (const void *) full_save,
88925 			           sizeof(duk_uint8_t *) * re_ctx->nsaved);
88926 			duk_pop_unsafe(re_ctx->thr);
88927 			goto fail;
88928 		}
88929 		case DUK_REOP_BACKREFERENCE: {
88930 			/*
88931 			 *  Byte matching for back-references would be OK in case-
88932 			 *  sensitive matching.  In case-insensitive matching we need
88933 			 *  to canonicalize characters, so back-reference matching needs
88934 			 *  to be done with codepoints instead.  So, we just decode
88935 			 *  everything normally here, too.
88936 			 *
88937 			 *  Note: back-reference index which is 0 or higher than
88938 			 *  NCapturingParens (= number of capturing parens in the
88939 			 *  -entire- regexp) is a compile time error.  However, a
88940 			 *  backreference referring to a valid capture which has
88941 			 *  not matched anything always succeeds!  See E5 Section
88942 			 *  15.10.2.9, step 5, sub-step 3.
88943 			 */
88944 			duk_uint32_t idx;
88945 			const duk_uint8_t *p;
88946 
88947 			idx = duk__bc_get_u32(re_ctx, &pc);
88948 			idx = idx << 1;  /* backref n -> saved indices [n*2, n*2+1] */
88949 			if (idx < 2 || idx + 1 >= re_ctx->nsaved) {
88950 				/* regexp compiler should catch these */
88951 				DUK_D(DUK_DPRINT("internal error, backreference index insane"));
88952 				goto internal_error;
88953 			}
88954 			if (!re_ctx->saved[idx] || !re_ctx->saved[idx+1]) {
88955 				/* capture is 'undefined', always matches! */
88956 				DUK_DDD(DUK_DDDPRINT("backreference: saved[%ld,%ld] not complete, always match",
88957 				                     (long) idx, (long) (idx + 1)));
88958 				break;
88959 			}
88960 			DUK_DDD(DUK_DDDPRINT("backreference: match saved[%ld,%ld]", (long) idx, (long) (idx + 1)));
88961 
88962 			p = re_ctx->saved[idx];
88963 			while (p < re_ctx->saved[idx+1]) {
88964 				duk_codepoint_t c1, c2;
88965 
88966 				/* Note: not necessary to check p against re_ctx->input_end:
88967 				 * the memory access is checked by duk__inp_get_cp(), while
88968 				 * valid compiled regexps cannot write a saved[] entry
88969 				 * which points to outside the string.
88970 				 */
88971 				c1 = duk__inp_get_cp(re_ctx, &p);
88972 				DUK_ASSERT(c1 >= 0);
88973 				c2 = duk__inp_get_cp(re_ctx, &sp);
88974 				/* No need for an explicit c2 < 0 check: because c1 >= 0,
88975 				 * the comparison will always fail if c2 < 0.
88976 				 */
88977 #if 0
88978 				if (c2 < 0) {
88979 					goto fail;
88980 				}
88981 #endif
88982 				if (c1 != c2) {
88983 					goto fail;
88984 				}
88985 			}
88986 			break;
88987 		}
88988 		default: {
88989 			DUK_D(DUK_DPRINT("internal error, regexp opcode error: %ld", (long) op));
88990 			goto internal_error;
88991 		}
88992 		}
88993 	}
88994 
88995  match:
88996 	re_ctx->recursion_depth--;
88997 	return sp;
88998 
88999  fail:
89000 	re_ctx->recursion_depth--;
89001 	return NULL;
89002 
89003  internal_error:
89004 	DUK_ERROR_INTERNAL(re_ctx->thr);
89005 	DUK_WO_NORETURN(return NULL;);
89006 }
89007 
89008 /*
89009  *  Exposed matcher function which provides the semantics of RegExp.prototype.exec().
89010  *
89011  *  RegExp.prototype.test() has the same semantics as exec() but does not return the
89012  *  result object (which contains the matching string and capture groups).  Currently
89013  *  there is no separate test() helper, so a temporary result object is created and
89014  *  discarded if test() is needed.  This is intentional, to save code space.
89015  *
89016  *  Input stack:  [ ... re_obj input ]
89017  *  Output stack: [ ... result ]
89018  */
89019 
89020 DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_global) {
89021 	duk_re_matcher_ctx re_ctx;
89022 	duk_hobject *h_regexp;
89023 	duk_hstring *h_bytecode;
89024 	duk_hstring *h_input;
89025 	duk_uint8_t *p_buf;
89026 	const duk_uint8_t *pc;
89027 	const duk_uint8_t *sp;
89028 	duk_small_int_t match = 0;
89029 	duk_small_int_t global;
89030 	duk_uint_fast32_t i;
89031 	double d;
89032 	duk_uint32_t char_offset;
89033 
89034 	DUK_ASSERT(thr != NULL);
89035 
89036 	DUK_DD(DUK_DDPRINT("regexp match: regexp=%!T, input=%!T",
89037 	                   (duk_tval *) duk_get_tval(thr, -2),
89038 	                   (duk_tval *) duk_get_tval(thr, -1)));
89039 
89040 	/*
89041 	 *  Regexp instance check, bytecode check, input coercion.
89042 	 *
89043 	 *  See E5 Section 15.10.6.
89044 	 */
89045 
89046 	/* TypeError if wrong; class check, see E5 Section 15.10.6 */
89047 	h_regexp = duk_require_hobject_with_class(thr, -2, DUK_HOBJECT_CLASS_REGEXP);
89048 	DUK_ASSERT(h_regexp != NULL);
89049 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_regexp) == DUK_HOBJECT_CLASS_REGEXP);
89050 	DUK_UNREF(h_regexp);
89051 
89052 	h_input = duk_to_hstring(thr, -1);
89053 	DUK_ASSERT(h_input != NULL);
89054 
89055 	duk_xget_owndataprop_stridx_short(thr, -2, DUK_STRIDX_INT_BYTECODE);  /* [ ... re_obj input ] -> [ ... re_obj input bc ] */
89056 	h_bytecode = duk_require_hstring(thr, -1);  /* no regexp instance should exist without a non-configurable bytecode property */
89057 	DUK_ASSERT(h_bytecode != NULL);
89058 
89059 	/*
89060 	 *  Basic context initialization.
89061 	 *
89062 	 *  Some init values are read from the bytecode header
89063 	 *  whose format is (UTF-8 codepoints):
89064 	 *
89065 	 *    uint   flags
89066 	 *    uint   nsaved (even, 2n+2 where n = num captures)
89067 	 */
89068 
89069 	/* [ ... re_obj input bc ] */
89070 
89071 	duk_memzero(&re_ctx, sizeof(re_ctx));
89072 
89073 	re_ctx.thr = thr;
89074 	re_ctx.input = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
89075 	re_ctx.input_end = re_ctx.input + DUK_HSTRING_GET_BYTELEN(h_input);
89076 	re_ctx.bytecode = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_bytecode);
89077 	re_ctx.bytecode_end = re_ctx.bytecode + DUK_HSTRING_GET_BYTELEN(h_bytecode);
89078 	re_ctx.saved = NULL;
89079 	re_ctx.recursion_limit = DUK_USE_REGEXP_EXECUTOR_RECLIMIT;
89080 	re_ctx.steps_limit = DUK_RE_EXECUTE_STEPS_LIMIT;
89081 
89082 	/* read header */
89083 	pc = re_ctx.bytecode;
89084 	re_ctx.re_flags = duk__bc_get_u32(&re_ctx, &pc);
89085 	re_ctx.nsaved = duk__bc_get_u32(&re_ctx, &pc);
89086 	re_ctx.bytecode = pc;
89087 
89088 	DUK_ASSERT(DUK_RE_FLAG_GLOBAL < 0x10000UL);  /* must fit into duk_small_int_t */
89089 	global = (duk_small_int_t) (force_global | (duk_small_int_t) (re_ctx.re_flags & DUK_RE_FLAG_GLOBAL));
89090 
89091 	DUK_ASSERT(re_ctx.nsaved >= 2);
89092 	DUK_ASSERT((re_ctx.nsaved % 2) == 0);
89093 
89094 	p_buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, sizeof(duk_uint8_t *) * re_ctx.nsaved);  /* rely on zeroing */
89095 	DUK_UNREF(p_buf);
89096 	re_ctx.saved = (const duk_uint8_t **) duk_get_buffer(thr, -1, NULL);
89097 	DUK_ASSERT(re_ctx.saved != NULL);
89098 
89099 	/* [ ... re_obj input bc saved_buf ] */
89100 
89101 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
89102 	for (i = 0; i < re_ctx.nsaved; i++) {
89103 		re_ctx.saved[i] = (duk_uint8_t *) NULL;
89104 	}
89105 #elif defined(DUK_USE_ZERO_BUFFER_DATA)
89106 	/* buffer is automatically zeroed */
89107 #else
89108 	duk_memzero((void *) p_buf, sizeof(duk_uint8_t *) * re_ctx.nsaved);
89109 #endif
89110 
89111 	DUK_DDD(DUK_DDDPRINT("regexp ctx initialized, flags=0x%08lx, nsaved=%ld, recursion_limit=%ld, steps_limit=%ld",
89112 	                     (unsigned long) re_ctx.re_flags, (long) re_ctx.nsaved, (long) re_ctx.recursion_limit,
89113 	                     (long) re_ctx.steps_limit));
89114 
89115 	/*
89116 	 *  Get starting character offset for match, and initialize 'sp' based on it.
89117 	 *
89118 	 *  Note: lastIndex is non-configurable so it must be present (we check the
89119 	 *  internal class of the object above, so we know it is).  User code can set
89120 	 *  its value to an arbitrary (garbage) value though; E5 requires that lastIndex
89121 	 *  be coerced to a number before using.  The code below works even if the
89122 	 *  property is missing: the value will then be coerced to zero.
89123 	 *
89124 	 *  Note: lastIndex may be outside Uint32 range even after ToInteger() coercion.
89125 	 *  For instance, ToInteger(+Infinity) = +Infinity.  We track the match offset
89126 	 *  as an integer, but pre-check it to be inside the 32-bit range before the loop.
89127 	 *  If not, the check in E5 Section 15.10.6.2, step 9.a applies.
89128 	 */
89129 
89130 	/* XXX: lastIndex handling produces a lot of asm */
89131 
89132 	/* [ ... re_obj input bc saved_buf ] */
89133 
89134 	duk_get_prop_stridx_short(thr, -4, DUK_STRIDX_LAST_INDEX);  /* -> [ ... re_obj input bc saved_buf lastIndex ] */
89135 	(void) duk_to_int(thr, -1);  /* ToInteger(lastIndex) */
89136 	d = duk_get_number(thr, -1);  /* integer, but may be +/- Infinite, +/- zero (not NaN, though) */
89137 	duk_pop_nodecref_unsafe(thr);
89138 
89139 	if (global) {
89140 		if (d < 0.0 || d > (double) DUK_HSTRING_GET_CHARLEN(h_input)) {
89141 			/* match fail */
89142 			char_offset = 0;   /* not really necessary */
89143 			DUK_ASSERT(match == 0);
89144 			goto match_over;
89145 		}
89146 		char_offset = (duk_uint32_t) d;
89147 	} else {
89148 		/* lastIndex must be ignored for non-global regexps, but get the
89149 		 * value for (theoretical) side effects.  No side effects can
89150 		 * really occur, because lastIndex is a normal property and is
89151 		 * always non-configurable for RegExp instances.
89152 		 */
89153 		char_offset = (duk_uint32_t) 0;
89154 	}
89155 
89156 	DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
89157 	sp = re_ctx.input + duk_heap_strcache_offset_char2byte(thr, h_input, char_offset);
89158 
89159 	/*
89160 	 *  Match loop.
89161 	 *
89162 	 *  Try matching at different offsets until match found or input exhausted.
89163 	 */
89164 
89165 	/* [ ... re_obj input bc saved_buf ] */
89166 
89167 	DUK_ASSERT(match == 0);
89168 
89169 	for (;;) {
89170 		/* char offset in [0, h_input->clen] (both ends inclusive), checked before entry */
89171 		DUK_ASSERT_DISABLE(char_offset >= 0);
89172 		DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
89173 
89174 		/* Note: re_ctx.steps is intentionally not reset, it applies to the entire unanchored match */
89175 		DUK_ASSERT(re_ctx.recursion_depth == 0);
89176 
89177 		DUK_DDD(DUK_DDDPRINT("attempt match at char offset %ld; %p [%p,%p]",
89178 		                     (long) char_offset, (const void *) sp,
89179 		                     (const void *) re_ctx.input, (const void *) re_ctx.input_end));
89180 
89181 		/*
89182 		 *  Note:
89183 		 *
89184 		 *    - duk__match_regexp() is required not to longjmp() in ordinary "non-match"
89185 		 *      conditions; a longjmp() will terminate the entire matching process.
89186 		 *
89187 		 *    - Clearing saved[] is not necessary because backtracking does it
89188 		 *
89189 		 *    - Backtracking also rewinds re_ctx.recursion back to zero, unless an
89190 		 *      internal/limit error occurs (which causes a longjmp())
89191 		 *
89192 		 *    - If we supported anchored matches, we would break out here
89193 		 *      unconditionally; however, ECMAScript regexps don't have anchored
89194 		 *      matches.  It might make sense to implement a fast bail-out if
89195 		 *      the regexp begins with '^' and sp is not 0: currently we'll just
89196 		 *      run through the entire input string, trivially failing the match
89197 		 *      at every non-zero offset.
89198 		 */
89199 
89200 		if (duk__match_regexp(&re_ctx, re_ctx.bytecode, sp) != NULL) {
89201 			DUK_DDD(DUK_DDDPRINT("match at offset %ld", (long) char_offset));
89202 			match = 1;
89203 			break;
89204 		}
89205 
89206 		/* advance by one character (code point) and one char_offset */
89207 		char_offset++;
89208 		if (char_offset > DUK_HSTRING_GET_CHARLEN(h_input)) {
89209 			/*
89210 			 *  Note:
89211 			 *
89212 			 *    - Intentionally attempt (empty) match at char_offset == k_input->clen
89213 			 *
89214 			 *    - Negative char_offsets have been eliminated and char_offset is duk_uint32_t
89215 			 *      -> no need or use for a negative check
89216 			 */
89217 
89218 			DUK_DDD(DUK_DDDPRINT("no match after trying all sp offsets"));
89219 			break;
89220 		}
89221 
89222 		/* avoid calling at end of input, will DUK_ERROR (above check suffices to avoid this) */
89223 		(void) duk__utf8_advance(thr, &sp, re_ctx.input, re_ctx.input_end, (duk_uint_fast32_t) 1);
89224 	}
89225 
89226  match_over:
89227 
89228 	/*
89229 	 *  Matching complete, create result array or return a 'null'.  Update lastIndex
89230 	 *  if necessary.  See E5 Section 15.10.6.2.
89231 	 *
89232 	 *  Because lastIndex is a character (not byte) offset, we need the character
89233 	 *  length of the match which we conveniently get as a side effect of interning
89234 	 *  the matching substring (0th index of result array).
89235 	 *
89236 	 *  saved[0]         start pointer (~ byte offset) of current match
89237 	 *  saved[1]         end pointer (~ byte offset) of current match (exclusive)
89238 	 *  char_offset      start character offset of current match (-> .index of result)
89239 	 *  char_end_offset  end character offset (computed below)
89240 	 */
89241 
89242 	/* [ ... re_obj input bc saved_buf ] */
89243 
89244 	if (match) {
89245 #if defined(DUK_USE_ASSERTIONS)
89246 		duk_hobject *h_res;
89247 #endif
89248 		duk_uint32_t char_end_offset = 0;
89249 
89250 		DUK_DDD(DUK_DDDPRINT("regexp matches at char_offset %ld", (long) char_offset));
89251 
89252 		DUK_ASSERT(re_ctx.nsaved >= 2);        /* must have start and end */
89253 		DUK_ASSERT((re_ctx.nsaved % 2) == 0);  /* and even number */
89254 
89255 		/* XXX: Array size is known before and (2 * re_ctx.nsaved) but not taken
89256 		 * advantage of now.  The array is not compacted either, as regexp match
89257 		 * objects are usually short lived.
89258 		 */
89259 
89260 		duk_push_array(thr);
89261 
89262 #if defined(DUK_USE_ASSERTIONS)
89263 		h_res = duk_require_hobject(thr, -1);
89264 		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_res));
89265 		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h_res));
89266 		DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_res) == DUK_HOBJECT_CLASS_ARRAY);
89267 #endif
89268 
89269 		/* [ ... re_obj input bc saved_buf res_obj ] */
89270 
89271 		duk_push_u32(thr, char_offset);
89272 		duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INDEX);
89273 
89274 		duk_dup_m4(thr);
89275 		duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INPUT);
89276 
89277 		for (i = 0; i < re_ctx.nsaved; i += 2) {
89278 			/* Captures which are undefined have NULL pointers and are returned
89279 			 * as 'undefined'.  The same is done when saved[] pointers are insane
89280 			 * (this should, of course, never happen in practice).
89281 			 */
89282 			if (re_ctx.saved[i] && re_ctx.saved[i + 1] && re_ctx.saved[i + 1] >= re_ctx.saved[i]) {
89283 				duk_push_lstring(thr,
89284 				                 (const char *) re_ctx.saved[i],
89285 				                 (duk_size_t) (re_ctx.saved[i+1] - re_ctx.saved[i]));
89286 				if (i == 0) {
89287 					/* Assumes that saved[0] and saved[1] are always
89288 					 * set by regexp bytecode (if not, char_end_offset
89289 					 * will be zero).  Also assumes clen reflects the
89290 					 * correct char length.
89291 					 */
89292 					char_end_offset = char_offset + (duk_uint32_t) duk_get_length(thr, -1);  /* add charlen */
89293 				}
89294 			} else {
89295 				duk_push_undefined(thr);
89296 			}
89297 
89298 			/* [ ... re_obj input bc saved_buf res_obj val ] */
89299 			duk_put_prop_index(thr, -2, (duk_uarridx_t) (i / 2));
89300 		}
89301 
89302 		/* [ ... re_obj input bc saved_buf res_obj ] */
89303 
89304 		/* NB: 'length' property is automatically updated by the array setup loop */
89305 
89306 		if (global) {
89307 			/* global regexp: lastIndex updated on match */
89308 			duk_push_u32(thr, char_end_offset);
89309 			duk_put_prop_stridx_short(thr, -6, DUK_STRIDX_LAST_INDEX);
89310 		} else {
89311 			/* non-global regexp: lastIndex never updated on match */
89312 			;
89313 		}
89314 	} else {
89315 		/*
89316 		 *  No match, E5 Section 15.10.6.2, step 9.a.i - 9.a.ii apply, regardless
89317 		 *  of 'global' flag of the RegExp.  In particular, if lastIndex is invalid
89318 		 *  initially, it is reset to zero.
89319 		 */
89320 
89321 		DUK_DDD(DUK_DDDPRINT("regexp does not match"));
89322 
89323 		duk_push_null(thr);
89324 
89325 		/* [ ... re_obj input bc saved_buf res_obj ] */
89326 
89327 		duk_push_int(thr, 0);
89328 		duk_put_prop_stridx_short(thr, -6, DUK_STRIDX_LAST_INDEX);
89329 	}
89330 
89331 	/* [ ... re_obj input bc saved_buf res_obj ] */
89332 
89333 	duk_insert(thr, -5);
89334 
89335 	/* [ ... res_obj re_obj input bc saved_buf ] */
89336 
89337 	duk_pop_n_unsafe(thr, 4);
89338 
89339 	/* [ ... res_obj ] */
89340 
89341 	/* XXX: these last tricks are unnecessary if the function is made
89342 	 * a genuine native function.
89343 	 */
89344 }
89345 
89346 DUK_INTERNAL void duk_regexp_match(duk_hthread *thr) {
89347 	duk__regexp_match_helper(thr, 0 /*force_global*/);
89348 }
89349 
89350 /* This variant is needed by String.prototype.split(); it needs to perform
89351  * global-style matching on a cloned RegExp which is potentially non-global.
89352  */
89353 DUK_INTERNAL void duk_regexp_match_force_global(duk_hthread *thr) {
89354 	duk__regexp_match_helper(thr, 1 /*force_global*/);
89355 }
89356 
89357 #else  /* DUK_USE_REGEXP_SUPPORT */
89358 
89359 /* regexp support disabled */
89360 
89361 #endif  /* DUK_USE_REGEXP_SUPPORT */
89362 /*
89363  *  Self tests to ensure execution environment is sane.  Intended to catch
89364  *  compiler/platform problems which cannot be detected at compile time.
89365  */
89366 
89367 /* #include duk_internal.h -> already included */
89368 
89369 #if defined(DUK_USE_SELF_TESTS)
89370 
89371 /*
89372  *  Unions and structs for self tests
89373  */
89374 
89375 typedef union {
89376 	double d;
89377 	duk_uint8_t x[8];
89378 } duk__test_double_union;
89379 
89380 /* Self test failed.  Expects a local variable 'error_count' to exist. */
89381 #define DUK__FAILED(msg)  do { \
89382 		DUK_D(DUK_DPRINT("self test failed: " #msg " at " DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO))); \
89383 		error_count++; \
89384 	} while (0)
89385 
89386 #define DUK__DBLUNION_CMP_TRUE(a,b)  do { \
89387 		if (duk_memcmp((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) != 0) { \
89388 			DUK__FAILED("double union compares false (expected true)"); \
89389 		} \
89390 	} while (0)
89391 
89392 #define DUK__DBLUNION_CMP_FALSE(a,b)  do { \
89393 		if (duk_memcmp((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) == 0) { \
89394 			DUK__FAILED("double union compares true (expected false)"); \
89395 		} \
89396 	} while (0)
89397 
89398 typedef union {
89399 	duk_uint32_t i;
89400 	duk_uint8_t x[8];
89401 } duk__test_u32_union;
89402 
89403 #if defined(DUK_USE_INTEGER_LE)
89404 #define DUK__U32_INIT(u, a, b, c, d) do { \
89405 		(u)->x[0] = (d); (u)->x[1] = (c); (u)->x[2] = (b); (u)->x[3] = (a); \
89406 	} while (0)
89407 #elif defined(DUK_USE_INTEGER_ME)
89408 #error integer mixed endian not supported now
89409 #elif defined(DUK_USE_INTEGER_BE)
89410 #define DUK__U32_INIT(u, a, b, c, d) do { \
89411 		(u)->x[0] = (a); (u)->x[1] = (b); (u)->x[2] = (c); (u)->x[3] = (d); \
89412 	} while (0)
89413 #else
89414 #error unknown integer endianness
89415 #endif
89416 
89417 #if defined(DUK_USE_DOUBLE_LE)
89418 #define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
89419 		(u)->x[0] = (h); (u)->x[1] = (g); (u)->x[2] = (f); (u)->x[3] = (e); \
89420 		(u)->x[4] = (d); (u)->x[5] = (c); (u)->x[6] = (b); (u)->x[7] = (a); \
89421 	} while (0)
89422 #define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
89423 	((u)->x[0] == (h) && (u)->x[1] == (g) && (u)->x[2] == (f) && (u)->x[3] == (e) && \
89424 	 (u)->x[4] == (d) && (u)->x[5] == (c) && (u)->x[6] == (b) && (u)->x[7] == (a))
89425 #elif defined(DUK_USE_DOUBLE_ME)
89426 #define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
89427 		(u)->x[0] = (d); (u)->x[1] = (c); (u)->x[2] = (b); (u)->x[3] = (a); \
89428 		(u)->x[4] = (h); (u)->x[5] = (g); (u)->x[6] = (f); (u)->x[7] = (e); \
89429 	} while (0)
89430 #define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
89431 	((u)->x[0] == (d) && (u)->x[1] == (c) && (u)->x[2] == (b) && (u)->x[3] == (a) && \
89432 	 (u)->x[4] == (h) && (u)->x[5] == (g) && (u)->x[6] == (f) && (u)->x[7] == (e))
89433 #elif defined(DUK_USE_DOUBLE_BE)
89434 #define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
89435 		(u)->x[0] = (a); (u)->x[1] = (b); (u)->x[2] = (c); (u)->x[3] = (d); \
89436 		(u)->x[4] = (e); (u)->x[5] = (f); (u)->x[6] = (g); (u)->x[7] = (h); \
89437 	} while (0)
89438 #define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
89439 	((u)->x[0] == (a) && (u)->x[1] == (b) && (u)->x[2] == (c) && (u)->x[3] == (d) && \
89440 	 (u)->x[4] == (e) && (u)->x[5] == (f) && (u)->x[6] == (g) && (u)->x[7] == (h))
89441 #else
89442 #error unknown double endianness
89443 #endif
89444 
89445 /*
89446  *  Various sanity checks for typing
89447  */
89448 
89449 DUK_LOCAL duk_uint_t duk__selftest_types(void) {
89450 	duk_uint_t error_count = 0;
89451 
89452 	if (!(sizeof(duk_int8_t) == 1 &&
89453 	      sizeof(duk_uint8_t) == 1 &&
89454 	      sizeof(duk_int16_t) == 2 &&
89455 	      sizeof(duk_uint16_t) == 2 &&
89456 	      sizeof(duk_int32_t) == 4 &&
89457 	      sizeof(duk_uint32_t) == 4)) {
89458 		DUK__FAILED("duk_(u)int{8,16,32}_t size");
89459 	}
89460 #if defined(DUK_USE_64BIT_OPS)
89461 	if (!(sizeof(duk_int64_t) == 8 &&
89462 	      sizeof(duk_uint64_t) == 8)) {
89463 		DUK__FAILED("duk_(u)int64_t size");
89464 	}
89465 #endif
89466 
89467 	if (!(sizeof(duk_size_t) >= sizeof(duk_uint_t))) {
89468 		/* Some internal code now assumes that all duk_uint_t values
89469 		 * can be expressed with a duk_size_t.
89470 		 */
89471 		DUK__FAILED("duk_size_t is smaller than duk_uint_t");
89472 	}
89473 	if (!(sizeof(duk_int_t) >= 4)) {
89474 		DUK__FAILED("duk_int_t is not 32 bits");
89475 	}
89476 
89477 	return error_count;
89478 }
89479 
89480 /*
89481  *  Packed tval sanity
89482  */
89483 
89484 DUK_LOCAL duk_uint_t duk__selftest_packed_tval(void) {
89485 	duk_uint_t error_count = 0;
89486 
89487 #if defined(DUK_USE_PACKED_TVAL)
89488 	if (sizeof(void *) > 4) {
89489 		DUK__FAILED("packed duk_tval in use but sizeof(void *) > 4");
89490 	}
89491 #endif
89492 
89493 	return error_count;
89494 }
89495 
89496 /*
89497  *  Two's complement arithmetic.
89498  */
89499 
89500 DUK_LOCAL duk_uint_t duk__selftest_twos_complement(void) {
89501 	duk_uint_t error_count = 0;
89502 	volatile int test;
89503 	test = -1;
89504 
89505 	/* Note that byte order doesn't affect this test: all bytes in
89506 	 * 'test' will be 0xFF for two's complement.
89507 	 */
89508 	if (((volatile duk_uint8_t *) &test)[0] != (duk_uint8_t) 0xff) {
89509 		DUK__FAILED("two's complement arithmetic");
89510 	}
89511 
89512 	return error_count;
89513 }
89514 
89515 /*
89516  *  Byte order.  Important to self check, because on some exotic platforms
89517  *  there is no actual detection but rather assumption based on platform
89518  *  defines.
89519  */
89520 
89521 DUK_LOCAL duk_uint_t duk__selftest_byte_order(void) {
89522 	duk_uint_t error_count = 0;
89523 	duk__test_u32_union u1;
89524 	duk__test_double_union u2;
89525 
89526 	/*
89527 	 *  >>> struct.pack('>d', 102030405060).encode('hex')
89528 	 *  '4237c17c6dc40000'
89529 	 */
89530 
89531 	DUK__U32_INIT(&u1, 0xde, 0xad, 0xbe, 0xef);
89532 	DUK__DOUBLE_INIT(&u2, 0x42, 0x37, 0xc1, 0x7c, 0x6d, 0xc4, 0x00, 0x00);
89533 
89534 	if (u1.i != (duk_uint32_t) 0xdeadbeefUL) {
89535 		DUK__FAILED("duk_uint32_t byte order");
89536 	}
89537 
89538 	if (u2.d != (double) 102030405060.0) {
89539 		DUK__FAILED("double byte order");
89540 	}
89541 
89542 	return error_count;
89543 }
89544 
89545 /*
89546  *  DUK_BSWAP macros
89547  */
89548 
89549 DUK_LOCAL duk_uint_t duk__selftest_bswap_macros(void) {
89550 	duk_uint_t error_count = 0;
89551 	volatile duk_uint32_t x32_input, x32_output;
89552 	duk_uint32_t x32;
89553 	volatile duk_uint16_t x16_input, x16_output;
89554 	duk_uint16_t x16;
89555 	duk_double_union du;
89556 	duk_double_t du_diff;
89557 #if defined(DUK_BSWAP64)
89558 	volatile duk_uint64_t x64_input, x64_output;
89559 	duk_uint64_t x64;
89560 #endif
89561 
89562 	/* Cover both compile time and runtime bswap operations, as these
89563 	 * may have different bugs.
89564 	 */
89565 
89566 	x16_input = 0xbeefUL;
89567 	x16 = x16_input;
89568 	x16 = DUK_BSWAP16(x16);
89569 	x16_output = x16;
89570 	if (x16_output != (duk_uint16_t) 0xefbeUL) {
89571 		DUK__FAILED("DUK_BSWAP16");
89572 	}
89573 
89574 	x16 = 0xbeefUL;
89575 	x16 = DUK_BSWAP16(x16);
89576 	if (x16 != (duk_uint16_t) 0xefbeUL) {
89577 		DUK__FAILED("DUK_BSWAP16");
89578 	}
89579 
89580 	x32_input = 0xdeadbeefUL;
89581 	x32 = x32_input;
89582 	x32 = DUK_BSWAP32(x32);
89583 	x32_output = x32;
89584 	if (x32_output != (duk_uint32_t) 0xefbeaddeUL) {
89585 		DUK__FAILED("DUK_BSWAP32");
89586 	}
89587 
89588 	x32 = 0xdeadbeefUL;
89589 	x32 = DUK_BSWAP32(x32);
89590 	if (x32 != (duk_uint32_t) 0xefbeaddeUL) {
89591 		DUK__FAILED("DUK_BSWAP32");
89592 	}
89593 
89594 #if defined(DUK_BSWAP64)
89595 	x64_input = DUK_U64_CONSTANT(0x8899aabbccddeeff);
89596 	x64 = x64_input;
89597 	x64 = DUK_BSWAP64(x64);
89598 	x64_output = x64;
89599 	if (x64_output != (duk_uint64_t) DUK_U64_CONSTANT(0xffeeddccbbaa9988)) {
89600 		DUK__FAILED("DUK_BSWAP64");
89601 	}
89602 
89603 	x64 = DUK_U64_CONSTANT(0x8899aabbccddeeff);
89604 	x64 = DUK_BSWAP64(x64);
89605 	if (x64 != (duk_uint64_t) DUK_U64_CONSTANT(0xffeeddccbbaa9988)) {
89606 		DUK__FAILED("DUK_BSWAP64");
89607 	}
89608 #endif
89609 
89610 	/* >>> struct.unpack('>d', '4000112233445566'.decode('hex'))
89611 	 * (2.008366013071895,)
89612 	 */
89613 
89614 	du.uc[0] = 0x40; du.uc[1] = 0x00; du.uc[2] = 0x11; du.uc[3] = 0x22;
89615 	du.uc[4] = 0x33; du.uc[5] = 0x44; du.uc[6] = 0x55; du.uc[7] = 0x66;
89616 	DUK_DBLUNION_DOUBLE_NTOH(&du);
89617 	du_diff = du.d - 2.008366013071895;
89618 #if 0
89619 	DUK_D(DUK_DPRINT("du_diff: %lg\n", (double) du_diff));
89620 #endif
89621 	if (du_diff > 1e-15) {
89622 		/* Allow very small lenience because some compilers won't parse
89623 		 * exact IEEE double constants (happened in matrix testing with
89624 		 * Linux gcc-4.8 -m32 at least).
89625 		 */
89626 #if 0
89627 		DUK_D(DUK_DPRINT("Result of DUK_DBLUNION_DOUBLE_NTOH: %02x %02x %02x %02x %02x %02x %02x %02x\n",
89628 		            (unsigned int) du.uc[0], (unsigned int) du.uc[1],
89629 		            (unsigned int) du.uc[2], (unsigned int) du.uc[3],
89630 		            (unsigned int) du.uc[4], (unsigned int) du.uc[5],
89631 		            (unsigned int) du.uc[6], (unsigned int) du.uc[7]));
89632 #endif
89633 		DUK__FAILED("DUK_DBLUNION_DOUBLE_NTOH");
89634 	}
89635 
89636 	return error_count;
89637 }
89638 
89639 /*
89640  *  Basic double / byte union memory layout.
89641  */
89642 
89643 DUK_LOCAL duk_uint_t duk__selftest_double_union_size(void) {
89644 	duk_uint_t error_count = 0;
89645 
89646 	if (sizeof(duk__test_double_union) != 8) {
89647 		DUK__FAILED("invalid union size");
89648 	}
89649 
89650 	return error_count;
89651 }
89652 
89653 /*
89654  *  Union aliasing, see misc/clang_aliasing.c.
89655  */
89656 
89657 DUK_LOCAL duk_uint_t duk__selftest_double_aliasing(void) {
89658 	/* This testcase fails when Emscripten-generated code runs on Firefox.
89659 	 * It's not an issue because the failure should only affect packed
89660 	 * duk_tval representation, which is not used with Emscripten.
89661 	 */
89662 #if defined(DUK_USE_PACKED_TVAL)
89663 	duk_uint_t error_count = 0;
89664 	duk__test_double_union a, b;
89665 
89666 	/* Test signaling NaN and alias assignment in all endianness combinations.
89667 	 */
89668 
89669 	/* little endian */
89670 	a.x[0] = 0x11; a.x[1] = 0x22; a.x[2] = 0x33; a.x[3] = 0x44;
89671 	a.x[4] = 0x00; a.x[5] = 0x00; a.x[6] = 0xf1; a.x[7] = 0xff;
89672 	b = a;
89673 	DUK__DBLUNION_CMP_TRUE(&a, &b);
89674 
89675 	/* big endian */
89676 	a.x[0] = 0xff; a.x[1] = 0xf1; a.x[2] = 0x00; a.x[3] = 0x00;
89677 	a.x[4] = 0x44; a.x[5] = 0x33; a.x[6] = 0x22; a.x[7] = 0x11;
89678 	b = a;
89679 	DUK__DBLUNION_CMP_TRUE(&a, &b);
89680 
89681 	/* mixed endian */
89682 	a.x[0] = 0x00; a.x[1] = 0x00; a.x[2] = 0xf1; a.x[3] = 0xff;
89683 	a.x[4] = 0x11; a.x[5] = 0x22; a.x[6] = 0x33; a.x[7] = 0x44;
89684 	b = a;
89685 	DUK__DBLUNION_CMP_TRUE(&a, &b);
89686 
89687 	return error_count;
89688 #else
89689 	DUK_D(DUK_DPRINT("skip double aliasing self test when duk_tval is not packed"));
89690 	return 0;
89691 #endif
89692 }
89693 
89694 /*
89695  *  Zero sign, see misc/tcc_zerosign2.c.
89696  */
89697 
89698 DUK_LOCAL duk_uint_t duk__selftest_double_zero_sign(void) {
89699 	duk_uint_t error_count = 0;
89700 	duk__test_double_union a, b;
89701 
89702 	a.d = 0.0;
89703 	b.d = -a.d;
89704 	DUK__DBLUNION_CMP_FALSE(&a, &b);
89705 
89706 	return error_count;
89707 }
89708 
89709 /*
89710  *  Rounding mode: Duktape assumes round-to-nearest, check that this is true.
89711  *  If we had C99 fenv.h we could check that fegetround() == FE_TONEAREST,
89712  *  but we don't want to rely on that header; and even if we did, it's good
89713  *  to ensure the rounding actually works.
89714  */
89715 
89716 DUK_LOCAL duk_uint_t duk__selftest_double_rounding(void) {
89717 	duk_uint_t error_count = 0;
89718 	duk__test_double_union a, b, c;
89719 
89720 #if 0
89721 	/* Include <fenv.h> and test manually; these trigger failures: */
89722 	fesetround(FE_UPWARD);
89723 	fesetround(FE_DOWNWARD);
89724 	fesetround(FE_TOWARDZERO);
89725 
89726 	/* This is the default and passes. */
89727 	fesetround(FE_TONEAREST);
89728 #endif
89729 
89730 	/* Rounding tests check that none of the other modes (round to
89731 	 * +Inf, round to -Inf, round to zero) can be active:
89732 	 * http://www.gnu.org/software/libc/manual/html_node/Rounding.html
89733 	 */
89734 
89735 	/* 1.0 + 2^(-53): result is midway between 1.0 and 1.0 + ulp.
89736 	 * Round to nearest: 1.0
89737 	 * Round to +Inf:    1.0 + ulp
89738 	 * Round to -Inf:    1.0
89739 	 * Round to zero:    1.0
89740 	 * => Correct result eliminates round to +Inf.
89741 	 */
89742 	DUK__DOUBLE_INIT(&a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
89743 	DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
89744 	duk_memset((void *) &c, 0, sizeof(c));
89745 	c.d = a.d + b.d;
89746 	if (!DUK__DOUBLE_COMPARE(&c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)) {
89747 		DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x",
89748 		                 (unsigned int) c.x[0], (unsigned int) c.x[1],
89749 		                 (unsigned int) c.x[2], (unsigned int) c.x[3],
89750 		                 (unsigned int) c.x[4], (unsigned int) c.x[5],
89751 		                 (unsigned int) c.x[6], (unsigned int) c.x[7]));
89752 		DUK__FAILED("invalid result from 1.0 + 0.5ulp");
89753 	}
89754 
89755 	/* (1.0 + ulp) + 2^(-53): result is midway between 1.0 + ulp and 1.0 + 2*ulp.
89756 	 * Round to nearest: 1.0 + 2*ulp (round to even mantissa)
89757 	 * Round to +Inf:    1.0 + 2*ulp
89758 	 * Round to -Inf:    1.0 + ulp
89759 	 * Round to zero:    1.0 + ulp
89760 	 * => Correct result eliminates round to -Inf and round to zero.
89761 	 */
89762 	DUK__DOUBLE_INIT(&a, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
89763 	DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
89764 	duk_memset((void *) &c, 0, sizeof(c));
89765 	c.d = a.d + b.d;
89766 	if (!DUK__DOUBLE_COMPARE(&c, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02)) {
89767 		DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x",
89768 		                 (unsigned int) c.x[0], (unsigned int) c.x[1],
89769 		                 (unsigned int) c.x[2], (unsigned int) c.x[3],
89770 		                 (unsigned int) c.x[4], (unsigned int) c.x[5],
89771 		                 (unsigned int) c.x[6], (unsigned int) c.x[7]));
89772 		DUK__FAILED("invalid result from (1.0 + ulp) + 0.5ulp");
89773 	}
89774 
89775 	/* Could do negative number testing too, but the tests above should
89776 	 * differentiate between IEEE 754 rounding modes.
89777 	 */
89778 	return error_count;
89779 }
89780 
89781 /*
89782  *  fmod(): often a portability issue in embedded or bare platform targets.
89783  *  Check for at least minimally correct behavior.  Unlike some other math
89784  *  functions (like cos()) Duktape relies on fmod() internally too.
89785  */
89786 
89787 DUK_LOCAL duk_uint_t duk__selftest_fmod(void) {
89788 	duk_uint_t error_count = 0;
89789 	duk__test_double_union u1, u2;
89790 	volatile duk_double_t t1, t2, t3;
89791 
89792 	/* fmod() with integer argument and exponent 2^32 is used by e.g.
89793 	 * ToUint32() and some Duktape internals.
89794 	 */
89795 	u1.d = DUK_FMOD(10.0, 4294967296.0);
89796 	u2.d = 10.0;
89797 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89798 
89799 	u1.d = DUK_FMOD(4294967306.0, 4294967296.0);
89800 	u2.d = 10.0;
89801 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89802 
89803 	u1.d = DUK_FMOD(73014444042.0, 4294967296.0);
89804 	u2.d = 10.0;
89805 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89806 
89807 	/* 52-bit integer split into two parts:
89808 	 * >>> 0x1fedcba9876543
89809 	 * 8987183256397123
89810 	 * >>> float(0x1fedcba9876543) / float(2**53)
89811 	 * 0.9977777777777778
89812 	 */
89813 	u1.d = DUK_FMOD(8987183256397123.0, 4294967296.0);
89814 	u2.d = (duk_double_t) 0xa9876543UL;
89815 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89816 	t1 = 8987183256397123.0;
89817 	t2 = 4294967296.0;
89818 	t3 = t1 / t2;
89819 	u1.d = DUK_FLOOR(t3);
89820 	u2.d = (duk_double_t) 0x1fedcbUL;
89821 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89822 
89823 	/* C99 behavior is for fmod() result sign to mathc argument sign. */
89824 	u1.d = DUK_FMOD(-10.0, 4294967296.0);
89825 	u2.d = -10.0;
89826 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89827 
89828 	u1.d = DUK_FMOD(-4294967306.0, 4294967296.0);
89829 	u2.d = -10.0;
89830 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89831 
89832 	u1.d = DUK_FMOD(-73014444042.0, 4294967296.0);
89833 	u2.d = -10.0;
89834 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89835 
89836 	return error_count;
89837 }
89838 
89839 /*
89840  *  Struct size/alignment if platform requires it
89841  *
89842  *  There are some compiler specific struct padding pragmas etc in use, this
89843  *  selftest ensures they're correctly detected and used.
89844  */
89845 
89846 DUK_LOCAL duk_uint_t duk__selftest_struct_align(void) {
89847 	duk_uint_t error_count = 0;
89848 
89849 #if (DUK_USE_ALIGN_BY == 4)
89850 	if ((sizeof(duk_hbuffer_fixed) % 4) != 0) {
89851 		DUK__FAILED("sizeof(duk_hbuffer_fixed) not aligned to 4");
89852 	}
89853 #elif (DUK_USE_ALIGN_BY == 8)
89854 	if ((sizeof(duk_hbuffer_fixed) % 8) != 0) {
89855 		DUK__FAILED("sizeof(duk_hbuffer_fixed) not aligned to 8");
89856 	}
89857 #elif (DUK_USE_ALIGN_BY == 1)
89858 	/* no check */
89859 #else
89860 #error invalid DUK_USE_ALIGN_BY
89861 #endif
89862 	return error_count;
89863 }
89864 
89865 /*
89866  *  64-bit arithmetic
89867  *
89868  *  There are some platforms/compilers where 64-bit types are available
89869  *  but don't work correctly.  Test for known cases.
89870  */
89871 
89872 DUK_LOCAL duk_uint_t duk__selftest_64bit_arithmetic(void) {
89873 	duk_uint_t error_count = 0;
89874 #if defined(DUK_USE_64BIT_OPS)
89875 	volatile duk_int64_t i;
89876 	volatile duk_double_t d;
89877 
89878 	/* Catch a double-to-int64 cast issue encountered in practice. */
89879 	d = 2147483648.0;
89880 	i = (duk_int64_t) d;
89881 	if (i != DUK_I64_CONSTANT(0x80000000)) {
89882 		DUK__FAILED("casting 2147483648.0 to duk_int64_t failed");
89883 	}
89884 #else
89885 	/* nop */
89886 #endif
89887 	return error_count;
89888 }
89889 
89890 /*
89891  *  Casting
89892  */
89893 
89894 DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_small_uint(void) {
89895 	/*
89896 	 *  https://github.com/svaarala/duktape/issues/127#issuecomment-77863473
89897 	 */
89898 
89899 	duk_uint_t error_count = 0;
89900 
89901 	duk_double_t d1, d2;
89902 	duk_small_uint_t u;
89903 
89904 	duk_double_t d1v, d2v;
89905 	duk_small_uint_t uv;
89906 
89907 	/* Test without volatiles */
89908 
89909 	d1 = 1.0;
89910 	u = (duk_small_uint_t) d1;
89911 	d2 = (duk_double_t) u;
89912 
89913 	if (!(d1 == 1.0 && u == 1 && d2 == 1.0 && d1 == d2)) {
89914 		DUK__FAILED("double to duk_small_uint_t cast failed");
89915 	}
89916 
89917 	/* Same test with volatiles */
89918 
89919 	d1v = 1.0;
89920 	uv = (duk_small_uint_t) d1v;
89921 	d2v = (duk_double_t) uv;
89922 
89923 	if (!(d1v == 1.0 && uv == 1 && d2v == 1.0 && d1v == d2v)) {
89924 		DUK__FAILED("double to duk_small_uint_t cast failed");
89925 	}
89926 
89927 	return error_count;
89928 }
89929 
89930 DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_uint32(void) {
89931 	/*
89932 	 *  This test fails on an exotic ARM target; double-to-uint
89933 	 *  cast is incorrectly clamped to -signed- int highest value.
89934 	 *
89935 	 *  https://github.com/svaarala/duktape/issues/336
89936 	 */
89937 
89938 	duk_uint_t error_count = 0;
89939 	duk_double_t dv;
89940 	duk_uint32_t uv;
89941 
89942 	dv = 3735928559.0;  /* 0xdeadbeef in decimal */
89943 	uv = (duk_uint32_t) dv;
89944 
89945 	if (uv != 0xdeadbeefUL) {
89946 		DUK__FAILED("double to duk_uint32_t cast failed");
89947 	}
89948 
89949 	return error_count;
89950 }
89951 
89952 /*
89953  *  Minimal test of user supplied allocation functions
89954  *
89955  *    - Basic alloc + realloc + free cycle
89956  *
89957  *    - Realloc to significantly larger size to (hopefully) trigger a
89958  *      relocation and check that relocation copying works
89959  */
89960 
89961 DUK_LOCAL duk_uint_t duk__selftest_alloc_funcs(duk_alloc_function alloc_func,
89962                                                duk_realloc_function realloc_func,
89963                                                duk_free_function free_func,
89964                                                void *udata) {
89965 	duk_uint_t error_count = 0;
89966 	void *ptr;
89967 	void *new_ptr;
89968 	duk_small_int_t i, j;
89969 	unsigned char x;
89970 
89971 	if (alloc_func == NULL || realloc_func == NULL || free_func == NULL) {
89972 		return 0;
89973 	}
89974 
89975 	for (i = 1; i <= 256; i++) {
89976 		ptr = alloc_func(udata, (duk_size_t) i);
89977 		if (ptr == NULL) {
89978 			DUK_D(DUK_DPRINT("alloc failed, ignore"));
89979 			continue;  /* alloc failed, ignore */
89980 		}
89981 		for (j = 0; j < i; j++) {
89982 			((unsigned char *) ptr)[j] = (unsigned char) (0x80 + j);
89983 		}
89984 		new_ptr = realloc_func(udata, ptr, 1024);
89985 		if (new_ptr == NULL) {
89986 			DUK_D(DUK_DPRINT("realloc failed, ignore"));
89987 			free_func(udata, ptr);
89988 			continue;  /* realloc failed, ignore */
89989 		}
89990 		ptr = new_ptr;
89991 		for (j = 0; j < i; j++) {
89992 			x = ((unsigned char *) ptr)[j];
89993 			if (x != (unsigned char) (0x80 + j)) {
89994 				DUK_D(DUK_DPRINT("byte at index %ld doesn't match after realloc: %02lx",
89995 				                 (long) j, (unsigned long) x));
89996 				DUK__FAILED("byte compare after realloc");
89997 				break;
89998 			}
89999 		}
90000 		free_func(udata, ptr);
90001 	}
90002 
90003 	return error_count;
90004 }
90005 
90006 /*
90007  *  Self test main
90008  */
90009 
90010 DUK_INTERNAL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,
90011                                                duk_realloc_function realloc_func,
90012                                                duk_free_function free_func,
90013                                                void *udata) {
90014 	duk_uint_t error_count = 0;
90015 
90016 	DUK_D(DUK_DPRINT("self test starting"));
90017 
90018 	error_count += duk__selftest_types();
90019 	error_count += duk__selftest_packed_tval();
90020 	error_count += duk__selftest_twos_complement();
90021 	error_count += duk__selftest_byte_order();
90022 	error_count += duk__selftest_bswap_macros();
90023 	error_count += duk__selftest_double_union_size();
90024 	error_count += duk__selftest_double_aliasing();
90025 	error_count += duk__selftest_double_zero_sign();
90026 	error_count += duk__selftest_double_rounding();
90027 	error_count += duk__selftest_fmod();
90028 	error_count += duk__selftest_struct_align();
90029 	error_count += duk__selftest_64bit_arithmetic();
90030 	error_count += duk__selftest_cast_double_to_small_uint();
90031 	error_count += duk__selftest_cast_double_to_uint32();
90032 	error_count += duk__selftest_alloc_funcs(alloc_func, realloc_func, free_func, udata);
90033 
90034 	DUK_D(DUK_DPRINT("self test complete, total error count: %ld", (long) error_count));
90035 
90036 	return error_count;
90037 }
90038 
90039 #endif  /* DUK_USE_SELF_TESTS */
90040 
90041 /* automatic undefs */
90042 #undef DUK__DBLUNION_CMP_FALSE
90043 #undef DUK__DBLUNION_CMP_TRUE
90044 #undef DUK__DOUBLE_COMPARE
90045 #undef DUK__DOUBLE_INIT
90046 #undef DUK__FAILED
90047 #undef DUK__U32_INIT
90048 /* #include duk_internal.h -> already included */
90049 
90050 #if defined(DUK_USE_FASTINT)
90051 
90052 /*
90053  *  Manually optimized double-to-fastint downgrade check.
90054  *
90055  *  This check has a large impact on performance, especially for fastint
90056  *  slow paths, so must be changed carefully.  The code should probably be
90057  *  optimized for the case where the result does not fit into a fastint,
90058  *  to minimize the penalty for "slow path code" dealing with fractions etc.
90059  *
90060  *  At least on one tested soft float ARM platform double-to-int64 coercion
90061  *  is very slow (and sometimes produces incorrect results, see self tests).
90062  *  This algorithm combines a fastint compatibility check and extracting the
90063  *  integer value from an IEEE double for setting the tagged fastint.  For
90064  *  other platforms a more naive approach might be better.
90065  *
90066  *  See doc/fastint.rst for details.
90067  */
90068 
90069 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x) {
90070 	duk_double_union du;
90071 	duk_int64_t i;
90072 	duk_small_int_t expt;
90073 	duk_small_int_t shift;
90074 
90075 	/* XXX: optimize for packed duk_tval directly? */
90076 
90077 	du.d = x;
90078 	i = (duk_int64_t) DUK_DBLUNION_GET_INT64(&du);
90079 	expt = (duk_small_int_t) ((i >> 52) & 0x07ff);
90080 	shift = expt - 1023;
90081 
90082 	if (shift >= 0 && shift <= 46) {  /* exponents 1023 to 1069 */
90083 		duk_int64_t t;
90084 
90085 		if (((DUK_I64_CONSTANT(0x000fffffffffffff) >> shift) & i) == 0) {
90086 			t = i | DUK_I64_CONSTANT(0x0010000000000000);  /* implicit leading one */
90087 			t = t & DUK_I64_CONSTANT(0x001fffffffffffff);
90088 			t = t >> (52 - shift);
90089 			if (i < 0) {
90090 				t = -t;
90091 			}
90092 			DUK_TVAL_SET_FASTINT(tv, t);
90093 			return;
90094 		}
90095 	} else if (shift == -1023) {  /* exponent 0 */
90096 		if (i >= 0 && (i & DUK_I64_CONSTANT(0x000fffffffffffff)) == 0) {
90097 			/* Note: reject negative zero. */
90098 			DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) 0);
90099 			return;
90100 		}
90101 	} else if (shift == 47) {  /* exponent 1070 */
90102 		if (i < 0 && (i & DUK_I64_CONSTANT(0x000fffffffffffff)) == 0) {
90103 			DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) DUK_FASTINT_MIN);
90104 			return;
90105 		}
90106 	}
90107 
90108 	DUK_TVAL_SET_DOUBLE(tv, x);
90109 	return;
90110 }
90111 
90112 DUK_INTERNAL DUK_NOINLINE void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x) {
90113 	duk_tval_set_number_chkfast_fast(tv, x);
90114 }
90115 
90116 /*
90117  *  Manually optimized number-to-double conversion
90118  */
90119 
90120 #if defined(DUK_USE_FASTINT) && defined(DUK_USE_PACKED_TVAL)
90121 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_packed(duk_tval *tv) {
90122 	duk_double_union du;
90123 	duk_uint64_t t;
90124 
90125 	t = (duk_uint64_t) DUK_DBLUNION_GET_UINT64(tv);
90126 	if ((t >> 48) != DUK_TAG_FASTINT) {
90127 		return tv->d;
90128 	} else if (t & DUK_U64_CONSTANT(0x0000800000000000)) {
90129 		t = (duk_uint64_t) (-((duk_int64_t) t));  /* avoid unary minus on unsigned */
90130 		t = t & DUK_U64_CONSTANT(0x0000ffffffffffff);  /* negative */
90131 		t |= DUK_U64_CONSTANT(0xc330000000000000);
90132 		DUK_DBLUNION_SET_UINT64(&du, t);
90133 		return du.d + 4503599627370496.0;  /* 1 << 52 */
90134 	} else if (t != 0) {
90135 		t &= DUK_U64_CONSTANT(0x0000ffffffffffff);  /* positive */
90136 		t |= DUK_U64_CONSTANT(0x4330000000000000);
90137 		DUK_DBLUNION_SET_UINT64(&du, t);
90138 		return du.d - 4503599627370496.0;  /* 1 << 52 */
90139 	} else {
90140 		return 0.0;  /* zero */
90141 	}
90142 }
90143 #endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
90144 
90145 #if 0  /* unused */
90146 #if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
90147 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked(duk_tval *tv) {
90148 	duk_double_union du;
90149 	duk_uint64_t t;
90150 
90151 	DUK_ASSERT(tv->t == DUK_TAG_NUMBER || tv->t == DUK_TAG_FASTINT);
90152 
90153 	if (tv->t == DUK_TAG_FASTINT) {
90154 		if (tv->v.fi >= 0) {
90155 			t = DUK_U64_CONSTANT(0x4330000000000000) | (duk_uint64_t) tv->v.fi;
90156 			DUK_DBLUNION_SET_UINT64(&du, t);
90157 			return du.d - 4503599627370496.0;  /* 1 << 52 */
90158 		} else {
90159 			t = DUK_U64_CONSTANT(0xc330000000000000) | (duk_uint64_t) (-tv->v.fi);
90160 			DUK_DBLUNION_SET_UINT64(&du, t);
90161 			return du.d + 4503599627370496.0;  /* 1 << 52 */
90162 		}
90163 	} else {
90164 		return tv->v.d;
90165 	}
90166 }
90167 #endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
90168 #endif  /* 0 */
90169 
90170 #if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
90171 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv) {
90172 	duk_double_union du;
90173 	duk_uint64_t t;
90174 
90175 	DUK_ASSERT(tv->t == DUK_TAG_FASTINT);
90176 
90177 	if (tv->v.fi >= 0) {
90178 		t = DUK_U64_CONSTANT(0x4330000000000000) | (duk_uint64_t) tv->v.fi;
90179 		DUK_DBLUNION_SET_UINT64(&du, t);
90180 		return du.d - 4503599627370496.0;  /* 1 << 52 */
90181 	} else {
90182 		t = DUK_U64_CONSTANT(0xc330000000000000) | (duk_uint64_t) (-tv->v.fi);
90183 		DUK_DBLUNION_SET_UINT64(&du, t);
90184 		return du.d + 4503599627370496.0;  /* 1 << 52 */
90185 	}
90186 }
90187 #endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
90188 
90189 #endif  /* DUK_USE_FASTINT */
90190 
90191 /*
90192  *  Assertion helpers.
90193  */
90194 
90195 #if defined(DUK_USE_ASSERTIONS)
90196 DUK_INTERNAL void duk_tval_assert_valid(duk_tval *tv) {
90197 	DUK_ASSERT(tv != NULL);
90198 }
90199 #endif
90200 /*
90201  *  Unicode support tables automatically generated during build.
90202  */
90203 
90204 /* #include duk_internal.h -> already included */
90205 
90206 /*
90207  *  Unicode tables containing ranges of Unicode characters in a
90208  *  packed format.  These tables are used to match non-ASCII
90209  *  characters of complex productions by resorting to a linear
90210  *  range-by-range comparison.  This is very slow, but is expected
90211  *  to be very rare in practical ECMAScript source code, and thus
90212  *  compactness is most important.
90213  *
90214  *  The tables are matched using uni_range_match() and the format
90215  *  is described in tools/extract_chars.py.
90216  */
90217 
90218 #if defined(DUK_USE_SOURCE_NONBMP)
90219 /* IdentifierStart production with ASCII excluded */
90220 /* duk_unicode_ids_noa[] */
90221 /*
90222  *  Automatically generated by extract_chars.py, do not edit!
90223  */
90224 
90225 const duk_uint8_t duk_unicode_ids_noa[1116] = {
90226 249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,
90227 2,240,66,244,50,247,185,249,98,241,99,7,241,159,57,240,181,63,31,241,191,
90228 21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
90229 101,10,4,15,9,240,152,175,39,240,82,127,56,242,100,15,4,8,159,1,240,5,115,
90230 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,
90231 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,
90232 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,
90233 12,38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,
90234 6,41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,2,66,240,130,
90235 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,
90236 24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35,63,17,35,
90237 54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227,240,18,240,
90238 166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,15,53,244,
90239 152,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40,240,122,
90240 242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27,43,241,67,
90241 136,241,179,47,27,50,82,20,6,251,15,50,255,224,8,53,63,22,53,55,32,32,32,
90242 47,15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,
90243 68,112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,
90244 52,29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,
90245 12,146,240,184,132,52,95,70,114,47,74,35,111,27,47,78,240,63,11,242,127,0,
90246 255,224,244,255,240,0,138,143,60,255,240,4,14,47,2,255,227,127,243,95,30,
90247 63,253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,37,52,242,42,
90248 34,35,47,7,240,255,36,240,15,34,243,5,64,33,207,12,191,7,240,191,13,143,31,
90249 240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,48,32,
90250 240,162,58,130,213,53,53,166,38,47,27,43,159,99,240,255,255,0,26,150,223,7,
90251 95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,18,245,
90252 207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,127,10,
90253 207,73,69,53,53,50,241,91,47,10,47,3,33,46,61,241,79,107,243,127,37,255,
90254 223,13,79,33,242,31,16,239,14,111,22,191,14,63,20,87,36,241,207,142,240,79,
90255 20,95,20,95,24,159,36,248,239,254,2,154,240,107,127,138,83,2,241,194,20,3,
90256 240,123,240,122,240,255,51,240,50,27,240,107,240,175,56,242,135,31,50,15,1,
90257 50,34,240,223,28,240,212,240,223,21,114,240,207,13,242,107,240,107,240,62,
90258 240,47,96,243,159,41,242,62,242,62,241,79,254,13,15,13,176,159,6,248,207,7,
90259 223,37,243,223,29,241,47,9,240,207,20,240,240,207,19,64,223,32,240,3,240,
90260 112,32,241,95,2,47,9,244,102,32,35,46,41,143,31,241,135,49,63,6,38,33,36,
90261 64,240,64,212,249,15,37,240,67,240,96,241,47,32,240,97,32,250,175,31,241,
90262 179,241,111,32,240,96,242,223,27,224,243,159,11,253,127,28,246,111,48,241,
90263 16,249,39,63,23,240,32,32,240,224,191,24,128,240,112,207,30,240,80,241,79,
90264 41,255,152,47,21,240,48,242,63,14,246,38,33,47,22,240,112,240,181,33,47,16,
90265 240,0,255,224,59,240,63,254,0,31,254,40,207,88,245,255,3,251,79,254,155,15,
90266 254,50,31,254,236,95,254,19,159,255,0,16,173,255,225,43,143,15,246,63,14,
90267 240,79,32,240,35,241,31,5,111,3,255,225,164,243,15,114,243,182,15,52,207,
90268 50,18,15,14,255,240,0,110,169,255,225,229,255,240,1,64,31,254,1,31,35,47,3,
90269 57,255,224,126,255,231,248,245,182,196,136,159,255,0,6,90,244,82,243,114,
90270 19,3,19,50,178,2,98,243,18,51,114,98,240,194,50,66,4,98,255,224,70,63,9,47,
90271 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,
90272 15,254,6,95,28,255,228,8,251,95,45,243,72,15,254,58,131,47,11,33,32,48,41,
90273 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,
90274 98,36,47,1,255,240,0,3,143,255,0,149,201,241,191,254,242,124,252,227,255,
90275 240,0,87,79,0,255,240,0,194,63,254,177,63,254,17,0,
90276 };
90277 #else
90278 /* IdentifierStart production with ASCII and non-BMP excluded */
90279 /* duk_unicode_ids_noabmp[] */
90280 /*
90281  *  Automatically generated by extract_chars.py, do not edit!
90282  */
90283 
90284 const duk_uint8_t duk_unicode_ids_noabmp[625] = {
90285 249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,
90286 2,240,66,244,50,247,185,249,98,241,99,7,241,159,57,240,181,63,31,241,191,
90287 21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
90288 101,10,4,15,9,240,152,175,39,240,82,127,56,242,100,15,4,8,159,1,240,5,115,
90289 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,
90290 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,
90291 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,
90292 12,38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,
90293 6,41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,2,66,240,130,
90294 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,
90295 24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35,63,17,35,
90296 54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227,240,18,240,
90297 166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,15,53,244,
90298 152,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40,240,122,
90299 242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27,43,241,67,
90300 136,241,179,47,27,50,82,20,6,251,15,50,255,224,8,53,63,22,53,55,32,32,32,
90301 47,15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,
90302 68,112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,
90303 52,29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,
90304 12,146,240,184,132,52,95,70,114,47,74,35,111,27,47,78,240,63,11,242,127,0,
90305 255,224,244,255,240,0,138,143,60,255,240,4,14,47,2,255,227,127,243,95,30,
90306 63,253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,37,52,242,42,
90307 34,35,47,7,240,255,36,240,15,34,243,5,64,33,207,12,191,7,240,191,13,143,31,
90308 240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,48,32,
90309 240,162,58,130,213,53,53,166,38,47,27,43,159,99,240,255,255,0,26,150,223,7,
90310 95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,18,245,
90311 207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,127,10,
90312 207,73,69,53,53,50,0,
90313 };
90314 #endif
90315 
90316 #if defined(DUK_USE_SOURCE_NONBMP)
90317 /* IdentifierStart production with Letter and ASCII excluded */
90318 /* duk_unicode_ids_m_let_noa[] */
90319 /*
90320  *  Automatically generated by extract_chars.py, do not edit!
90321  */
90322 
90323 const duk_uint8_t duk_unicode_ids_m_let_noa[42] = {
90324 255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
90325 249,255,240,4,148,79,37,255,224,192,9,15,120,79,255,0,15,30,245,240,
90326 };
90327 #else
90328 /* IdentifierStart production with Letter, ASCII, and non-BMP excluded */
90329 /* duk_unicode_ids_m_let_noabmp[] */
90330 /*
90331  *  Automatically generated by extract_chars.py, do not edit!
90332  */
90333 
90334 const duk_uint8_t duk_unicode_ids_m_let_noabmp[24] = {
90335 255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
90336 249,0,
90337 };
90338 #endif
90339 
90340 #if defined(DUK_USE_SOURCE_NONBMP)
90341 /* IdentifierPart production with IdentifierStart and ASCII excluded */
90342 /* duk_unicode_idp_m_ids_noa[] */
90343 /*
90344  *  Automatically generated by extract_chars.py, do not edit!
90345  */
90346 
90347 const duk_uint8_t duk_unicode_idp_m_ids_noa[576] = {
90348 255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
90349 245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,160,240,163,40,
90350 34,36,241,210,246,158,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
90351 160,177,57,240,0,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,
90352 240,97,57,181,34,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,
90353 9,240,36,242,182,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,
90354 35,242,145,38,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,
90355 215,41,244,144,56,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,
90356 245,111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,
90357 241,241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,
90358 242,244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,
90359 57,241,237,242,47,4,153,121,246,130,47,5,80,112,50,251,143,42,36,255,225,0,
90360 31,35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,
90361 31,255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,
90362 242,79,2,185,127,2,234,240,231,240,188,241,227,242,29,240,25,192,185,242,
90363 29,208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
90364 225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,15,254,27,16,253,64,
90365 248,116,255,224,25,159,254,68,178,33,99,241,162,80,249,113,255,225,49,57,
90366 159,254,16,10,250,18,242,126,241,25,240,19,241,250,242,121,114,241,109,41,
90367 97,241,224,210,242,45,147,73,244,75,112,249,43,105,115,242,145,38,49,50,
90368 160,177,54,68,251,47,2,169,80,244,63,4,217,252,118,56,240,209,244,79,1,240,
90369 25,244,60,153,244,94,89,254,78,249,121,253,150,54,64,240,233,241,166,35,
90370 144,170,242,15,0,255,224,137,114,127,2,159,42,240,98,223,108,84,2,18,98,9,
90371 159,34,66,18,73,159,254,3,211,255,240,3,165,217,247,132,242,214,240,185,
90372 255,226,233,2,242,120,63,255,0,59,254,31,255,0,3,186,68,89,115,111,16,63,
90373 134,47,254,71,223,34,255,224,244,242,117,242,41,15,0,15,8,66,239,254,68,70,
90374 47,1,54,33,36,255,118,169,255,224,150,223,254,76,166,245,246,105,255,240,
90375 192,105,175,224,0,
90376 };
90377 #else
90378 /* IdentifierPart production with IdentifierStart, ASCII, and non-BMP excluded */
90379 /* duk_unicode_idp_m_ids_noabmp[] */
90380 /*
90381  *  Automatically generated by extract_chars.py, do not edit!
90382  */
90383 
90384 const duk_uint8_t duk_unicode_idp_m_ids_noabmp[358] = {
90385 255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
90386 245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,160,240,163,40,
90387 34,36,241,210,246,158,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
90388 160,177,57,240,0,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,
90389 240,97,57,181,34,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,
90390 9,240,36,242,182,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,
90391 35,242,145,38,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,
90392 215,41,244,144,56,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,
90393 245,111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,
90394 241,241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,
90395 242,244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,
90396 57,241,237,242,47,4,153,121,246,130,47,5,80,112,50,251,143,42,36,255,225,0,
90397 31,35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,
90398 31,255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,
90399 242,79,2,185,127,2,234,240,231,240,188,241,227,242,29,240,25,192,185,242,
90400 29,208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
90401 225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,0,
90402 };
90403 #endif
90404 
90405 /*
90406  *  Case conversion tables generated using tools/extract_caseconv.py.
90407  */
90408 
90409 /* duk_unicode_caseconv_uc[] */
90410 /* duk_unicode_caseconv_lc[] */
90411 
90412 /*
90413  *  Automatically generated by extract_caseconv.py, do not edit!
90414  */
90415 
90416 const duk_uint8_t duk_unicode_caseconv_uc[1411] = {
90417 152,3,128,3,0,184,7,192,6,192,112,35,242,199,224,64,74,192,49,32,128,162,
90418 128,108,65,1,189,129,254,131,3,173,3,136,6,7,98,7,34,68,15,12,14,140,72,30,
90419 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,
90420 28,189,6,39,240,39,224,24,114,12,16,132,16,248,0,248,64,129,241,1,241,128,
90421 195,228,3,229,2,7,204,7,206,4,15,160,15,164,6,31,96,31,104,16,62,224,63,
90422 116,8,125,200,127,32,32,251,176,254,208,33,247,129,255,128,67,239,67,253,
90423 64,135,223,7,254,129,15,216,15,220,2,31,208,31,216,4,63,192,63,208,8,133,
90424 192,133,128,129,38,129,37,177,162,195,2,192,5,229,160,2,20,9,170,220,4,232,
90425 40,127,160,255,144,154,136,4,4,4,0,192,9,152,9,144,48,19,160,19,145,0,41,
90426 96,41,69,192,94,128,94,65,128,193,128,193,2,1,161,1,160,6,3,104,3,102,8,7,
90427 56,7,52,64,14,248,14,240,144,31,144,31,130,128,68,96,68,66,64,145,192,145,
90428 130,129,184,129,184,2,3,217,3,216,24,8,194,8,192,68,18,44,18,40,216,38,16,
90429 38,8,112,77,16,77,6,3,192,35,192,18,199,168,71,168,24,15,168,143,172,132,
90430 44,104,44,103,6,89,2,89,0,200,179,176,179,172,21,50,13,50,1,122,104,26,104,
90431 1,212,228,116,228,65,233,204,233,204,143,211,189,83,188,130,167,127,167,
90432 126,11,79,35,79,32,10,158,94,158,88,85,61,173,61,160,97,192,107,64,107,1,0,
90433 226,128,226,3,1,198,1,196,6,3,228,3,226,8,10,0,6,152,16,31,192,31,184,34,
90434 199,50,199,32,65,128,196,0,195,130,1,185,1,184,4,4,205,79,84,8,0,192,143,0,
90435 142,193,1,52,128,203,2,45,39,16,199,5,253,0,11,80,57,192,15,240,23,128,19,
90436 16,4,144,23,240,5,48,24,0,36,48,25,32,25,16,25,80,31,96,25,144,25,128,25,
90437 160,35,208,25,224,34,0,26,128,26,112,27,240,31,112,29,208,24,224,31,48,31,
90438 16,37,2,198,240,37,18,198,208,37,34,199,0,37,48,24,16,37,64,24,96,37,144,
90439 24,240,37,176,25,0,37,202,122,176,38,0,25,48,38,26,122,192,38,48,25,64,38,
90440 90,120,208,38,128,25,112,38,178,198,32,38,202,122,208,39,18,198,224,39,32,
90441 25,208,39,80,25,240,39,210,198,64,40,42,124,80,40,122,123,16,40,128,26,224,
90442 40,144,36,64,40,192,36,80,41,32,27,112,41,218,123,32,41,234,123,0,52,80,57,
90443 144,55,112,55,96,58,192,56,96,60,32,58,48,60,192,56,192,61,0,57,32,61,16,
90444 57,128,61,80,58,96,61,96,58,0,61,112,60,240,63,0,57,160,63,16,58,16,63,32,
90445 63,144,63,48,55,240,63,80,57,80,76,240,76,1,200,0,65,33,200,16,65,65,200,
90446 32,65,225,200,80,66,33,200,96,66,161,200,112,70,33,200,138,100,161,215,154,
90447 119,209,215,210,198,49,216,234,124,97,233,177,230,1,251,224,57,145,254,81,
90448 254,194,20,226,19,34,24,66,24,50,198,18,198,2,198,80,35,162,198,96,35,226,
90449 207,50,207,42,120,202,120,186,121,74,124,74,124,58,124,42,181,58,123,60,
90450 192,27,240,2,152,2,152,10,76,5,120,0,156,3,225,0,37,1,134,1,200,96,115,32,
90451 97,0,96,32,118,24,29,40,24,64,24,8,44,60,10,106,10,164,61,45,0,36,1,152,
90452 143,75,192,10,128,97,3,211,16,2,184,24,80,244,204,0,178,6,20,61,53,0,32,
90453 129,95,15,168,64,116,160,98,99,234,88,29,40,24,152,24,0,250,166,7,74,6,38,
90454 6,2,62,173,129,210,129,137,129,161,15,192,67,225,0,115,35,240,48,248,72,28,
90455 200,252,20,62,20,7,50,63,7,15,133,129,204,143,194,67,225,128,115,35,240,
90456 176,248,104,28,200,252,52,62,28,7,50,63,15,15,135,129,204,143,196,67,225,0,
90457 115,35,241,48,248,72,28,200,252,84,62,20,7,50,63,23,15,133,129,204,143,198,
90458 67,225,128,115,35,241,176,248,104,28,200,252,116,62,28,7,50,63,31,15,135,
90459 129,204,143,200,67,229,0,115,35,242,48,249,72,28,200,252,148,62,84,7,50,63,
90460 39,15,149,129,204,143,202,67,229,128,115,35,242,176,249,104,28,200,252,180,
90461 62,92,7,50,63,47,15,151,129,204,143,204,67,229,0,115,35,243,48,249,72,28,
90462 200,252,212,62,84,7,50,63,55,15,149,129,204,143,206,67,229,128,115,35,243,
90463 176,249,104,28,200,252,244,62,92,7,50,63,63,15,151,129,204,143,208,67,237,
90464 0,115,35,244,48,251,72,28,200,253,20,62,212,7,50,63,71,15,181,129,204,143,
90465 210,67,237,128,115,35,244,176,251,104,28,200,253,52,62,220,7,50,63,79,15,
90466 183,129,204,143,212,67,237,0,115,35,245,48,251,72,28,200,253,84,62,212,7,
90467 50,63,87,15,181,129,204,143,214,67,237,128,115,35,245,176,251,104,28,200,
90468 253,116,62,220,7,50,63,95,15,183,129,204,143,217,67,247,64,115,35,246,112,
90469 28,136,28,200,253,164,7,12,7,50,63,109,1,200,129,161,15,219,224,114,32,104,
90470 64,115,35,247,144,28,136,28,200,254,20,63,148,7,50,63,135,1,203,129,204,
90471 143,226,64,113,32,115,35,248,208,28,184,26,16,254,62,7,46,6,132,7,50,63,
90472 153,1,203,129,204,143,233,96,115,32,97,0,96,3,250,120,28,200,24,64,24,8,
90473 254,180,7,50,6,132,63,175,129,204,129,132,1,161,15,241,96,116,160,97,0,96,
90474 3,252,120,29,40,24,64,24,8,255,36,7,66,6,38,63,205,1,210,129,161,15,243,
90475 224,116,160,97,0,104,67,254,80,255,208,28,200,255,156,7,82,7,50,63,233,1,
90476 199,129,204,143,251,64,117,32,104,67,254,248,29,72,26,16,28,200,255,228,7,
90477 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,
90478 140,0,140,0,147,246,9,128,35,0,35,0,38,125,130,192,10,96,10,159,96,208,2,
90479 152,2,167,216,156,10,136,10,141,246,41,2,162,2,154,253,138,192,168,128,167,
90480 127,98,208,42,112,42,55,216,188,10,136,10,122,
90481 };
90482 const duk_uint8_t duk_unicode_caseconv_lc[706] = {
90483 160,3,0,3,128,184,6,192,7,192,112,24,144,37,96,64,54,32,81,64,128,226,0,
90484 235,65,129,199,1,230,130,3,145,3,177,34,7,70,7,134,36,15,244,13,236,24,32,
90485 0,34,129,0,65,0,67,4,0,166,32,172,41,132,40,11,64,19,9,208,85,184,80,19,
90486 240,19,248,12,57,32,33,160,172,114,244,67,244,24,248,64,248,0,129,241,129,
90487 241,0,195,229,3,228,2,7,206,7,204,4,15,164,15,160,6,31,104,31,96,16,63,16,
90488 63,0,32,126,96,126,64,64,253,64,253,0,129,251,129,251,0,67,247,67,238,0,
90489 135,242,7,220,130,15,236,15,232,2,31,218,31,118,4,63,208,63,192,8,127,168,
90490 125,232,16,255,192,251,192,33,255,161,247,192,68,44,4,46,4,9,45,137,52,13,
90491 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,
90492 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,
90493 152,13,160,32,28,176,28,193,32,59,192,59,226,64,124,128,124,193,0,252,0,
90494 252,148,2,34,2,35,18,4,140,4,142,20,13,192,13,196,16,30,192,30,200,192,70,
90495 0,70,18,32,145,64,145,102,193,48,65,48,131,130,104,2,104,176,30,0,30,1,150,
90496 61,64,61,66,192,125,100,125,68,33,99,57,99,64,50,200,2,200,22,69,157,101,
90497 157,128,169,144,41,144,75,211,64,83,64,142,167,34,167,35,15,78,101,78,102,
90498 126,157,230,157,232,21,59,245,59,248,90,121,10,121,16,84,242,212,242,226,
90499 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,
90500 64,126,224,127,0,139,28,139,28,193,6,3,14,3,16,8,6,224,6,228,21,61,80,19,
90501 48,32,3,1,150,2,105,4,4,118,4,120,8,67,28,180,156,23,240,192,94,0,63,192,
90502 96,64,148,192,97,128,149,0,99,128,119,64,99,192,150,64,100,0,150,192,100,
90503 64,100,128,100,192,152,0,101,0,152,192,101,192,154,0,102,0,102,64,103,64,
90504 156,128,103,192,157,64,105,192,106,0,107,128,162,0,109,192,164,128,124,64,
90505 124,192,125,128,101,64,125,192,111,192,136,0,103,128,142,139,25,64,143,64,
90506 102,128,143,139,25,128,144,192,96,0,145,0,162,64,145,64,163,0,221,128,221,
90507 192,223,192,252,192,225,128,235,0,227,0,243,0,243,192,245,192,253,0,238,0,
90508 254,64,252,129,48,1,51,199,167,128,55,199,239,7,236,199,243,7,240,199,251,
90509 7,249,71,255,7,252,200,73,128,242,72,74,128,26,200,74,192,57,72,76,136,83,
90510 136,96,200,97,11,24,11,24,75,24,128,154,203,24,199,95,75,25,0,159,75,27,64,
90511 148,75,27,128,156,75,27,192,148,11,28,0,148,139,60,139,60,233,223,71,94,
90512 105,226,233,227,41,227,64,153,105,234,192,151,41,235,0,152,105,235,64,155,
90513 41,236,0,167,169,236,64,161,233,236,128,167,105,236,234,212,233,240,169,
90514 240,233,241,41,229,41,241,64,160,169,241,135,99,128,128,152,64,13,32,96,
90515 224,
90516 };
90517 
90518 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
90519 /*
90520  *  Automatically generated by extract_caseconv.py, do not edit!
90521  */
90522 
90523 const duk_uint16_t duk_unicode_re_canon_lookup[65536] = {
90524 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,
90525 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,
90526 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,
90527 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,
90528 71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,123,124,125,
90529 126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
90530 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
90531 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
90532 180,924,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
90533 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
90534 216,217,218,219,220,221,222,223,192,193,194,195,196,197,198,199,200,201,
90535 202,203,204,205,206,207,208,209,210,211,212,213,214,247,216,217,218,219,
90536 220,221,222,376,256,256,258,258,260,260,262,262,264,264,266,266,268,268,
90537 270,270,272,272,274,274,276,276,278,278,280,280,282,282,284,284,286,286,
90538 288,288,290,290,292,292,294,294,296,296,298,298,300,300,302,302,304,305,
90539 306,306,308,308,310,310,312,313,313,315,315,317,317,319,319,321,321,323,
90540 323,325,325,327,327,329,330,330,332,332,334,334,336,336,338,338,340,340,
90541 342,342,344,344,346,346,348,348,350,350,352,352,354,354,356,356,358,358,
90542 360,360,362,362,364,364,366,366,368,368,370,370,372,372,374,374,376,377,
90543 377,379,379,381,381,383,579,385,386,386,388,388,390,391,391,393,394,395,
90544 395,397,398,399,400,401,401,403,404,502,406,407,408,408,573,411,412,413,
90545 544,415,416,416,418,418,420,420,422,423,423,425,426,427,428,428,430,431,
90546 431,433,434,435,435,437,437,439,440,440,442,443,444,444,446,503,448,449,
90547 450,451,452,452,452,455,455,455,458,458,458,461,461,463,463,465,465,467,
90548 467,469,469,471,471,473,473,475,475,398,478,478,480,480,482,482,484,484,
90549 486,486,488,488,490,490,492,492,494,494,496,497,497,497,500,500,502,503,
90550 504,504,506,506,508,508,510,510,512,512,514,514,516,516,518,518,520,520,
90551 522,522,524,524,526,526,528,528,530,530,532,532,534,534,536,536,538,538,
90552 540,540,542,542,544,545,546,546,548,548,550,550,552,552,554,554,556,556,
90553 558,558,560,560,562,562,564,565,566,567,568,569,570,571,571,573,574,11390,
90554 11391,577,577,579,580,581,582,582,584,584,586,586,588,588,590,590,11375,
90555 11373,11376,385,390,597,393,394,600,399,602,400,42923L,605,606,607,403,
90556 42924L,610,404,612,42893L,42922L,615,407,406,42926L,11362,42925L,621,622,
90557 412,624,11374,413,627,628,415,630,631,632,633,634,635,636,11364,638,639,
90558 422,641,42949L,425,644,645,646,42929L,430,580,433,434,581,653,654,655,656,
90559 657,439,659,660,661,662,663,664,665,666,667,668,42930L,42928L,671,672,673,
90560 674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,
90561 692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,
90562 710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,
90563 728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,
90564 746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,
90565 764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,
90566 782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,
90567 800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,
90568 818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,
90569 836,921,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,
90570 854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,
90571 872,873,874,875,876,877,878,879,880,880,882,882,884,885,886,886,888,889,
90572 890,1021,1022,1023,894,895,896,897,898,899,900,901,902,903,904,905,906,907,
90573 908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,
90574 926,927,928,929,930,931,932,933,934,935,936,937,938,939,902,904,905,906,
90575 944,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,
90576 931,931,932,933,934,935,936,937,938,939,908,910,911,975,914,920,978,979,
90577 980,934,928,975,984,984,986,986,988,988,990,990,992,992,994,994,996,996,
90578 998,998,1000,1000,1002,1002,1004,1004,1006,1006,922,929,1017,895,1012,917,
90579 1014,1015,1015,1017,1018,1018,1020,1021,1022,1023,1024,1025,1026,1027,1028,
90580 1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,
90581 1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,
90582 1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1040,1041,
90583 1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,
90584 1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,
90585 1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,
90586 1039,1120,1120,1122,1122,1124,1124,1126,1126,1128,1128,1130,1130,1132,1132,
90587 1134,1134,1136,1136,1138,1138,1140,1140,1142,1142,1144,1144,1146,1146,1148,
90588 1148,1150,1150,1152,1152,1154,1155,1156,1157,1158,1159,1160,1161,1162,1162,
90589 1164,1164,1166,1166,1168,1168,1170,1170,1172,1172,1174,1174,1176,1176,1178,
90590 1178,1180,1180,1182,1182,1184,1184,1186,1186,1188,1188,1190,1190,1192,1192,
90591 1194,1194,1196,1196,1198,1198,1200,1200,1202,1202,1204,1204,1206,1206,1208,
90592 1208,1210,1210,1212,1212,1214,1214,1216,1217,1217,1219,1219,1221,1221,1223,
90593 1223,1225,1225,1227,1227,1229,1229,1216,1232,1232,1234,1234,1236,1236,1238,
90594 1238,1240,1240,1242,1242,1244,1244,1246,1246,1248,1248,1250,1250,1252,1252,
90595 1254,1254,1256,1256,1258,1258,1260,1260,1262,1262,1264,1264,1266,1266,1268,
90596 1268,1270,1270,1272,1272,1274,1274,1276,1276,1278,1278,1280,1280,1282,1282,
90597 1284,1284,1286,1286,1288,1288,1290,1290,1292,1292,1294,1294,1296,1296,1298,
90598 1298,1300,1300,1302,1302,1304,1304,1306,1306,1308,1308,1310,1310,1312,1312,
90599 1314,1314,1316,1316,1318,1318,1320,1320,1322,1322,1324,1324,1326,1326,1328,
90600 1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,
90601 1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,
90602 1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,
90603 1374,1375,1376,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,
90604 1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,
90605 1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1415,1416,1417,1418,
90606 1419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,
90607 1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,
90608 1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,
90609 1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,
90610 1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,
90611 1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,
90612 1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,
90613 1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,
90614 1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,
90615 1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,
90616 1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,
90617 1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,
90618 1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,
90619 1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,
90620 1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,
90621 1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,
90622 1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,
90623 1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,
90624 1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,
90625 1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,
90626 1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,
90627 1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,
90628 1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,
90629 1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,
90630 1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,
90631 1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,
90632 1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,
90633 1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,
90634 1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,
90635 1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,
90636 1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,
90637 1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,
90638 1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,
90639 1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,
90640 1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,
90641 1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,
90642 1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,
90643 1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,
90644 1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,
90645 2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,
90646 2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,
90647 2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,
90648 2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,
90649 2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,
90650 2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,
90651 2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,
90652 2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,
90653 2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,
90654 2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,
90655 2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,
90656 2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,
90657 2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,
90658 2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,
90659 2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,
90660 2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,
90661 2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,
90662 2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,
90663 2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,
90664 2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,
90665 2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,
90666 2319,2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,
90667 2334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,
90668 2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,
90669 2364,2365,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,
90670 2379,2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,
90671 2394,2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,
90672 2409,2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,
90673 2424,2425,2426,2427,2428,2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,
90674 2439,2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,
90675 2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,
90676 2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,
90677 2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,
90678 2499,2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,
90679 2514,2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,
90680 2529,2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,
90681 2544,2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,
90682 2559,2560,2561,2562,2563,2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,
90683 2574,2575,2576,2577,2578,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,
90684 2589,2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2601,2602,2603,
90685 2604,2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,
90686 2619,2620,2621,2622,2623,2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,
90687 2634,2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,
90688 2649,2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,
90689 2664,2665,2666,2667,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,
90690 2679,2680,2681,2682,2683,2684,2685,2686,2687,2688,2689,2690,2691,2692,2693,
90691 2694,2695,2696,2697,2698,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,
90692 2709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,
90693 2724,2725,2726,2727,2728,2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,
90694 2739,2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,
90695 2754,2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,
90696 2769,2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,
90697 2784,2785,2786,2787,2788,2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,
90698 2799,2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,
90699 2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,
90700 2829,2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,
90701 2844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,
90702 2859,2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,
90703 2874,2875,2876,2877,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,
90704 2889,2890,2891,2892,2893,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,
90705 2904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,
90706 2919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,
90707 2934,2935,2936,2937,2938,2939,2940,2941,2942,2943,2944,2945,2946,2947,2948,
90708 2949,2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,
90709 2964,2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,
90710 2979,2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,
90711 2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,
90712 3009,3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,
90713 3024,3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,
90714 3039,3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,
90715 3054,3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,
90716 3069,3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,
90717 3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,
90718 3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,
90719 3114,3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,
90720 3129,3130,3131,3132,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,
90721 3144,3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,
90722 3159,3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,
90723 3174,3175,3176,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187,3188,
90724 3189,3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201,3202,3203,
90725 3204,3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,
90726 3219,3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,
90727 3234,3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,
90728 3249,3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,
90729 3264,3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,
90730 3279,3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,
90731 3294,3295,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,
90732 3309,3310,3311,3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,
90733 3324,3325,3326,3327,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,
90734 3339,3340,3341,3342,3343,3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,
90735 3354,3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,
90736 3369,3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,
90737 3384,3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,
90738 3399,3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,
90739 3414,3415,3416,3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,
90740 3429,3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,
90741 3444,3445,3446,3447,3448,3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,
90742 3459,3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,
90743 3474,3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,
90744 3489,3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,
90745 3504,3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,
90746 3519,3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,
90747 3534,3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,
90748 3549,3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,
90749 3564,3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,
90750 3579,3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593,
90751 3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,
90752 3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,
90753 3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,
90754 3639,3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,
90755 3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,
90756 3669,3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,
90757 3684,3685,3686,3687,3688,3689,3690,3691,3692,3693,3694,3695,3696,3697,3698,
90758 3699,3700,3701,3702,3703,3704,3705,3706,3707,3708,3709,3710,3711,3712,3713,
90759 3714,3715,3716,3717,3718,3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,
90760 3729,3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,
90761 3744,3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,
90762 3759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,
90763 3774,3775,3776,3777,3778,3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,
90764 3789,3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3802,3803,
90765 3804,3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,
90766 3819,3820,3821,3822,3823,3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,
90767 3834,3835,3836,3837,3838,3839,3840,3841,3842,3843,3844,3845,3846,3847,3848,
90768 3849,3850,3851,3852,3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,
90769 3864,3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,
90770 3879,3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,
90771 3894,3895,3896,3897,3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,
90772 3909,3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,
90773 3924,3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,
90774 3939,3940,3941,3942,3943,3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,
90775 3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,
90776 3969,3970,3971,3972,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,
90777 3984,3985,3986,3987,3988,3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,
90778 3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,
90779 4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,
90780 4029,4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,
90781 4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,
90782 4059,4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,
90783 4074,4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,
90784 4089,4090,4091,4092,4093,4094,4095,4096,4097,4098,4099,4100,4101,4102,4103,
90785 4104,4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,
90786 4119,4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,
90787 4134,4135,4136,4137,4138,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,
90788 4149,4150,4151,4152,4153,4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,
90789 4164,4165,4166,4167,4168,4169,4170,4171,4172,4173,4174,4175,4176,4177,4178,
90790 4179,4180,4181,4182,4183,4184,4185,4186,4187,4188,4189,4190,4191,4192,4193,
90791 4194,4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205,4206,4207,4208,
90792 4209,4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,
90793 4224,4225,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4238,
90794 4239,4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,
90795 4254,4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,
90796 4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,
90797 4284,4285,4286,4287,4288,4289,4290,4291,4292,4293,4294,4295,4296,4297,4298,
90798 4299,4300,4301,4302,4303,7312,7313,7314,7315,7316,7317,7318,7319,7320,7321,
90799 7322,7323,7324,7325,7326,7327,7328,7329,7330,7331,7332,7333,7334,7335,7336,
90800 7337,7338,7339,7340,7341,7342,7343,7344,7345,7346,7347,7348,7349,7350,7351,
90801 7352,7353,7354,4347,4348,7357,7358,7359,4352,4353,4354,4355,4356,4357,4358,
90802 4359,4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,
90803 4374,4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,
90804 4389,4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,
90805 4404,4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416,4417,4418,
90806 4419,4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,
90807 4434,4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,
90808 4449,4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,
90809 4464,4465,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,
90810 4479,4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,
90811 4494,4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,
90812 4509,4510,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,
90813 4524,4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,
90814 4539,4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,
90815 4554,4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,
90816 4569,4570,4571,4572,4573,4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,
90817 4584,4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,
90818 4599,4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,
90819 4614,4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,
90820 4629,4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,
90821 4644,4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,
90822 4659,4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,
90823 4674,4675,4676,4677,4678,4679,4680,4681,4682,4683,4684,4685,4686,4687,4688,
90824 4689,4690,4691,4692,4693,4694,4695,4696,4697,4698,4699,4700,4701,4702,4703,
90825 4704,4705,4706,4707,4708,4709,4710,4711,4712,4713,4714,4715,4716,4717,4718,
90826 4719,4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,
90827 4734,4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4745,4746,4747,4748,
90828 4749,4750,4751,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,
90829 4764,4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,
90830 4779,4780,4781,4782,4783,4784,4785,4786,4787,4788,4789,4790,4791,4792,4793,
90831 4794,4795,4796,4797,4798,4799,4800,4801,4802,4803,4804,4805,4806,4807,4808,
90832 4809,4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4823,
90833 4824,4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,
90834 4839,4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,
90835 4854,4855,4856,4857,4858,4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,
90836 4869,4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4881,4882,4883,
90837 4884,4885,4886,4887,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,
90838 4899,4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,
90839 4914,4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,
90840 4929,4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,
90841 4944,4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4955,4956,4957,4958,
90842 4959,4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970,4971,4972,4973,
90843 4974,4975,4976,4977,4978,4979,4980,4981,4982,4983,4984,4985,4986,4987,4988,
90844 4989,4990,4991,4992,4993,4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,
90845 5004,5005,5006,5007,5008,5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,
90846 5019,5020,5021,5022,5023,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,
90847 5034,5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,
90848 5049,5050,5051,5052,5053,5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,
90849 5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,
90850 5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,
90851 5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,
90852 5109,5110,5111,5104,5105,5106,5107,5108,5109,5118,5119,5120,5121,5122,5123,
90853 5124,5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,
90854 5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,
90855 5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,
90856 5169,5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,
90857 5184,5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,
90858 5199,5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,
90859 5214,5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,
90860 5229,5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,
90861 5244,5245,5246,5247,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,
90862 5259,5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,
90863 5274,5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,
90864 5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,
90865 5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,
90866 5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,
90867 5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,
90868 5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,
90869 5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,
90870 5379,5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,
90871 5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,
90872 5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,
90873 5424,5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,
90874 5439,5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,
90875 5454,5455,5456,5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,
90876 5469,5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,
90877 5484,5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,
90878 5499,5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,
90879 5514,5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,
90880 5529,5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,
90881 5544,5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,
90882 5559,5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570,5571,5572,5573,
90883 5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585,5586,5587,5588,
90884 5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600,5601,5602,5603,
90885 5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616,5617,5618,
90886 5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632,5633,
90887 5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648,
90888 5649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,
90889 5664,5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,
90890 5679,5680,5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,
90891 5694,5695,5696,5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,
90892 5709,5710,5711,5712,5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,
90893 5724,5725,5726,5727,5728,5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,
90894 5739,5740,5741,5742,5743,5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,
90895 5754,5755,5756,5757,5758,5759,5760,5761,5762,5763,5764,5765,5766,5767,5768,
90896 5769,5770,5771,5772,5773,5774,5775,5776,5777,5778,5779,5780,5781,5782,5783,
90897 5784,5785,5786,5787,5788,5789,5790,5791,5792,5793,5794,5795,5796,5797,5798,
90898 5799,5800,5801,5802,5803,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,
90899 5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,
90900 5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,
90901 5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,
90902 5859,5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872,5873,
90903 5874,5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888,
90904 5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,
90905 5904,5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,
90906 5919,5920,5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,
90907 5934,5935,5936,5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,
90908 5949,5950,5951,5952,5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,
90909 5964,5965,5966,5967,5968,5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,
90910 5979,5980,5981,5982,5983,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,
90911 5994,5995,5996,5997,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6008,
90912 6009,6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020,6021,6022,6023,
90913 6024,6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,
90914 6039,6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,
90915 6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068,
90916 6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,
90917 6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,
90918 6099,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,
90919 6114,6115,6116,6117,6118,6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,
90920 6129,6130,6131,6132,6133,6134,6135,6136,6137,6138,6139,6140,6141,6142,6143,
90921 6144,6145,6146,6147,6148,6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,
90922 6159,6160,6161,6162,6163,6164,6165,6166,6167,6168,6169,6170,6171,6172,6173,
90923 6174,6175,6176,6177,6178,6179,6180,6181,6182,6183,6184,6185,6186,6187,6188,
90924 6189,6190,6191,6192,6193,6194,6195,6196,6197,6198,6199,6200,6201,6202,6203,
90925 6204,6205,6206,6207,6208,6209,6210,6211,6212,6213,6214,6215,6216,6217,6218,
90926 6219,6220,6221,6222,6223,6224,6225,6226,6227,6228,6229,6230,6231,6232,6233,
90927 6234,6235,6236,6237,6238,6239,6240,6241,6242,6243,6244,6245,6246,6247,6248,
90928 6249,6250,6251,6252,6253,6254,6255,6256,6257,6258,6259,6260,6261,6262,6263,
90929 6264,6265,6266,6267,6268,6269,6270,6271,6272,6273,6274,6275,6276,6277,6278,
90930 6279,6280,6281,6282,6283,6284,6285,6286,6287,6288,6289,6290,6291,6292,6293,
90931 6294,6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305,6306,6307,6308,
90932 6309,6310,6311,6312,6313,6314,6315,6316,6317,6318,6319,6320,6321,6322,6323,
90933 6324,6325,6326,6327,6328,6329,6330,6331,6332,6333,6334,6335,6336,6337,6338,
90934 6339,6340,6341,6342,6343,6344,6345,6346,6347,6348,6349,6350,6351,6352,6353,
90935 6354,6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365,6366,6367,6368,
90936 6369,6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381,6382,6383,
90937 6384,6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395,6396,6397,6398,
90938 6399,6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,
90939 6414,6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,6426,6427,6428,
90940 6429,6430,6431,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,
90941 6444,6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,
90942 6459,6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472,6473,
90943 6474,6475,6476,6477,6478,6479,6480,6481,6482,6483,6484,6485,6486,6487,6488,
90944 6489,6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,
90945 6504,6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516,6517,6518,
90946 6519,6520,6521,6522,6523,6524,6525,6526,6527,6528,6529,6530,6531,6532,6533,
90947 6534,6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,
90948 6549,6550,6551,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,
90949 6564,6565,6566,6567,6568,6569,6570,6571,6572,6573,6574,6575,6576,6577,6578,
90950 6579,6580,6581,6582,6583,6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,
90951 6594,6595,6596,6597,6598,6599,6600,6601,6602,6603,6604,6605,6606,6607,6608,
90952 6609,6610,6611,6612,6613,6614,6615,6616,6617,6618,6619,6620,6621,6622,6623,
90953 6624,6625,6626,6627,6628,6629,6630,6631,6632,6633,6634,6635,6636,6637,6638,
90954 6639,6640,6641,6642,6643,6644,6645,6646,6647,6648,6649,6650,6651,6652,6653,
90955 6654,6655,6656,6657,6658,6659,6660,6661,6662,6663,6664,6665,6666,6667,6668,
90956 6669,6670,6671,6672,6673,6674,6675,6676,6677,6678,6679,6680,6681,6682,6683,
90957 6684,6685,6686,6687,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,6698,
90958 6699,6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,
90959 6714,6715,6716,6717,6718,6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,
90960 6729,6730,6731,6732,6733,6734,6735,6736,6737,6738,6739,6740,6741,6742,6743,
90961 6744,6745,6746,6747,6748,6749,6750,6751,6752,6753,6754,6755,6756,6757,6758,
90962 6759,6760,6761,6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,
90963 6774,6775,6776,6777,6778,6779,6780,6781,6782,6783,6784,6785,6786,6787,6788,
90964 6789,6790,6791,6792,6793,6794,6795,6796,6797,6798,6799,6800,6801,6802,6803,
90965 6804,6805,6806,6807,6808,6809,6810,6811,6812,6813,6814,6815,6816,6817,6818,
90966 6819,6820,6821,6822,6823,6824,6825,6826,6827,6828,6829,6830,6831,6832,6833,
90967 6834,6835,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,6847,6848,
90968 6849,6850,6851,6852,6853,6854,6855,6856,6857,6858,6859,6860,6861,6862,6863,
90969 6864,6865,6866,6867,6868,6869,6870,6871,6872,6873,6874,6875,6876,6877,6878,
90970 6879,6880,6881,6882,6883,6884,6885,6886,6887,6888,6889,6890,6891,6892,6893,
90971 6894,6895,6896,6897,6898,6899,6900,6901,6902,6903,6904,6905,6906,6907,6908,
90972 6909,6910,6911,6912,6913,6914,6915,6916,6917,6918,6919,6920,6921,6922,6923,
90973 6924,6925,6926,6927,6928,6929,6930,6931,6932,6933,6934,6935,6936,6937,6938,
90974 6939,6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,
90975 6954,6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966,6967,6968,
90976 6969,6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,6981,6982,6983,
90977 6984,6985,6986,6987,6988,6989,6990,6991,6992,6993,6994,6995,6996,6997,6998,
90978 6999,7000,7001,7002,7003,7004,7005,7006,7007,7008,7009,7010,7011,7012,7013,
90979 7014,7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027,7028,
90980 7029,7030,7031,7032,7033,7034,7035,7036,7037,7038,7039,7040,7041,7042,7043,
90981 7044,7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,
90982 7059,7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,7071,7072,7073,
90983 7074,7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7086,7087,7088,
90984 7089,7090,7091,7092,7093,7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,
90985 7104,7105,7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,
90986 7119,7120,7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,
90987 7134,7135,7136,7137,7138,7139,7140,7141,7142,7143,7144,7145,7146,7147,7148,
90988 7149,7150,7151,7152,7153,7154,7155,7156,7157,7158,7159,7160,7161,7162,7163,
90989 7164,7165,7166,7167,7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,
90990 7179,7180,7181,7182,7183,7184,7185,7186,7187,7188,7189,7190,7191,7192,7193,
90991 7194,7195,7196,7197,7198,7199,7200,7201,7202,7203,7204,7205,7206,7207,7208,
90992 7209,7210,7211,7212,7213,7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,
90993 7224,7225,7226,7227,7228,7229,7230,7231,7232,7233,7234,7235,7236,7237,7238,
90994 7239,7240,7241,7242,7243,7244,7245,7246,7247,7248,7249,7250,7251,7252,7253,
90995 7254,7255,7256,7257,7258,7259,7260,7261,7262,7263,7264,7265,7266,7267,7268,
90996 7269,7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280,7281,7282,7283,
90997 7284,7285,7286,7287,7288,7289,7290,7291,7292,7293,7294,7295,1042,1044,1054,
90998 1057,1058,1058,1066,1122,42570L,7305,7306,7307,7308,7309,7310,7311,7312,
90999 7313,7314,7315,7316,7317,7318,7319,7320,7321,7322,7323,7324,7325,7326,7327,
91000 7328,7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339,7340,7341,7342,
91001 7343,7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,7354,7355,7356,7357,
91002 7358,7359,7360,7361,7362,7363,7364,7365,7366,7367,7368,7369,7370,7371,7372,
91003 7373,7374,7375,7376,7377,7378,7379,7380,7381,7382,7383,7384,7385,7386,7387,
91004 7388,7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400,7401,7402,
91005 7403,7404,7405,7406,7407,7408,7409,7410,7411,7412,7413,7414,7415,7416,7417,
91006 7418,7419,7420,7421,7422,7423,7424,7425,7426,7427,7428,7429,7430,7431,7432,
91007 7433,7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447,
91008 7448,7449,7450,7451,7452,7453,7454,7455,7456,7457,7458,7459,7460,7461,7462,
91009 7463,7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,7475,7476,7477,
91010 7478,7479,7480,7481,7482,7483,7484,7485,7486,7487,7488,7489,7490,7491,7492,
91011 7493,7494,7495,7496,7497,7498,7499,7500,7501,7502,7503,7504,7505,7506,7507,
91012 7508,7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,7522,
91013 7523,7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537,
91014 7538,7539,7540,7541,7542,7543,7544,42877L,7546,7547,7548,11363,7550,7551,
91015 7552,7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,
91016 42950L,7567,7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,
91017 7580,7581,7582,7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,
91018 7595,7596,7597,7598,7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,
91019 7610,7611,7612,7613,7614,7615,7616,7617,7618,7619,7620,7621,7622,7623,7624,
91020 7625,7626,7627,7628,7629,7630,7631,7632,7633,7634,7635,7636,7637,7638,7639,
91021 7640,7641,7642,7643,7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,
91022 7655,7656,7657,7658,7659,7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,
91023 7670,7671,7672,7673,7674,7675,7676,7677,7678,7679,7680,7680,7682,7682,7684,
91024 7684,7686,7686,7688,7688,7690,7690,7692,7692,7694,7694,7696,7696,7698,7698,
91025 7700,7700,7702,7702,7704,7704,7706,7706,7708,7708,7710,7710,7712,7712,7714,
91026 7714,7716,7716,7718,7718,7720,7720,7722,7722,7724,7724,7726,7726,7728,7728,
91027 7730,7730,7732,7732,7734,7734,7736,7736,7738,7738,7740,7740,7742,7742,7744,
91028 7744,7746,7746,7748,7748,7750,7750,7752,7752,7754,7754,7756,7756,7758,7758,
91029 7760,7760,7762,7762,7764,7764,7766,7766,7768,7768,7770,7770,7772,7772,7774,
91030 7774,7776,7776,7778,7778,7780,7780,7782,7782,7784,7784,7786,7786,7788,7788,
91031 7790,7790,7792,7792,7794,7794,7796,7796,7798,7798,7800,7800,7802,7802,7804,
91032 7804,7806,7806,7808,7808,7810,7810,7812,7812,7814,7814,7816,7816,7818,7818,
91033 7820,7820,7822,7822,7824,7824,7826,7826,7828,7828,7830,7831,7832,7833,7834,
91034 7776,7836,7837,7838,7839,7840,7840,7842,7842,7844,7844,7846,7846,7848,7848,
91035 7850,7850,7852,7852,7854,7854,7856,7856,7858,7858,7860,7860,7862,7862,7864,
91036 7864,7866,7866,7868,7868,7870,7870,7872,7872,7874,7874,7876,7876,7878,7878,
91037 7880,7880,7882,7882,7884,7884,7886,7886,7888,7888,7890,7890,7892,7892,7894,
91038 7894,7896,7896,7898,7898,7900,7900,7902,7902,7904,7904,7906,7906,7908,7908,
91039 7910,7910,7912,7912,7914,7914,7916,7916,7918,7918,7920,7920,7922,7922,7924,
91040 7924,7926,7926,7928,7928,7930,7930,7932,7932,7934,7934,7944,7945,7946,7947,
91041 7948,7949,7950,7951,7944,7945,7946,7947,7948,7949,7950,7951,7960,7961,7962,
91042 7963,7964,7965,7958,7959,7960,7961,7962,7963,7964,7965,7966,7967,7976,7977,
91043 7978,7979,7980,7981,7982,7983,7976,7977,7978,7979,7980,7981,7982,7983,7992,
91044 7993,7994,7995,7996,7997,7998,7999,7992,7993,7994,7995,7996,7997,7998,7999,
91045 8008,8009,8010,8011,8012,8013,8006,8007,8008,8009,8010,8011,8012,8013,8014,
91046 8015,8016,8025,8018,8027,8020,8029,8022,8031,8024,8025,8026,8027,8028,8029,
91047 8030,8031,8040,8041,8042,8043,8044,8045,8046,8047,8040,8041,8042,8043,8044,
91048 8045,8046,8047,8122,8123,8136,8137,8138,8139,8154,8155,8184,8185,8170,8171,
91049 8186,8187,8062,8063,8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,
91050 8075,8076,8077,8078,8079,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,
91051 8090,8091,8092,8093,8094,8095,8096,8097,8098,8099,8100,8101,8102,8103,8104,
91052 8105,8106,8107,8108,8109,8110,8111,8120,8121,8114,8115,8116,8117,8118,8119,
91053 8120,8121,8122,8123,8124,8125,921,8127,8128,8129,8130,8131,8132,8133,8134,
91054 8135,8136,8137,8138,8139,8140,8141,8142,8143,8152,8153,8146,8147,8148,8149,
91055 8150,8151,8152,8153,8154,8155,8156,8157,8158,8159,8168,8169,8162,8163,8164,
91056 8172,8166,8167,8168,8169,8170,8171,8172,8173,8174,8175,8176,8177,8178,8179,
91057 8180,8181,8182,8183,8184,8185,8186,8187,8188,8189,8190,8191,8192,8193,8194,
91058 8195,8196,8197,8198,8199,8200,8201,8202,8203,8204,8205,8206,8207,8208,8209,
91059 8210,8211,8212,8213,8214,8215,8216,8217,8218,8219,8220,8221,8222,8223,8224,
91060 8225,8226,8227,8228,8229,8230,8231,8232,8233,8234,8235,8236,8237,8238,8239,
91061 8240,8241,8242,8243,8244,8245,8246,8247,8248,8249,8250,8251,8252,8253,8254,
91062 8255,8256,8257,8258,8259,8260,8261,8262,8263,8264,8265,8266,8267,8268,8269,
91063 8270,8271,8272,8273,8274,8275,8276,8277,8278,8279,8280,8281,8282,8283,8284,
91064 8285,8286,8287,8288,8289,8290,8291,8292,8293,8294,8295,8296,8297,8298,8299,
91065 8300,8301,8302,8303,8304,8305,8306,8307,8308,8309,8310,8311,8312,8313,8314,
91066 8315,8316,8317,8318,8319,8320,8321,8322,8323,8324,8325,8326,8327,8328,8329,
91067 8330,8331,8332,8333,8334,8335,8336,8337,8338,8339,8340,8341,8342,8343,8344,
91068 8345,8346,8347,8348,8349,8350,8351,8352,8353,8354,8355,8356,8357,8358,8359,
91069 8360,8361,8362,8363,8364,8365,8366,8367,8368,8369,8370,8371,8372,8373,8374,
91070 8375,8376,8377,8378,8379,8380,8381,8382,8383,8384,8385,8386,8387,8388,8389,
91071 8390,8391,8392,8393,8394,8395,8396,8397,8398,8399,8400,8401,8402,8403,8404,
91072 8405,8406,8407,8408,8409,8410,8411,8412,8413,8414,8415,8416,8417,8418,8419,
91073 8420,8421,8422,8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,8433,8434,
91074 8435,8436,8437,8438,8439,8440,8441,8442,8443,8444,8445,8446,8447,8448,8449,
91075 8450,8451,8452,8453,8454,8455,8456,8457,8458,8459,8460,8461,8462,8463,8464,
91076 8465,8466,8467,8468,8469,8470,8471,8472,8473,8474,8475,8476,8477,8478,8479,
91077 8480,8481,8482,8483,8484,8485,8486,8487,8488,8489,8490,8491,8492,8493,8494,
91078 8495,8496,8497,8498,8499,8500,8501,8502,8503,8504,8505,8506,8507,8508,8509,
91079 8510,8511,8512,8513,8514,8515,8516,8517,8518,8519,8520,8521,8522,8523,8524,
91080 8525,8498,8527,8528,8529,8530,8531,8532,8533,8534,8535,8536,8537,8538,8539,
91081 8540,8541,8542,8543,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,
91082 8555,8556,8557,8558,8559,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,
91083 8554,8555,8556,8557,8558,8559,8576,8577,8578,8579,8579,8581,8582,8583,8584,
91084 8585,8586,8587,8588,8589,8590,8591,8592,8593,8594,8595,8596,8597,8598,8599,
91085 8600,8601,8602,8603,8604,8605,8606,8607,8608,8609,8610,8611,8612,8613,8614,
91086 8615,8616,8617,8618,8619,8620,8621,8622,8623,8624,8625,8626,8627,8628,8629,
91087 8630,8631,8632,8633,8634,8635,8636,8637,8638,8639,8640,8641,8642,8643,8644,
91088 8645,8646,8647,8648,8649,8650,8651,8652,8653,8654,8655,8656,8657,8658,8659,
91089 8660,8661,8662,8663,8664,8665,8666,8667,8668,8669,8670,8671,8672,8673,8674,
91090 8675,8676,8677,8678,8679,8680,8681,8682,8683,8684,8685,8686,8687,8688,8689,
91091 8690,8691,8692,8693,8694,8695,8696,8697,8698,8699,8700,8701,8702,8703,8704,
91092 8705,8706,8707,8708,8709,8710,8711,8712,8713,8714,8715,8716,8717,8718,8719,
91093 8720,8721,8722,8723,8724,8725,8726,8727,8728,8729,8730,8731,8732,8733,8734,
91094 8735,8736,8737,8738,8739,8740,8741,8742,8743,8744,8745,8746,8747,8748,8749,
91095 8750,8751,8752,8753,8754,8755,8756,8757,8758,8759,8760,8761,8762,8763,8764,
91096 8765,8766,8767,8768,8769,8770,8771,8772,8773,8774,8775,8776,8777,8778,8779,
91097 8780,8781,8782,8783,8784,8785,8786,8787,8788,8789,8790,8791,8792,8793,8794,
91098 8795,8796,8797,8798,8799,8800,8801,8802,8803,8804,8805,8806,8807,8808,8809,
91099 8810,8811,8812,8813,8814,8815,8816,8817,8818,8819,8820,8821,8822,8823,8824,
91100 8825,8826,8827,8828,8829,8830,8831,8832,8833,8834,8835,8836,8837,8838,8839,
91101 8840,8841,8842,8843,8844,8845,8846,8847,8848,8849,8850,8851,8852,8853,8854,
91102 8855,8856,8857,8858,8859,8860,8861,8862,8863,8864,8865,8866,8867,8868,8869,
91103 8870,8871,8872,8873,8874,8875,8876,8877,8878,8879,8880,8881,8882,8883,8884,
91104 8885,8886,8887,8888,8889,8890,8891,8892,8893,8894,8895,8896,8897,8898,8899,
91105 8900,8901,8902,8903,8904,8905,8906,8907,8908,8909,8910,8911,8912,8913,8914,
91106 8915,8916,8917,8918,8919,8920,8921,8922,8923,8924,8925,8926,8927,8928,8929,
91107 8930,8931,8932,8933,8934,8935,8936,8937,8938,8939,8940,8941,8942,8943,8944,
91108 8945,8946,8947,8948,8949,8950,8951,8952,8953,8954,8955,8956,8957,8958,8959,
91109 8960,8961,8962,8963,8964,8965,8966,8967,8968,8969,8970,8971,8972,8973,8974,
91110 8975,8976,8977,8978,8979,8980,8981,8982,8983,8984,8985,8986,8987,8988,8989,
91111 8990,8991,8992,8993,8994,8995,8996,8997,8998,8999,9000,9001,9002,9003,9004,
91112 9005,9006,9007,9008,9009,9010,9011,9012,9013,9014,9015,9016,9017,9018,9019,
91113 9020,9021,9022,9023,9024,9025,9026,9027,9028,9029,9030,9031,9032,9033,9034,
91114 9035,9036,9037,9038,9039,9040,9041,9042,9043,9044,9045,9046,9047,9048,9049,
91115 9050,9051,9052,9053,9054,9055,9056,9057,9058,9059,9060,9061,9062,9063,9064,
91116 9065,9066,9067,9068,9069,9070,9071,9072,9073,9074,9075,9076,9077,9078,9079,
91117 9080,9081,9082,9083,9084,9085,9086,9087,9088,9089,9090,9091,9092,9093,9094,
91118 9095,9096,9097,9098,9099,9100,9101,9102,9103,9104,9105,9106,9107,9108,9109,
91119 9110,9111,9112,9113,9114,9115,9116,9117,9118,9119,9120,9121,9122,9123,9124,
91120 9125,9126,9127,9128,9129,9130,9131,9132,9133,9134,9135,9136,9137,9138,9139,
91121 9140,9141,9142,9143,9144,9145,9146,9147,9148,9149,9150,9151,9152,9153,9154,
91122 9155,9156,9157,9158,9159,9160,9161,9162,9163,9164,9165,9166,9167,9168,9169,
91123 9170,9171,9172,9173,9174,9175,9176,9177,9178,9179,9180,9181,9182,9183,9184,
91124 9185,9186,9187,9188,9189,9190,9191,9192,9193,9194,9195,9196,9197,9198,9199,
91125 9200,9201,9202,9203,9204,9205,9206,9207,9208,9209,9210,9211,9212,9213,9214,
91126 9215,9216,9217,9218,9219,9220,9221,9222,9223,9224,9225,9226,9227,9228,9229,
91127 9230,9231,9232,9233,9234,9235,9236,9237,9238,9239,9240,9241,9242,9243,9244,
91128 9245,9246,9247,9248,9249,9250,9251,9252,9253,9254,9255,9256,9257,9258,9259,
91129 9260,9261,9262,9263,9264,9265,9266,9267,9268,9269,9270,9271,9272,9273,9274,
91130 9275,9276,9277,9278,9279,9280,9281,9282,9283,9284,9285,9286,9287,9288,9289,
91131 9290,9291,9292,9293,9294,9295,9296,9297,9298,9299,9300,9301,9302,9303,9304,
91132 9305,9306,9307,9308,9309,9310,9311,9312,9313,9314,9315,9316,9317,9318,9319,
91133 9320,9321,9322,9323,9324,9325,9326,9327,9328,9329,9330,9331,9332,9333,9334,
91134 9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345,9346,9347,9348,9349,
91135 9350,9351,9352,9353,9354,9355,9356,9357,9358,9359,9360,9361,9362,9363,9364,
91136 9365,9366,9367,9368,9369,9370,9371,9372,9373,9374,9375,9376,9377,9378,9379,
91137 9380,9381,9382,9383,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,
91138 9395,9396,9397,9398,9399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,
91139 9410,9411,9412,9413,9414,9415,9416,9417,9418,9419,9420,9421,9422,9423,9398,
91140 9399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,9413,
91141 9414,9415,9416,9417,9418,9419,9420,9421,9422,9423,9450,9451,9452,9453,9454,
91142 9455,9456,9457,9458,9459,9460,9461,9462,9463,9464,9465,9466,9467,9468,9469,
91143 9470,9471,9472,9473,9474,9475,9476,9477,9478,9479,9480,9481,9482,9483,9484,
91144 9485,9486,9487,9488,9489,9490,9491,9492,9493,9494,9495,9496,9497,9498,9499,
91145 9500,9501,9502,9503,9504,9505,9506,9507,9508,9509,9510,9511,9512,9513,9514,
91146 9515,9516,9517,9518,9519,9520,9521,9522,9523,9524,9525,9526,9527,9528,9529,
91147 9530,9531,9532,9533,9534,9535,9536,9537,9538,9539,9540,9541,9542,9543,9544,
91148 9545,9546,9547,9548,9549,9550,9551,9552,9553,9554,9555,9556,9557,9558,9559,
91149 9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,9570,9571,9572,9573,9574,
91150 9575,9576,9577,9578,9579,9580,9581,9582,9583,9584,9585,9586,9587,9588,9589,
91151 9590,9591,9592,9593,9594,9595,9596,9597,9598,9599,9600,9601,9602,9603,9604,
91152 9605,9606,9607,9608,9609,9610,9611,9612,9613,9614,9615,9616,9617,9618,9619,
91153 9620,9621,9622,9623,9624,9625,9626,9627,9628,9629,9630,9631,9632,9633,9634,
91154 9635,9636,9637,9638,9639,9640,9641,9642,9643,9644,9645,9646,9647,9648,9649,
91155 9650,9651,9652,9653,9654,9655,9656,9657,9658,9659,9660,9661,9662,9663,9664,
91156 9665,9666,9667,9668,9669,9670,9671,9672,9673,9674,9675,9676,9677,9678,9679,
91157 9680,9681,9682,9683,9684,9685,9686,9687,9688,9689,9690,9691,9692,9693,9694,
91158 9695,9696,9697,9698,9699,9700,9701,9702,9703,9704,9705,9706,9707,9708,9709,
91159 9710,9711,9712,9713,9714,9715,9716,9717,9718,9719,9720,9721,9722,9723,9724,
91160 9725,9726,9727,9728,9729,9730,9731,9732,9733,9734,9735,9736,9737,9738,9739,
91161 9740,9741,9742,9743,9744,9745,9746,9747,9748,9749,9750,9751,9752,9753,9754,
91162 9755,9756,9757,9758,9759,9760,9761,9762,9763,9764,9765,9766,9767,9768,9769,
91163 9770,9771,9772,9773,9774,9775,9776,9777,9778,9779,9780,9781,9782,9783,9784,
91164 9785,9786,9787,9788,9789,9790,9791,9792,9793,9794,9795,9796,9797,9798,9799,
91165 9800,9801,9802,9803,9804,9805,9806,9807,9808,9809,9810,9811,9812,9813,9814,
91166 9815,9816,9817,9818,9819,9820,9821,9822,9823,9824,9825,9826,9827,9828,9829,
91167 9830,9831,9832,9833,9834,9835,9836,9837,9838,9839,9840,9841,9842,9843,9844,
91168 9845,9846,9847,9848,9849,9850,9851,9852,9853,9854,9855,9856,9857,9858,9859,
91169 9860,9861,9862,9863,9864,9865,9866,9867,9868,9869,9870,9871,9872,9873,9874,
91170 9875,9876,9877,9878,9879,9880,9881,9882,9883,9884,9885,9886,9887,9888,9889,
91171 9890,9891,9892,9893,9894,9895,9896,9897,9898,9899,9900,9901,9902,9903,9904,
91172 9905,9906,9907,9908,9909,9910,9911,9912,9913,9914,9915,9916,9917,9918,9919,
91173 9920,9921,9922,9923,9924,9925,9926,9927,9928,9929,9930,9931,9932,9933,9934,
91174 9935,9936,9937,9938,9939,9940,9941,9942,9943,9944,9945,9946,9947,9948,9949,
91175 9950,9951,9952,9953,9954,9955,9956,9957,9958,9959,9960,9961,9962,9963,9964,
91176 9965,9966,9967,9968,9969,9970,9971,9972,9973,9974,9975,9976,9977,9978,9979,
91177 9980,9981,9982,9983,9984,9985,9986,9987,9988,9989,9990,9991,9992,9993,9994,
91178 9995,9996,9997,9998,9999,10000,10001,10002,10003,10004,10005,10006,10007,
91179 10008,10009,10010,10011,10012,10013,10014,10015,10016,10017,10018,10019,
91180 10020,10021,10022,10023,10024,10025,10026,10027,10028,10029,10030,10031,
91181 10032,10033,10034,10035,10036,10037,10038,10039,10040,10041,10042,10043,
91182 10044,10045,10046,10047,10048,10049,10050,10051,10052,10053,10054,10055,
91183 10056,10057,10058,10059,10060,10061,10062,10063,10064,10065,10066,10067,
91184 10068,10069,10070,10071,10072,10073,10074,10075,10076,10077,10078,10079,
91185 10080,10081,10082,10083,10084,10085,10086,10087,10088,10089,10090,10091,
91186 10092,10093,10094,10095,10096,10097,10098,10099,10100,10101,10102,10103,
91187 10104,10105,10106,10107,10108,10109,10110,10111,10112,10113,10114,10115,
91188 10116,10117,10118,10119,10120,10121,10122,10123,10124,10125,10126,10127,
91189 10128,10129,10130,10131,10132,10133,10134,10135,10136,10137,10138,10139,
91190 10140,10141,10142,10143,10144,10145,10146,10147,10148,10149,10150,10151,
91191 10152,10153,10154,10155,10156,10157,10158,10159,10160,10161,10162,10163,
91192 10164,10165,10166,10167,10168,10169,10170,10171,10172,10173,10174,10175,
91193 10176,10177,10178,10179,10180,10181,10182,10183,10184,10185,10186,10187,
91194 10188,10189,10190,10191,10192,10193,10194,10195,10196,10197,10198,10199,
91195 10200,10201,10202,10203,10204,10205,10206,10207,10208,10209,10210,10211,
91196 10212,10213,10214,10215,10216,10217,10218,10219,10220,10221,10222,10223,
91197 10224,10225,10226,10227,10228,10229,10230,10231,10232,10233,10234,10235,
91198 10236,10237,10238,10239,10240,10241,10242,10243,10244,10245,10246,10247,
91199 10248,10249,10250,10251,10252,10253,10254,10255,10256,10257,10258,10259,
91200 10260,10261,10262,10263,10264,10265,10266,10267,10268,10269,10270,10271,
91201 10272,10273,10274,10275,10276,10277,10278,10279,10280,10281,10282,10283,
91202 10284,10285,10286,10287,10288,10289,10290,10291,10292,10293,10294,10295,
91203 10296,10297,10298,10299,10300,10301,10302,10303,10304,10305,10306,10307,
91204 10308,10309,10310,10311,10312,10313,10314,10315,10316,10317,10318,10319,
91205 10320,10321,10322,10323,10324,10325,10326,10327,10328,10329,10330,10331,
91206 10332,10333,10334,10335,10336,10337,10338,10339,10340,10341,10342,10343,
91207 10344,10345,10346,10347,10348,10349,10350,10351,10352,10353,10354,10355,
91208 10356,10357,10358,10359,10360,10361,10362,10363,10364,10365,10366,10367,
91209 10368,10369,10370,10371,10372,10373,10374,10375,10376,10377,10378,10379,
91210 10380,10381,10382,10383,10384,10385,10386,10387,10388,10389,10390,10391,
91211 10392,10393,10394,10395,10396,10397,10398,10399,10400,10401,10402,10403,
91212 10404,10405,10406,10407,10408,10409,10410,10411,10412,10413,10414,10415,
91213 10416,10417,10418,10419,10420,10421,10422,10423,10424,10425,10426,10427,
91214 10428,10429,10430,10431,10432,10433,10434,10435,10436,10437,10438,10439,
91215 10440,10441,10442,10443,10444,10445,10446,10447,10448,10449,10450,10451,
91216 10452,10453,10454,10455,10456,10457,10458,10459,10460,10461,10462,10463,
91217 10464,10465,10466,10467,10468,10469,10470,10471,10472,10473,10474,10475,
91218 10476,10477,10478,10479,10480,10481,10482,10483,10484,10485,10486,10487,
91219 10488,10489,10490,10491,10492,10493,10494,10495,10496,10497,10498,10499,
91220 10500,10501,10502,10503,10504,10505,10506,10507,10508,10509,10510,10511,
91221 10512,10513,10514,10515,10516,10517,10518,10519,10520,10521,10522,10523,
91222 10524,10525,10526,10527,10528,10529,10530,10531,10532,10533,10534,10535,
91223 10536,10537,10538,10539,10540,10541,10542,10543,10544,10545,10546,10547,
91224 10548,10549,10550,10551,10552,10553,10554,10555,10556,10557,10558,10559,
91225 10560,10561,10562,10563,10564,10565,10566,10567,10568,10569,10570,10571,
91226 10572,10573,10574,10575,10576,10577,10578,10579,10580,10581,10582,10583,
91227 10584,10585,10586,10587,10588,10589,10590,10591,10592,10593,10594,10595,
91228 10596,10597,10598,10599,10600,10601,10602,10603,10604,10605,10606,10607,
91229 10608,10609,10610,10611,10612,10613,10614,10615,10616,10617,10618,10619,
91230 10620,10621,10622,10623,10624,10625,10626,10627,10628,10629,10630,10631,
91231 10632,10633,10634,10635,10636,10637,10638,10639,10640,10641,10642,10643,
91232 10644,10645,10646,10647,10648,10649,10650,10651,10652,10653,10654,10655,
91233 10656,10657,10658,10659,10660,10661,10662,10663,10664,10665,10666,10667,
91234 10668,10669,10670,10671,10672,10673,10674,10675,10676,10677,10678,10679,
91235 10680,10681,10682,10683,10684,10685,10686,10687,10688,10689,10690,10691,
91236 10692,10693,10694,10695,10696,10697,10698,10699,10700,10701,10702,10703,
91237 10704,10705,10706,10707,10708,10709,10710,10711,10712,10713,10714,10715,
91238 10716,10717,10718,10719,10720,10721,10722,10723,10724,10725,10726,10727,
91239 10728,10729,10730,10731,10732,10733,10734,10735,10736,10737,10738,10739,
91240 10740,10741,10742,10743,10744,10745,10746,10747,10748,10749,10750,10751,
91241 10752,10753,10754,10755,10756,10757,10758,10759,10760,10761,10762,10763,
91242 10764,10765,10766,10767,10768,10769,10770,10771,10772,10773,10774,10775,
91243 10776,10777,10778,10779,10780,10781,10782,10783,10784,10785,10786,10787,
91244 10788,10789,10790,10791,10792,10793,10794,10795,10796,10797,10798,10799,
91245 10800,10801,10802,10803,10804,10805,10806,10807,10808,10809,10810,10811,
91246 10812,10813,10814,10815,10816,10817,10818,10819,10820,10821,10822,10823,
91247 10824,10825,10826,10827,10828,10829,10830,10831,10832,10833,10834,10835,
91248 10836,10837,10838,10839,10840,10841,10842,10843,10844,10845,10846,10847,
91249 10848,10849,10850,10851,10852,10853,10854,10855,10856,10857,10858,10859,
91250 10860,10861,10862,10863,10864,10865,10866,10867,10868,10869,10870,10871,
91251 10872,10873,10874,10875,10876,10877,10878,10879,10880,10881,10882,10883,
91252 10884,10885,10886,10887,10888,10889,10890,10891,10892,10893,10894,10895,
91253 10896,10897,10898,10899,10900,10901,10902,10903,10904,10905,10906,10907,
91254 10908,10909,10910,10911,10912,10913,10914,10915,10916,10917,10918,10919,
91255 10920,10921,10922,10923,10924,10925,10926,10927,10928,10929,10930,10931,
91256 10932,10933,10934,10935,10936,10937,10938,10939,10940,10941,10942,10943,
91257 10944,10945,10946,10947,10948,10949,10950,10951,10952,10953,10954,10955,
91258 10956,10957,10958,10959,10960,10961,10962,10963,10964,10965,10966,10967,
91259 10968,10969,10970,10971,10972,10973,10974,10975,10976,10977,10978,10979,
91260 10980,10981,10982,10983,10984,10985,10986,10987,10988,10989,10990,10991,
91261 10992,10993,10994,10995,10996,10997,10998,10999,11000,11001,11002,11003,
91262 11004,11005,11006,11007,11008,11009,11010,11011,11012,11013,11014,11015,
91263 11016,11017,11018,11019,11020,11021,11022,11023,11024,11025,11026,11027,
91264 11028,11029,11030,11031,11032,11033,11034,11035,11036,11037,11038,11039,
91265 11040,11041,11042,11043,11044,11045,11046,11047,11048,11049,11050,11051,
91266 11052,11053,11054,11055,11056,11057,11058,11059,11060,11061,11062,11063,
91267 11064,11065,11066,11067,11068,11069,11070,11071,11072,11073,11074,11075,
91268 11076,11077,11078,11079,11080,11081,11082,11083,11084,11085,11086,11087,
91269 11088,11089,11090,11091,11092,11093,11094,11095,11096,11097,11098,11099,
91270 11100,11101,11102,11103,11104,11105,11106,11107,11108,11109,11110,11111,
91271 11112,11113,11114,11115,11116,11117,11118,11119,11120,11121,11122,11123,
91272 11124,11125,11126,11127,11128,11129,11130,11131,11132,11133,11134,11135,
91273 11136,11137,11138,11139,11140,11141,11142,11143,11144,11145,11146,11147,
91274 11148,11149,11150,11151,11152,11153,11154,11155,11156,11157,11158,11159,
91275 11160,11161,11162,11163,11164,11165,11166,11167,11168,11169,11170,11171,
91276 11172,11173,11174,11175,11176,11177,11178,11179,11180,11181,11182,11183,
91277 11184,11185,11186,11187,11188,11189,11190,11191,11192,11193,11194,11195,
91278 11196,11197,11198,11199,11200,11201,11202,11203,11204,11205,11206,11207,
91279 11208,11209,11210,11211,11212,11213,11214,11215,11216,11217,11218,11219,
91280 11220,11221,11222,11223,11224,11225,11226,11227,11228,11229,11230,11231,
91281 11232,11233,11234,11235,11236,11237,11238,11239,11240,11241,11242,11243,
91282 11244,11245,11246,11247,11248,11249,11250,11251,11252,11253,11254,11255,
91283 11256,11257,11258,11259,11260,11261,11262,11263,11264,11265,11266,11267,
91284 11268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,
91285 11280,11281,11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,
91286 11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,
91287 11304,11305,11306,11307,11308,11309,11310,11311,11264,11265,11266,11267,
91288 11268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,
91289 11280,11281,11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,
91290 11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,
91291 11304,11305,11306,11307,11308,11309,11310,11359,11360,11360,11362,11363,
91292 11364,570,574,11367,11367,11369,11369,11371,11371,11373,11374,11375,11376,
91293 11377,11378,11378,11380,11381,11381,11383,11384,11385,11386,11387,11388,
91294 11389,11390,11391,11392,11392,11394,11394,11396,11396,11398,11398,11400,
91295 11400,11402,11402,11404,11404,11406,11406,11408,11408,11410,11410,11412,
91296 11412,11414,11414,11416,11416,11418,11418,11420,11420,11422,11422,11424,
91297 11424,11426,11426,11428,11428,11430,11430,11432,11432,11434,11434,11436,
91298 11436,11438,11438,11440,11440,11442,11442,11444,11444,11446,11446,11448,
91299 11448,11450,11450,11452,11452,11454,11454,11456,11456,11458,11458,11460,
91300 11460,11462,11462,11464,11464,11466,11466,11468,11468,11470,11470,11472,
91301 11472,11474,11474,11476,11476,11478,11478,11480,11480,11482,11482,11484,
91302 11484,11486,11486,11488,11488,11490,11490,11492,11493,11494,11495,11496,
91303 11497,11498,11499,11499,11501,11501,11503,11504,11505,11506,11506,11508,
91304 11509,11510,11511,11512,11513,11514,11515,11516,11517,11518,11519,4256,
91305 4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,
91306 4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,
91307 4287,4288,4289,4290,4291,4292,4293,11558,4295,11560,11561,11562,11563,
91308 11564,4301,11566,11567,11568,11569,11570,11571,11572,11573,11574,11575,
91309 11576,11577,11578,11579,11580,11581,11582,11583,11584,11585,11586,11587,
91310 11588,11589,11590,11591,11592,11593,11594,11595,11596,11597,11598,11599,
91311 11600,11601,11602,11603,11604,11605,11606,11607,11608,11609,11610,11611,
91312 11612,11613,11614,11615,11616,11617,11618,11619,11620,11621,11622,11623,
91313 11624,11625,11626,11627,11628,11629,11630,11631,11632,11633,11634,11635,
91314 11636,11637,11638,11639,11640,11641,11642,11643,11644,11645,11646,11647,
91315 11648,11649,11650,11651,11652,11653,11654,11655,11656,11657,11658,11659,
91316 11660,11661,11662,11663,11664,11665,11666,11667,11668,11669,11670,11671,
91317 11672,11673,11674,11675,11676,11677,11678,11679,11680,11681,11682,11683,
91318 11684,11685,11686,11687,11688,11689,11690,11691,11692,11693,11694,11695,
91319 11696,11697,11698,11699,11700,11701,11702,11703,11704,11705,11706,11707,
91320 11708,11709,11710,11711,11712,11713,11714,11715,11716,11717,11718,11719,
91321 11720,11721,11722,11723,11724,11725,11726,11727,11728,11729,11730,11731,
91322 11732,11733,11734,11735,11736,11737,11738,11739,11740,11741,11742,11743,
91323 11744,11745,11746,11747,11748,11749,11750,11751,11752,11753,11754,11755,
91324 11756,11757,11758,11759,11760,11761,11762,11763,11764,11765,11766,11767,
91325 11768,11769,11770,11771,11772,11773,11774,11775,11776,11777,11778,11779,
91326 11780,11781,11782,11783,11784,11785,11786,11787,11788,11789,11790,11791,
91327 11792,11793,11794,11795,11796,11797,11798,11799,11800,11801,11802,11803,
91328 11804,11805,11806,11807,11808,11809,11810,11811,11812,11813,11814,11815,
91329 11816,11817,11818,11819,11820,11821,11822,11823,11824,11825,11826,11827,
91330 11828,11829,11830,11831,11832,11833,11834,11835,11836,11837,11838,11839,
91331 11840,11841,11842,11843,11844,11845,11846,11847,11848,11849,11850,11851,
91332 11852,11853,11854,11855,11856,11857,11858,11859,11860,11861,11862,11863,
91333 11864,11865,11866,11867,11868,11869,11870,11871,11872,11873,11874,11875,
91334 11876,11877,11878,11879,11880,11881,11882,11883,11884,11885,11886,11887,
91335 11888,11889,11890,11891,11892,11893,11894,11895,11896,11897,11898,11899,
91336 11900,11901,11902,11903,11904,11905,11906,11907,11908,11909,11910,11911,
91337 11912,11913,11914,11915,11916,11917,11918,11919,11920,11921,11922,11923,
91338 11924,11925,11926,11927,11928,11929,11930,11931,11932,11933,11934,11935,
91339 11936,11937,11938,11939,11940,11941,11942,11943,11944,11945,11946,11947,
91340 11948,11949,11950,11951,11952,11953,11954,11955,11956,11957,11958,11959,
91341 11960,11961,11962,11963,11964,11965,11966,11967,11968,11969,11970,11971,
91342 11972,11973,11974,11975,11976,11977,11978,11979,11980,11981,11982,11983,
91343 11984,11985,11986,11987,11988,11989,11990,11991,11992,11993,11994,11995,
91344 11996,11997,11998,11999,12000,12001,12002,12003,12004,12005,12006,12007,
91345 12008,12009,12010,12011,12012,12013,12014,12015,12016,12017,12018,12019,
91346 12020,12021,12022,12023,12024,12025,12026,12027,12028,12029,12030,12031,
91347 12032,12033,12034,12035,12036,12037,12038,12039,12040,12041,12042,12043,
91348 12044,12045,12046,12047,12048,12049,12050,12051,12052,12053,12054,12055,
91349 12056,12057,12058,12059,12060,12061,12062,12063,12064,12065,12066,12067,
91350 12068,12069,12070,12071,12072,12073,12074,12075,12076,12077,12078,12079,
91351 12080,12081,12082,12083,12084,12085,12086,12087,12088,12089,12090,12091,
91352 12092,12093,12094,12095,12096,12097,12098,12099,12100,12101,12102,12103,
91353 12104,12105,12106,12107,12108,12109,12110,12111,12112,12113,12114,12115,
91354 12116,12117,12118,12119,12120,12121,12122,12123,12124,12125,12126,12127,
91355 12128,12129,12130,12131,12132,12133,12134,12135,12136,12137,12138,12139,
91356 12140,12141,12142,12143,12144,12145,12146,12147,12148,12149,12150,12151,
91357 12152,12153,12154,12155,12156,12157,12158,12159,12160,12161,12162,12163,
91358 12164,12165,12166,12167,12168,12169,12170,12171,12172,12173,12174,12175,
91359 12176,12177,12178,12179,12180,12181,12182,12183,12184,12185,12186,12187,
91360 12188,12189,12190,12191,12192,12193,12194,12195,12196,12197,12198,12199,
91361 12200,12201,12202,12203,12204,12205,12206,12207,12208,12209,12210,12211,
91362 12212,12213,12214,12215,12216,12217,12218,12219,12220,12221,12222,12223,
91363 12224,12225,12226,12227,12228,12229,12230,12231,12232,12233,12234,12235,
91364 12236,12237,12238,12239,12240,12241,12242,12243,12244,12245,12246,12247,
91365 12248,12249,12250,12251,12252,12253,12254,12255,12256,12257,12258,12259,
91366 12260,12261,12262,12263,12264,12265,12266,12267,12268,12269,12270,12271,
91367 12272,12273,12274,12275,12276,12277,12278,12279,12280,12281,12282,12283,
91368 12284,12285,12286,12287,12288,12289,12290,12291,12292,12293,12294,12295,
91369 12296,12297,12298,12299,12300,12301,12302,12303,12304,12305,12306,12307,
91370 12308,12309,12310,12311,12312,12313,12314,12315,12316,12317,12318,12319,
91371 12320,12321,12322,12323,12324,12325,12326,12327,12328,12329,12330,12331,
91372 12332,12333,12334,12335,12336,12337,12338,12339,12340,12341,12342,12343,
91373 12344,12345,12346,12347,12348,12349,12350,12351,12352,12353,12354,12355,
91374 12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,
91375 12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,
91376 12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,
91377 12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,
91378 12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,
91379 12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,
91380 12428,12429,12430,12431,12432,12433,12434,12435,12436,12437,12438,12439,
91381 12440,12441,12442,12443,12444,12445,12446,12447,12448,12449,12450,12451,
91382 12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,
91383 12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,
91384 12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,
91385 12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,
91386 12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,
91387 12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,
91388 12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,12535,
91389 12536,12537,12538,12539,12540,12541,12542,12543,12544,12545,12546,12547,
91390 12548,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,
91391 12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,
91392 12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,
91393 12584,12585,12586,12587,12588,12589,12590,12591,12592,12593,12594,12595,
91394 12596,12597,12598,12599,12600,12601,12602,12603,12604,12605,12606,12607,
91395 12608,12609,12610,12611,12612,12613,12614,12615,12616,12617,12618,12619,
91396 12620,12621,12622,12623,12624,12625,12626,12627,12628,12629,12630,12631,
91397 12632,12633,12634,12635,12636,12637,12638,12639,12640,12641,12642,12643,
91398 12644,12645,12646,12647,12648,12649,12650,12651,12652,12653,12654,12655,
91399 12656,12657,12658,12659,12660,12661,12662,12663,12664,12665,12666,12667,
91400 12668,12669,12670,12671,12672,12673,12674,12675,12676,12677,12678,12679,
91401 12680,12681,12682,12683,12684,12685,12686,12687,12688,12689,12690,12691,
91402 12692,12693,12694,12695,12696,12697,12698,12699,12700,12701,12702,12703,
91403 12704,12705,12706,12707,12708,12709,12710,12711,12712,12713,12714,12715,
91404 12716,12717,12718,12719,12720,12721,12722,12723,12724,12725,12726,12727,
91405 12728,12729,12730,12731,12732,12733,12734,12735,12736,12737,12738,12739,
91406 12740,12741,12742,12743,12744,12745,12746,12747,12748,12749,12750,12751,
91407 12752,12753,12754,12755,12756,12757,12758,12759,12760,12761,12762,12763,
91408 12764,12765,12766,12767,12768,12769,12770,12771,12772,12773,12774,12775,
91409 12776,12777,12778,12779,12780,12781,12782,12783,12784,12785,12786,12787,
91410 12788,12789,12790,12791,12792,12793,12794,12795,12796,12797,12798,12799,
91411 12800,12801,12802,12803,12804,12805,12806,12807,12808,12809,12810,12811,
91412 12812,12813,12814,12815,12816,12817,12818,12819,12820,12821,12822,12823,
91413 12824,12825,12826,12827,12828,12829,12830,12831,12832,12833,12834,12835,
91414 12836,12837,12838,12839,12840,12841,12842,12843,12844,12845,12846,12847,
91415 12848,12849,12850,12851,12852,12853,12854,12855,12856,12857,12858,12859,
91416 12860,12861,12862,12863,12864,12865,12866,12867,12868,12869,12870,12871,
91417 12872,12873,12874,12875,12876,12877,12878,12879,12880,12881,12882,12883,
91418 12884,12885,12886,12887,12888,12889,12890,12891,12892,12893,12894,12895,
91419 12896,12897,12898,12899,12900,12901,12902,12903,12904,12905,12906,12907,
91420 12908,12909,12910,12911,12912,12913,12914,12915,12916,12917,12918,12919,
91421 12920,12921,12922,12923,12924,12925,12926,12927,12928,12929,12930,12931,
91422 12932,12933,12934,12935,12936,12937,12938,12939,12940,12941,12942,12943,
91423 12944,12945,12946,12947,12948,12949,12950,12951,12952,12953,12954,12955,
91424 12956,12957,12958,12959,12960,12961,12962,12963,12964,12965,12966,12967,
91425 12968,12969,12970,12971,12972,12973,12974,12975,12976,12977,12978,12979,
91426 12980,12981,12982,12983,12984,12985,12986,12987,12988,12989,12990,12991,
91427 12992,12993,12994,12995,12996,12997,12998,12999,13000,13001,13002,13003,
91428 13004,13005,13006,13007,13008,13009,13010,13011,13012,13013,13014,13015,
91429 13016,13017,13018,13019,13020,13021,13022,13023,13024,13025,13026,13027,
91430 13028,13029,13030,13031,13032,13033,13034,13035,13036,13037,13038,13039,
91431 13040,13041,13042,13043,13044,13045,13046,13047,13048,13049,13050,13051,
91432 13052,13053,13054,13055,13056,13057,13058,13059,13060,13061,13062,13063,
91433 13064,13065,13066,13067,13068,13069,13070,13071,13072,13073,13074,13075,
91434 13076,13077,13078,13079,13080,13081,13082,13083,13084,13085,13086,13087,
91435 13088,13089,13090,13091,13092,13093,13094,13095,13096,13097,13098,13099,
91436 13100,13101,13102,13103,13104,13105,13106,13107,13108,13109,13110,13111,
91437 13112,13113,13114,13115,13116,13117,13118,13119,13120,13121,13122,13123,
91438 13124,13125,13126,13127,13128,13129,13130,13131,13132,13133,13134,13135,
91439 13136,13137,13138,13139,13140,13141,13142,13143,13144,13145,13146,13147,
91440 13148,13149,13150,13151,13152,13153,13154,13155,13156,13157,13158,13159,
91441 13160,13161,13162,13163,13164,13165,13166,13167,13168,13169,13170,13171,
91442 13172,13173,13174,13175,13176,13177,13178,13179,13180,13181,13182,13183,
91443 13184,13185,13186,13187,13188,13189,13190,13191,13192,13193,13194,13195,
91444 13196,13197,13198,13199,13200,13201,13202,13203,13204,13205,13206,13207,
91445 13208,13209,13210,13211,13212,13213,13214,13215,13216,13217,13218,13219,
91446 13220,13221,13222,13223,13224,13225,13226,13227,13228,13229,13230,13231,
91447 13232,13233,13234,13235,13236,13237,13238,13239,13240,13241,13242,13243,
91448 13244,13245,13246,13247,13248,13249,13250,13251,13252,13253,13254,13255,
91449 13256,13257,13258,13259,13260,13261,13262,13263,13264,13265,13266,13267,
91450 13268,13269,13270,13271,13272,13273,13274,13275,13276,13277,13278,13279,
91451 13280,13281,13282,13283,13284,13285,13286,13287,13288,13289,13290,13291,
91452 13292,13293,13294,13295,13296,13297,13298,13299,13300,13301,13302,13303,
91453 13304,13305,13306,13307,13308,13309,13310,13311,13312,13313,13314,13315,
91454 13316,13317,13318,13319,13320,13321,13322,13323,13324,13325,13326,13327,
91455 13328,13329,13330,13331,13332,13333,13334,13335,13336,13337,13338,13339,
91456 13340,13341,13342,13343,13344,13345,13346,13347,13348,13349,13350,13351,
91457 13352,13353,13354,13355,13356,13357,13358,13359,13360,13361,13362,13363,
91458 13364,13365,13366,13367,13368,13369,13370,13371,13372,13373,13374,13375,
91459 13376,13377,13378,13379,13380,13381,13382,13383,13384,13385,13386,13387,
91460 13388,13389,13390,13391,13392,13393,13394,13395,13396,13397,13398,13399,
91461 13400,13401,13402,13403,13404,13405,13406,13407,13408,13409,13410,13411,
91462 13412,13413,13414,13415,13416,13417,13418,13419,13420,13421,13422,13423,
91463 13424,13425,13426,13427,13428,13429,13430,13431,13432,13433,13434,13435,
91464 13436,13437,13438,13439,13440,13441,13442,13443,13444,13445,13446,13447,
91465 13448,13449,13450,13451,13452,13453,13454,13455,13456,13457,13458,13459,
91466 13460,13461,13462,13463,13464,13465,13466,13467,13468,13469,13470,13471,
91467 13472,13473,13474,13475,13476,13477,13478,13479,13480,13481,13482,13483,
91468 13484,13485,13486,13487,13488,13489,13490,13491,13492,13493,13494,13495,
91469 13496,13497,13498,13499,13500,13501,13502,13503,13504,13505,13506,13507,
91470 13508,13509,13510,13511,13512,13513,13514,13515,13516,13517,13518,13519,
91471 13520,13521,13522,13523,13524,13525,13526,13527,13528,13529,13530,13531,
91472 13532,13533,13534,13535,13536,13537,13538,13539,13540,13541,13542,13543,
91473 13544,13545,13546,13547,13548,13549,13550,13551,13552,13553,13554,13555,
91474 13556,13557,13558,13559,13560,13561,13562,13563,13564,13565,13566,13567,
91475 13568,13569,13570,13571,13572,13573,13574,13575,13576,13577,13578,13579,
91476 13580,13581,13582,13583,13584,13585,13586,13587,13588,13589,13590,13591,
91477 13592,13593,13594,13595,13596,13597,13598,13599,13600,13601,13602,13603,
91478 13604,13605,13606,13607,13608,13609,13610,13611,13612,13613,13614,13615,
91479 13616,13617,13618,13619,13620,13621,13622,13623,13624,13625,13626,13627,
91480 13628,13629,13630,13631,13632,13633,13634,13635,13636,13637,13638,13639,
91481 13640,13641,13642,13643,13644,13645,13646,13647,13648,13649,13650,13651,
91482 13652,13653,13654,13655,13656,13657,13658,13659,13660,13661,13662,13663,
91483 13664,13665,13666,13667,13668,13669,13670,13671,13672,13673,13674,13675,
91484 13676,13677,13678,13679,13680,13681,13682,13683,13684,13685,13686,13687,
91485 13688,13689,13690,13691,13692,13693,13694,13695,13696,13697,13698,13699,
91486 13700,13701,13702,13703,13704,13705,13706,13707,13708,13709,13710,13711,
91487 13712,13713,13714,13715,13716,13717,13718,13719,13720,13721,13722,13723,
91488 13724,13725,13726,13727,13728,13729,13730,13731,13732,13733,13734,13735,
91489 13736,13737,13738,13739,13740,13741,13742,13743,13744,13745,13746,13747,
91490 13748,13749,13750,13751,13752,13753,13754,13755,13756,13757,13758,13759,
91491 13760,13761,13762,13763,13764,13765,13766,13767,13768,13769,13770,13771,
91492 13772,13773,13774,13775,13776,13777,13778,13779,13780,13781,13782,13783,
91493 13784,13785,13786,13787,13788,13789,13790,13791,13792,13793,13794,13795,
91494 13796,13797,13798,13799,13800,13801,13802,13803,13804,13805,13806,13807,
91495 13808,13809,13810,13811,13812,13813,13814,13815,13816,13817,13818,13819,
91496 13820,13821,13822,13823,13824,13825,13826,13827,13828,13829,13830,13831,
91497 13832,13833,13834,13835,13836,13837,13838,13839,13840,13841,13842,13843,
91498 13844,13845,13846,13847,13848,13849,13850,13851,13852,13853,13854,13855,
91499 13856,13857,13858,13859,13860,13861,13862,13863,13864,13865,13866,13867,
91500 13868,13869,13870,13871,13872,13873,13874,13875,13876,13877,13878,13879,
91501 13880,13881,13882,13883,13884,13885,13886,13887,13888,13889,13890,13891,
91502 13892,13893,13894,13895,13896,13897,13898,13899,13900,13901,13902,13903,
91503 13904,13905,13906,13907,13908,13909,13910,13911,13912,13913,13914,13915,
91504 13916,13917,13918,13919,13920,13921,13922,13923,13924,13925,13926,13927,
91505 13928,13929,13930,13931,13932,13933,13934,13935,13936,13937,13938,13939,
91506 13940,13941,13942,13943,13944,13945,13946,13947,13948,13949,13950,13951,
91507 13952,13953,13954,13955,13956,13957,13958,13959,13960,13961,13962,13963,
91508 13964,13965,13966,13967,13968,13969,13970,13971,13972,13973,13974,13975,
91509 13976,13977,13978,13979,13980,13981,13982,13983,13984,13985,13986,13987,
91510 13988,13989,13990,13991,13992,13993,13994,13995,13996,13997,13998,13999,
91511 14000,14001,14002,14003,14004,14005,14006,14007,14008,14009,14010,14011,
91512 14012,14013,14014,14015,14016,14017,14018,14019,14020,14021,14022,14023,
91513 14024,14025,14026,14027,14028,14029,14030,14031,14032,14033,14034,14035,
91514 14036,14037,14038,14039,14040,14041,14042,14043,14044,14045,14046,14047,
91515 14048,14049,14050,14051,14052,14053,14054,14055,14056,14057,14058,14059,
91516 14060,14061,14062,14063,14064,14065,14066,14067,14068,14069,14070,14071,
91517 14072,14073,14074,14075,14076,14077,14078,14079,14080,14081,14082,14083,
91518 14084,14085,14086,14087,14088,14089,14090,14091,14092,14093,14094,14095,
91519 14096,14097,14098,14099,14100,14101,14102,14103,14104,14105,14106,14107,
91520 14108,14109,14110,14111,14112,14113,14114,14115,14116,14117,14118,14119,
91521 14120,14121,14122,14123,14124,14125,14126,14127,14128,14129,14130,14131,
91522 14132,14133,14134,14135,14136,14137,14138,14139,14140,14141,14142,14143,
91523 14144,14145,14146,14147,14148,14149,14150,14151,14152,14153,14154,14155,
91524 14156,14157,14158,14159,14160,14161,14162,14163,14164,14165,14166,14167,
91525 14168,14169,14170,14171,14172,14173,14174,14175,14176,14177,14178,14179,
91526 14180,14181,14182,14183,14184,14185,14186,14187,14188,14189,14190,14191,
91527 14192,14193,14194,14195,14196,14197,14198,14199,14200,14201,14202,14203,
91528 14204,14205,14206,14207,14208,14209,14210,14211,14212,14213,14214,14215,
91529 14216,14217,14218,14219,14220,14221,14222,14223,14224,14225,14226,14227,
91530 14228,14229,14230,14231,14232,14233,14234,14235,14236,14237,14238,14239,
91531 14240,14241,14242,14243,14244,14245,14246,14247,14248,14249,14250,14251,
91532 14252,14253,14254,14255,14256,14257,14258,14259,14260,14261,14262,14263,
91533 14264,14265,14266,14267,14268,14269,14270,14271,14272,14273,14274,14275,
91534 14276,14277,14278,14279,14280,14281,14282,14283,14284,14285,14286,14287,
91535 14288,14289,14290,14291,14292,14293,14294,14295,14296,14297,14298,14299,
91536 14300,14301,14302,14303,14304,14305,14306,14307,14308,14309,14310,14311,
91537 14312,14313,14314,14315,14316,14317,14318,14319,14320,14321,14322,14323,
91538 14324,14325,14326,14327,14328,14329,14330,14331,14332,14333,14334,14335,
91539 14336,14337,14338,14339,14340,14341,14342,14343,14344,14345,14346,14347,
91540 14348,14349,14350,14351,14352,14353,14354,14355,14356,14357,14358,14359,
91541 14360,14361,14362,14363,14364,14365,14366,14367,14368,14369,14370,14371,
91542 14372,14373,14374,14375,14376,14377,14378,14379,14380,14381,14382,14383,
91543 14384,14385,14386,14387,14388,14389,14390,14391,14392,14393,14394,14395,
91544 14396,14397,14398,14399,14400,14401,14402,14403,14404,14405,14406,14407,
91545 14408,14409,14410,14411,14412,14413,14414,14415,14416,14417,14418,14419,
91546 14420,14421,14422,14423,14424,14425,14426,14427,14428,14429,14430,14431,
91547 14432,14433,14434,14435,14436,14437,14438,14439,14440,14441,14442,14443,
91548 14444,14445,14446,14447,14448,14449,14450,14451,14452,14453,14454,14455,
91549 14456,14457,14458,14459,14460,14461,14462,14463,14464,14465,14466,14467,
91550 14468,14469,14470,14471,14472,14473,14474,14475,14476,14477,14478,14479,
91551 14480,14481,14482,14483,14484,14485,14486,14487,14488,14489,14490,14491,
91552 14492,14493,14494,14495,14496,14497,14498,14499,14500,14501,14502,14503,
91553 14504,14505,14506,14507,14508,14509,14510,14511,14512,14513,14514,14515,
91554 14516,14517,14518,14519,14520,14521,14522,14523,14524,14525,14526,14527,
91555 14528,14529,14530,14531,14532,14533,14534,14535,14536,14537,14538,14539,
91556 14540,14541,14542,14543,14544,14545,14546,14547,14548,14549,14550,14551,
91557 14552,14553,14554,14555,14556,14557,14558,14559,14560,14561,14562,14563,
91558 14564,14565,14566,14567,14568,14569,14570,14571,14572,14573,14574,14575,
91559 14576,14577,14578,14579,14580,14581,14582,14583,14584,14585,14586,14587,
91560 14588,14589,14590,14591,14592,14593,14594,14595,14596,14597,14598,14599,
91561 14600,14601,14602,14603,14604,14605,14606,14607,14608,14609,14610,14611,
91562 14612,14613,14614,14615,14616,14617,14618,14619,14620,14621,14622,14623,
91563 14624,14625,14626,14627,14628,14629,14630,14631,14632,14633,14634,14635,
91564 14636,14637,14638,14639,14640,14641,14642,14643,14644,14645,14646,14647,
91565 14648,14649,14650,14651,14652,14653,14654,14655,14656,14657,14658,14659,
91566 14660,14661,14662,14663,14664,14665,14666,14667,14668,14669,14670,14671,
91567 14672,14673,14674,14675,14676,14677,14678,14679,14680,14681,14682,14683,
91568 14684,14685,14686,14687,14688,14689,14690,14691,14692,14693,14694,14695,
91569 14696,14697,14698,14699,14700,14701,14702,14703,14704,14705,14706,14707,
91570 14708,14709,14710,14711,14712,14713,14714,14715,14716,14717,14718,14719,
91571 14720,14721,14722,14723,14724,14725,14726,14727,14728,14729,14730,14731,
91572 14732,14733,14734,14735,14736,14737,14738,14739,14740,14741,14742,14743,
91573 14744,14745,14746,14747,14748,14749,14750,14751,14752,14753,14754,14755,
91574 14756,14757,14758,14759,14760,14761,14762,14763,14764,14765,14766,14767,
91575 14768,14769,14770,14771,14772,14773,14774,14775,14776,14777,14778,14779,
91576 14780,14781,14782,14783,14784,14785,14786,14787,14788,14789,14790,14791,
91577 14792,14793,14794,14795,14796,14797,14798,14799,14800,14801,14802,14803,
91578 14804,14805,14806,14807,14808,14809,14810,14811,14812,14813,14814,14815,
91579 14816,14817,14818,14819,14820,14821,14822,14823,14824,14825,14826,14827,
91580 14828,14829,14830,14831,14832,14833,14834,14835,14836,14837,14838,14839,
91581 14840,14841,14842,14843,14844,14845,14846,14847,14848,14849,14850,14851,
91582 14852,14853,14854,14855,14856,14857,14858,14859,14860,14861,14862,14863,
91583 14864,14865,14866,14867,14868,14869,14870,14871,14872,14873,14874,14875,
91584 14876,14877,14878,14879,14880,14881,14882,14883,14884,14885,14886,14887,
91585 14888,14889,14890,14891,14892,14893,14894,14895,14896,14897,14898,14899,
91586 14900,14901,14902,14903,14904,14905,14906,14907,14908,14909,14910,14911,
91587 14912,14913,14914,14915,14916,14917,14918,14919,14920,14921,14922,14923,
91588 14924,14925,14926,14927,14928,14929,14930,14931,14932,14933,14934,14935,
91589 14936,14937,14938,14939,14940,14941,14942,14943,14944,14945,14946,14947,
91590 14948,14949,14950,14951,14952,14953,14954,14955,14956,14957,14958,14959,
91591 14960,14961,14962,14963,14964,14965,14966,14967,14968,14969,14970,14971,
91592 14972,14973,14974,14975,14976,14977,14978,14979,14980,14981,14982,14983,
91593 14984,14985,14986,14987,14988,14989,14990,14991,14992,14993,14994,14995,
91594 14996,14997,14998,14999,15000,15001,15002,15003,15004,15005,15006,15007,
91595 15008,15009,15010,15011,15012,15013,15014,15015,15016,15017,15018,15019,
91596 15020,15021,15022,15023,15024,15025,15026,15027,15028,15029,15030,15031,
91597 15032,15033,15034,15035,15036,15037,15038,15039,15040,15041,15042,15043,
91598 15044,15045,15046,15047,15048,15049,15050,15051,15052,15053,15054,15055,
91599 15056,15057,15058,15059,15060,15061,15062,15063,15064,15065,15066,15067,
91600 15068,15069,15070,15071,15072,15073,15074,15075,15076,15077,15078,15079,
91601 15080,15081,15082,15083,15084,15085,15086,15087,15088,15089,15090,15091,
91602 15092,15093,15094,15095,15096,15097,15098,15099,15100,15101,15102,15103,
91603 15104,15105,15106,15107,15108,15109,15110,15111,15112,15113,15114,15115,
91604 15116,15117,15118,15119,15120,15121,15122,15123,15124,15125,15126,15127,
91605 15128,15129,15130,15131,15132,15133,15134,15135,15136,15137,15138,15139,
91606 15140,15141,15142,15143,15144,15145,15146,15147,15148,15149,15150,15151,
91607 15152,15153,15154,15155,15156,15157,15158,15159,15160,15161,15162,15163,
91608 15164,15165,15166,15167,15168,15169,15170,15171,15172,15173,15174,15175,
91609 15176,15177,15178,15179,15180,15181,15182,15183,15184,15185,15186,15187,
91610 15188,15189,15190,15191,15192,15193,15194,15195,15196,15197,15198,15199,
91611 15200,15201,15202,15203,15204,15205,15206,15207,15208,15209,15210,15211,
91612 15212,15213,15214,15215,15216,15217,15218,15219,15220,15221,15222,15223,
91613 15224,15225,15226,15227,15228,15229,15230,15231,15232,15233,15234,15235,
91614 15236,15237,15238,15239,15240,15241,15242,15243,15244,15245,15246,15247,
91615 15248,15249,15250,15251,15252,15253,15254,15255,15256,15257,15258,15259,
91616 15260,15261,15262,15263,15264,15265,15266,15267,15268,15269,15270,15271,
91617 15272,15273,15274,15275,15276,15277,15278,15279,15280,15281,15282,15283,
91618 15284,15285,15286,15287,15288,15289,15290,15291,15292,15293,15294,15295,
91619 15296,15297,15298,15299,15300,15301,15302,15303,15304,15305,15306,15307,
91620 15308,15309,15310,15311,15312,15313,15314,15315,15316,15317,15318,15319,
91621 15320,15321,15322,15323,15324,15325,15326,15327,15328,15329,15330,15331,
91622 15332,15333,15334,15335,15336,15337,15338,15339,15340,15341,15342,15343,
91623 15344,15345,15346,15347,15348,15349,15350,15351,15352,15353,15354,15355,
91624 15356,15357,15358,15359,15360,15361,15362,15363,15364,15365,15366,15367,
91625 15368,15369,15370,15371,15372,15373,15374,15375,15376,15377,15378,15379,
91626 15380,15381,15382,15383,15384,15385,15386,15387,15388,15389,15390,15391,
91627 15392,15393,15394,15395,15396,15397,15398,15399,15400,15401,15402,15403,
91628 15404,15405,15406,15407,15408,15409,15410,15411,15412,15413,15414,15415,
91629 15416,15417,15418,15419,15420,15421,15422,15423,15424,15425,15426,15427,
91630 15428,15429,15430,15431,15432,15433,15434,15435,15436,15437,15438,15439,
91631 15440,15441,15442,15443,15444,15445,15446,15447,15448,15449,15450,15451,
91632 15452,15453,15454,15455,15456,15457,15458,15459,15460,15461,15462,15463,
91633 15464,15465,15466,15467,15468,15469,15470,15471,15472,15473,15474,15475,
91634 15476,15477,15478,15479,15480,15481,15482,15483,15484,15485,15486,15487,
91635 15488,15489,15490,15491,15492,15493,15494,15495,15496,15497,15498,15499,
91636 15500,15501,15502,15503,15504,15505,15506,15507,15508,15509,15510,15511,
91637 15512,15513,15514,15515,15516,15517,15518,15519,15520,15521,15522,15523,
91638 15524,15525,15526,15527,15528,15529,15530,15531,15532,15533,15534,15535,
91639 15536,15537,15538,15539,15540,15541,15542,15543,15544,15545,15546,15547,
91640 15548,15549,15550,15551,15552,15553,15554,15555,15556,15557,15558,15559,
91641 15560,15561,15562,15563,15564,15565,15566,15567,15568,15569,15570,15571,
91642 15572,15573,15574,15575,15576,15577,15578,15579,15580,15581,15582,15583,
91643 15584,15585,15586,15587,15588,15589,15590,15591,15592,15593,15594,15595,
91644 15596,15597,15598,15599,15600,15601,15602,15603,15604,15605,15606,15607,
91645 15608,15609,15610,15611,15612,15613,15614,15615,15616,15617,15618,15619,
91646 15620,15621,15622,15623,15624,15625,15626,15627,15628,15629,15630,15631,
91647 15632,15633,15634,15635,15636,15637,15638,15639,15640,15641,15642,15643,
91648 15644,15645,15646,15647,15648,15649,15650,15651,15652,15653,15654,15655,
91649 15656,15657,15658,15659,15660,15661,15662,15663,15664,15665,15666,15667,
91650 15668,15669,15670,15671,15672,15673,15674,15675,15676,15677,15678,15679,
91651 15680,15681,15682,15683,15684,15685,15686,15687,15688,15689,15690,15691,
91652 15692,15693,15694,15695,15696,15697,15698,15699,15700,15701,15702,15703,
91653 15704,15705,15706,15707,15708,15709,15710,15711,15712,15713,15714,15715,
91654 15716,15717,15718,15719,15720,15721,15722,15723,15724,15725,15726,15727,
91655 15728,15729,15730,15731,15732,15733,15734,15735,15736,15737,15738,15739,
91656 15740,15741,15742,15743,15744,15745,15746,15747,15748,15749,15750,15751,
91657 15752,15753,15754,15755,15756,15757,15758,15759,15760,15761,15762,15763,
91658 15764,15765,15766,15767,15768,15769,15770,15771,15772,15773,15774,15775,
91659 15776,15777,15778,15779,15780,15781,15782,15783,15784,15785,15786,15787,
91660 15788,15789,15790,15791,15792,15793,15794,15795,15796,15797,15798,15799,
91661 15800,15801,15802,15803,15804,15805,15806,15807,15808,15809,15810,15811,
91662 15812,15813,15814,15815,15816,15817,15818,15819,15820,15821,15822,15823,
91663 15824,15825,15826,15827,15828,15829,15830,15831,15832,15833,15834,15835,
91664 15836,15837,15838,15839,15840,15841,15842,15843,15844,15845,15846,15847,
91665 15848,15849,15850,15851,15852,15853,15854,15855,15856,15857,15858,15859,
91666 15860,15861,15862,15863,15864,15865,15866,15867,15868,15869,15870,15871,
91667 15872,15873,15874,15875,15876,15877,15878,15879,15880,15881,15882,15883,
91668 15884,15885,15886,15887,15888,15889,15890,15891,15892,15893,15894,15895,
91669 15896,15897,15898,15899,15900,15901,15902,15903,15904,15905,15906,15907,
91670 15908,15909,15910,15911,15912,15913,15914,15915,15916,15917,15918,15919,
91671 15920,15921,15922,15923,15924,15925,15926,15927,15928,15929,15930,15931,
91672 15932,15933,15934,15935,15936,15937,15938,15939,15940,15941,15942,15943,
91673 15944,15945,15946,15947,15948,15949,15950,15951,15952,15953,15954,15955,
91674 15956,15957,15958,15959,15960,15961,15962,15963,15964,15965,15966,15967,
91675 15968,15969,15970,15971,15972,15973,15974,15975,15976,15977,15978,15979,
91676 15980,15981,15982,15983,15984,15985,15986,15987,15988,15989,15990,15991,
91677 15992,15993,15994,15995,15996,15997,15998,15999,16000,16001,16002,16003,
91678 16004,16005,16006,16007,16008,16009,16010,16011,16012,16013,16014,16015,
91679 16016,16017,16018,16019,16020,16021,16022,16023,16024,16025,16026,16027,
91680 16028,16029,16030,16031,16032,16033,16034,16035,16036,16037,16038,16039,
91681 16040,16041,16042,16043,16044,16045,16046,16047,16048,16049,16050,16051,
91682 16052,16053,16054,16055,16056,16057,16058,16059,16060,16061,16062,16063,
91683 16064,16065,16066,16067,16068,16069,16070,16071,16072,16073,16074,16075,
91684 16076,16077,16078,16079,16080,16081,16082,16083,16084,16085,16086,16087,
91685 16088,16089,16090,16091,16092,16093,16094,16095,16096,16097,16098,16099,
91686 16100,16101,16102,16103,16104,16105,16106,16107,16108,16109,16110,16111,
91687 16112,16113,16114,16115,16116,16117,16118,16119,16120,16121,16122,16123,
91688 16124,16125,16126,16127,16128,16129,16130,16131,16132,16133,16134,16135,
91689 16136,16137,16138,16139,16140,16141,16142,16143,16144,16145,16146,16147,
91690 16148,16149,16150,16151,16152,16153,16154,16155,16156,16157,16158,16159,
91691 16160,16161,16162,16163,16164,16165,16166,16167,16168,16169,16170,16171,
91692 16172,16173,16174,16175,16176,16177,16178,16179,16180,16181,16182,16183,
91693 16184,16185,16186,16187,16188,16189,16190,16191,16192,16193,16194,16195,
91694 16196,16197,16198,16199,16200,16201,16202,16203,16204,16205,16206,16207,
91695 16208,16209,16210,16211,16212,16213,16214,16215,16216,16217,16218,16219,
91696 16220,16221,16222,16223,16224,16225,16226,16227,16228,16229,16230,16231,
91697 16232,16233,16234,16235,16236,16237,16238,16239,16240,16241,16242,16243,
91698 16244,16245,16246,16247,16248,16249,16250,16251,16252,16253,16254,16255,
91699 16256,16257,16258,16259,16260,16261,16262,16263,16264,16265,16266,16267,
91700 16268,16269,16270,16271,16272,16273,16274,16275,16276,16277,16278,16279,
91701 16280,16281,16282,16283,16284,16285,16286,16287,16288,16289,16290,16291,
91702 16292,16293,16294,16295,16296,16297,16298,16299,16300,16301,16302,16303,
91703 16304,16305,16306,16307,16308,16309,16310,16311,16312,16313,16314,16315,
91704 16316,16317,16318,16319,16320,16321,16322,16323,16324,16325,16326,16327,
91705 16328,16329,16330,16331,16332,16333,16334,16335,16336,16337,16338,16339,
91706 16340,16341,16342,16343,16344,16345,16346,16347,16348,16349,16350,16351,
91707 16352,16353,16354,16355,16356,16357,16358,16359,16360,16361,16362,16363,
91708 16364,16365,16366,16367,16368,16369,16370,16371,16372,16373,16374,16375,
91709 16376,16377,16378,16379,16380,16381,16382,16383,16384,16385,16386,16387,
91710 16388,16389,16390,16391,16392,16393,16394,16395,16396,16397,16398,16399,
91711 16400,16401,16402,16403,16404,16405,16406,16407,16408,16409,16410,16411,
91712 16412,16413,16414,16415,16416,16417,16418,16419,16420,16421,16422,16423,
91713 16424,16425,16426,16427,16428,16429,16430,16431,16432,16433,16434,16435,
91714 16436,16437,16438,16439,16440,16441,16442,16443,16444,16445,16446,16447,
91715 16448,16449,16450,16451,16452,16453,16454,16455,16456,16457,16458,16459,
91716 16460,16461,16462,16463,16464,16465,16466,16467,16468,16469,16470,16471,
91717 16472,16473,16474,16475,16476,16477,16478,16479,16480,16481,16482,16483,
91718 16484,16485,16486,16487,16488,16489,16490,16491,16492,16493,16494,16495,
91719 16496,16497,16498,16499,16500,16501,16502,16503,16504,16505,16506,16507,
91720 16508,16509,16510,16511,16512,16513,16514,16515,16516,16517,16518,16519,
91721 16520,16521,16522,16523,16524,16525,16526,16527,16528,16529,16530,16531,
91722 16532,16533,16534,16535,16536,16537,16538,16539,16540,16541,16542,16543,
91723 16544,16545,16546,16547,16548,16549,16550,16551,16552,16553,16554,16555,
91724 16556,16557,16558,16559,16560,16561,16562,16563,16564,16565,16566,16567,
91725 16568,16569,16570,16571,16572,16573,16574,16575,16576,16577,16578,16579,
91726 16580,16581,16582,16583,16584,16585,16586,16587,16588,16589,16590,16591,
91727 16592,16593,16594,16595,16596,16597,16598,16599,16600,16601,16602,16603,
91728 16604,16605,16606,16607,16608,16609,16610,16611,16612,16613,16614,16615,
91729 16616,16617,16618,16619,16620,16621,16622,16623,16624,16625,16626,16627,
91730 16628,16629,16630,16631,16632,16633,16634,16635,16636,16637,16638,16639,
91731 16640,16641,16642,16643,16644,16645,16646,16647,16648,16649,16650,16651,
91732 16652,16653,16654,16655,16656,16657,16658,16659,16660,16661,16662,16663,
91733 16664,16665,16666,16667,16668,16669,16670,16671,16672,16673,16674,16675,
91734 16676,16677,16678,16679,16680,16681,16682,16683,16684,16685,16686,16687,
91735 16688,16689,16690,16691,16692,16693,16694,16695,16696,16697,16698,16699,
91736 16700,16701,16702,16703,16704,16705,16706,16707,16708,16709,16710,16711,
91737 16712,16713,16714,16715,16716,16717,16718,16719,16720,16721,16722,16723,
91738 16724,16725,16726,16727,16728,16729,16730,16731,16732,16733,16734,16735,
91739 16736,16737,16738,16739,16740,16741,16742,16743,16744,16745,16746,16747,
91740 16748,16749,16750,16751,16752,16753,16754,16755,16756,16757,16758,16759,
91741 16760,16761,16762,16763,16764,16765,16766,16767,16768,16769,16770,16771,
91742 16772,16773,16774,16775,16776,16777,16778,16779,16780,16781,16782,16783,
91743 16784,16785,16786,16787,16788,16789,16790,16791,16792,16793,16794,16795,
91744 16796,16797,16798,16799,16800,16801,16802,16803,16804,16805,16806,16807,
91745 16808,16809,16810,16811,16812,16813,16814,16815,16816,16817,16818,16819,
91746 16820,16821,16822,16823,16824,16825,16826,16827,16828,16829,16830,16831,
91747 16832,16833,16834,16835,16836,16837,16838,16839,16840,16841,16842,16843,
91748 16844,16845,16846,16847,16848,16849,16850,16851,16852,16853,16854,16855,
91749 16856,16857,16858,16859,16860,16861,16862,16863,16864,16865,16866,16867,
91750 16868,16869,16870,16871,16872,16873,16874,16875,16876,16877,16878,16879,
91751 16880,16881,16882,16883,16884,16885,16886,16887,16888,16889,16890,16891,
91752 16892,16893,16894,16895,16896,16897,16898,16899,16900,16901,16902,16903,
91753 16904,16905,16906,16907,16908,16909,16910,16911,16912,16913,16914,16915,
91754 16916,16917,16918,16919,16920,16921,16922,16923,16924,16925,16926,16927,
91755 16928,16929,16930,16931,16932,16933,16934,16935,16936,16937,16938,16939,
91756 16940,16941,16942,16943,16944,16945,16946,16947,16948,16949,16950,16951,
91757 16952,16953,16954,16955,16956,16957,16958,16959,16960,16961,16962,16963,
91758 16964,16965,16966,16967,16968,16969,16970,16971,16972,16973,16974,16975,
91759 16976,16977,16978,16979,16980,16981,16982,16983,16984,16985,16986,16987,
91760 16988,16989,16990,16991,16992,16993,16994,16995,16996,16997,16998,16999,
91761 17000,17001,17002,17003,17004,17005,17006,17007,17008,17009,17010,17011,
91762 17012,17013,17014,17015,17016,17017,17018,17019,17020,17021,17022,17023,
91763 17024,17025,17026,17027,17028,17029,17030,17031,17032,17033,17034,17035,
91764 17036,17037,17038,17039,17040,17041,17042,17043,17044,17045,17046,17047,
91765 17048,17049,17050,17051,17052,17053,17054,17055,17056,17057,17058,17059,
91766 17060,17061,17062,17063,17064,17065,17066,17067,17068,17069,17070,17071,
91767 17072,17073,17074,17075,17076,17077,17078,17079,17080,17081,17082,17083,
91768 17084,17085,17086,17087,17088,17089,17090,17091,17092,17093,17094,17095,
91769 17096,17097,17098,17099,17100,17101,17102,17103,17104,17105,17106,17107,
91770 17108,17109,17110,17111,17112,17113,17114,17115,17116,17117,17118,17119,
91771 17120,17121,17122,17123,17124,17125,17126,17127,17128,17129,17130,17131,
91772 17132,17133,17134,17135,17136,17137,17138,17139,17140,17141,17142,17143,
91773 17144,17145,17146,17147,17148,17149,17150,17151,17152,17153,17154,17155,
91774 17156,17157,17158,17159,17160,17161,17162,17163,17164,17165,17166,17167,
91775 17168,17169,17170,17171,17172,17173,17174,17175,17176,17177,17178,17179,
91776 17180,17181,17182,17183,17184,17185,17186,17187,17188,17189,17190,17191,
91777 17192,17193,17194,17195,17196,17197,17198,17199,17200,17201,17202,17203,
91778 17204,17205,17206,17207,17208,17209,17210,17211,17212,17213,17214,17215,
91779 17216,17217,17218,17219,17220,17221,17222,17223,17224,17225,17226,17227,
91780 17228,17229,17230,17231,17232,17233,17234,17235,17236,17237,17238,17239,
91781 17240,17241,17242,17243,17244,17245,17246,17247,17248,17249,17250,17251,
91782 17252,17253,17254,17255,17256,17257,17258,17259,17260,17261,17262,17263,
91783 17264,17265,17266,17267,17268,17269,17270,17271,17272,17273,17274,17275,
91784 17276,17277,17278,17279,17280,17281,17282,17283,17284,17285,17286,17287,
91785 17288,17289,17290,17291,17292,17293,17294,17295,17296,17297,17298,17299,
91786 17300,17301,17302,17303,17304,17305,17306,17307,17308,17309,17310,17311,
91787 17312,17313,17314,17315,17316,17317,17318,17319,17320,17321,17322,17323,
91788 17324,17325,17326,17327,17328,17329,17330,17331,17332,17333,17334,17335,
91789 17336,17337,17338,17339,17340,17341,17342,17343,17344,17345,17346,17347,
91790 17348,17349,17350,17351,17352,17353,17354,17355,17356,17357,17358,17359,
91791 17360,17361,17362,17363,17364,17365,17366,17367,17368,17369,17370,17371,
91792 17372,17373,17374,17375,17376,17377,17378,17379,17380,17381,17382,17383,
91793 17384,17385,17386,17387,17388,17389,17390,17391,17392,17393,17394,17395,
91794 17396,17397,17398,17399,17400,17401,17402,17403,17404,17405,17406,17407,
91795 17408,17409,17410,17411,17412,17413,17414,17415,17416,17417,17418,17419,
91796 17420,17421,17422,17423,17424,17425,17426,17427,17428,17429,17430,17431,
91797 17432,17433,17434,17435,17436,17437,17438,17439,17440,17441,17442,17443,
91798 17444,17445,17446,17447,17448,17449,17450,17451,17452,17453,17454,17455,
91799 17456,17457,17458,17459,17460,17461,17462,17463,17464,17465,17466,17467,
91800 17468,17469,17470,17471,17472,17473,17474,17475,17476,17477,17478,17479,
91801 17480,17481,17482,17483,17484,17485,17486,17487,17488,17489,17490,17491,
91802 17492,17493,17494,17495,17496,17497,17498,17499,17500,17501,17502,17503,
91803 17504,17505,17506,17507,17508,17509,17510,17511,17512,17513,17514,17515,
91804 17516,17517,17518,17519,17520,17521,17522,17523,17524,17525,17526,17527,
91805 17528,17529,17530,17531,17532,17533,17534,17535,17536,17537,17538,17539,
91806 17540,17541,17542,17543,17544,17545,17546,17547,17548,17549,17550,17551,
91807 17552,17553,17554,17555,17556,17557,17558,17559,17560,17561,17562,17563,
91808 17564,17565,17566,17567,17568,17569,17570,17571,17572,17573,17574,17575,
91809 17576,17577,17578,17579,17580,17581,17582,17583,17584,17585,17586,17587,
91810 17588,17589,17590,17591,17592,17593,17594,17595,17596,17597,17598,17599,
91811 17600,17601,17602,17603,17604,17605,17606,17607,17608,17609,17610,17611,
91812 17612,17613,17614,17615,17616,17617,17618,17619,17620,17621,17622,17623,
91813 17624,17625,17626,17627,17628,17629,17630,17631,17632,17633,17634,17635,
91814 17636,17637,17638,17639,17640,17641,17642,17643,17644,17645,17646,17647,
91815 17648,17649,17650,17651,17652,17653,17654,17655,17656,17657,17658,17659,
91816 17660,17661,17662,17663,17664,17665,17666,17667,17668,17669,17670,17671,
91817 17672,17673,17674,17675,17676,17677,17678,17679,17680,17681,17682,17683,
91818 17684,17685,17686,17687,17688,17689,17690,17691,17692,17693,17694,17695,
91819 17696,17697,17698,17699,17700,17701,17702,17703,17704,17705,17706,17707,
91820 17708,17709,17710,17711,17712,17713,17714,17715,17716,17717,17718,17719,
91821 17720,17721,17722,17723,17724,17725,17726,17727,17728,17729,17730,17731,
91822 17732,17733,17734,17735,17736,17737,17738,17739,17740,17741,17742,17743,
91823 17744,17745,17746,17747,17748,17749,17750,17751,17752,17753,17754,17755,
91824 17756,17757,17758,17759,17760,17761,17762,17763,17764,17765,17766,17767,
91825 17768,17769,17770,17771,17772,17773,17774,17775,17776,17777,17778,17779,
91826 17780,17781,17782,17783,17784,17785,17786,17787,17788,17789,17790,17791,
91827 17792,17793,17794,17795,17796,17797,17798,17799,17800,17801,17802,17803,
91828 17804,17805,17806,17807,17808,17809,17810,17811,17812,17813,17814,17815,
91829 17816,17817,17818,17819,17820,17821,17822,17823,17824,17825,17826,17827,
91830 17828,17829,17830,17831,17832,17833,17834,17835,17836,17837,17838,17839,
91831 17840,17841,17842,17843,17844,17845,17846,17847,17848,17849,17850,17851,
91832 17852,17853,17854,17855,17856,17857,17858,17859,17860,17861,17862,17863,
91833 17864,17865,17866,17867,17868,17869,17870,17871,17872,17873,17874,17875,
91834 17876,17877,17878,17879,17880,17881,17882,17883,17884,17885,17886,17887,
91835 17888,17889,17890,17891,17892,17893,17894,17895,17896,17897,17898,17899,
91836 17900,17901,17902,17903,17904,17905,17906,17907,17908,17909,17910,17911,
91837 17912,17913,17914,17915,17916,17917,17918,17919,17920,17921,17922,17923,
91838 17924,17925,17926,17927,17928,17929,17930,17931,17932,17933,17934,17935,
91839 17936,17937,17938,17939,17940,17941,17942,17943,17944,17945,17946,17947,
91840 17948,17949,17950,17951,17952,17953,17954,17955,17956,17957,17958,17959,
91841 17960,17961,17962,17963,17964,17965,17966,17967,17968,17969,17970,17971,
91842 17972,17973,17974,17975,17976,17977,17978,17979,17980,17981,17982,17983,
91843 17984,17985,17986,17987,17988,17989,17990,17991,17992,17993,17994,17995,
91844 17996,17997,17998,17999,18000,18001,18002,18003,18004,18005,18006,18007,
91845 18008,18009,18010,18011,18012,18013,18014,18015,18016,18017,18018,18019,
91846 18020,18021,18022,18023,18024,18025,18026,18027,18028,18029,18030,18031,
91847 18032,18033,18034,18035,18036,18037,18038,18039,18040,18041,18042,18043,
91848 18044,18045,18046,18047,18048,18049,18050,18051,18052,18053,18054,18055,
91849 18056,18057,18058,18059,18060,18061,18062,18063,18064,18065,18066,18067,
91850 18068,18069,18070,18071,18072,18073,18074,18075,18076,18077,18078,18079,
91851 18080,18081,18082,18083,18084,18085,18086,18087,18088,18089,18090,18091,
91852 18092,18093,18094,18095,18096,18097,18098,18099,18100,18101,18102,18103,
91853 18104,18105,18106,18107,18108,18109,18110,18111,18112,18113,18114,18115,
91854 18116,18117,18118,18119,18120,18121,18122,18123,18124,18125,18126,18127,
91855 18128,18129,18130,18131,18132,18133,18134,18135,18136,18137,18138,18139,
91856 18140,18141,18142,18143,18144,18145,18146,18147,18148,18149,18150,18151,
91857 18152,18153,18154,18155,18156,18157,18158,18159,18160,18161,18162,18163,
91858 18164,18165,18166,18167,18168,18169,18170,18171,18172,18173,18174,18175,
91859 18176,18177,18178,18179,18180,18181,18182,18183,18184,18185,18186,18187,
91860 18188,18189,18190,18191,18192,18193,18194,18195,18196,18197,18198,18199,
91861 18200,18201,18202,18203,18204,18205,18206,18207,18208,18209,18210,18211,
91862 18212,18213,18214,18215,18216,18217,18218,18219,18220,18221,18222,18223,
91863 18224,18225,18226,18227,18228,18229,18230,18231,18232,18233,18234,18235,
91864 18236,18237,18238,18239,18240,18241,18242,18243,18244,18245,18246,18247,
91865 18248,18249,18250,18251,18252,18253,18254,18255,18256,18257,18258,18259,
91866 18260,18261,18262,18263,18264,18265,18266,18267,18268,18269,18270,18271,
91867 18272,18273,18274,18275,18276,18277,18278,18279,18280,18281,18282,18283,
91868 18284,18285,18286,18287,18288,18289,18290,18291,18292,18293,18294,18295,
91869 18296,18297,18298,18299,18300,18301,18302,18303,18304,18305,18306,18307,
91870 18308,18309,18310,18311,18312,18313,18314,18315,18316,18317,18318,18319,
91871 18320,18321,18322,18323,18324,18325,18326,18327,18328,18329,18330,18331,
91872 18332,18333,18334,18335,18336,18337,18338,18339,18340,18341,18342,18343,
91873 18344,18345,18346,18347,18348,18349,18350,18351,18352,18353,18354,18355,
91874 18356,18357,18358,18359,18360,18361,18362,18363,18364,18365,18366,18367,
91875 18368,18369,18370,18371,18372,18373,18374,18375,18376,18377,18378,18379,
91876 18380,18381,18382,18383,18384,18385,18386,18387,18388,18389,18390,18391,
91877 18392,18393,18394,18395,18396,18397,18398,18399,18400,18401,18402,18403,
91878 18404,18405,18406,18407,18408,18409,18410,18411,18412,18413,18414,18415,
91879 18416,18417,18418,18419,18420,18421,18422,18423,18424,18425,18426,18427,
91880 18428,18429,18430,18431,18432,18433,18434,18435,18436,18437,18438,18439,
91881 18440,18441,18442,18443,18444,18445,18446,18447,18448,18449,18450,18451,
91882 18452,18453,18454,18455,18456,18457,18458,18459,18460,18461,18462,18463,
91883 18464,18465,18466,18467,18468,18469,18470,18471,18472,18473,18474,18475,
91884 18476,18477,18478,18479,18480,18481,18482,18483,18484,18485,18486,18487,
91885 18488,18489,18490,18491,18492,18493,18494,18495,18496,18497,18498,18499,
91886 18500,18501,18502,18503,18504,18505,18506,18507,18508,18509,18510,18511,
91887 18512,18513,18514,18515,18516,18517,18518,18519,18520,18521,18522,18523,
91888 18524,18525,18526,18527,18528,18529,18530,18531,18532,18533,18534,18535,
91889 18536,18537,18538,18539,18540,18541,18542,18543,18544,18545,18546,18547,
91890 18548,18549,18550,18551,18552,18553,18554,18555,18556,18557,18558,18559,
91891 18560,18561,18562,18563,18564,18565,18566,18567,18568,18569,18570,18571,
91892 18572,18573,18574,18575,18576,18577,18578,18579,18580,18581,18582,18583,
91893 18584,18585,18586,18587,18588,18589,18590,18591,18592,18593,18594,18595,
91894 18596,18597,18598,18599,18600,18601,18602,18603,18604,18605,18606,18607,
91895 18608,18609,18610,18611,18612,18613,18614,18615,18616,18617,18618,18619,
91896 18620,18621,18622,18623,18624,18625,18626,18627,18628,18629,18630,18631,
91897 18632,18633,18634,18635,18636,18637,18638,18639,18640,18641,18642,18643,
91898 18644,18645,18646,18647,18648,18649,18650,18651,18652,18653,18654,18655,
91899 18656,18657,18658,18659,18660,18661,18662,18663,18664,18665,18666,18667,
91900 18668,18669,18670,18671,18672,18673,18674,18675,18676,18677,18678,18679,
91901 18680,18681,18682,18683,18684,18685,18686,18687,18688,18689,18690,18691,
91902 18692,18693,18694,18695,18696,18697,18698,18699,18700,18701,18702,18703,
91903 18704,18705,18706,18707,18708,18709,18710,18711,18712,18713,18714,18715,
91904 18716,18717,18718,18719,18720,18721,18722,18723,18724,18725,18726,18727,
91905 18728,18729,18730,18731,18732,18733,18734,18735,18736,18737,18738,18739,
91906 18740,18741,18742,18743,18744,18745,18746,18747,18748,18749,18750,18751,
91907 18752,18753,18754,18755,18756,18757,18758,18759,18760,18761,18762,18763,
91908 18764,18765,18766,18767,18768,18769,18770,18771,18772,18773,18774,18775,
91909 18776,18777,18778,18779,18780,18781,18782,18783,18784,18785,18786,18787,
91910 18788,18789,18790,18791,18792,18793,18794,18795,18796,18797,18798,18799,
91911 18800,18801,18802,18803,18804,18805,18806,18807,18808,18809,18810,18811,
91912 18812,18813,18814,18815,18816,18817,18818,18819,18820,18821,18822,18823,
91913 18824,18825,18826,18827,18828,18829,18830,18831,18832,18833,18834,18835,
91914 18836,18837,18838,18839,18840,18841,18842,18843,18844,18845,18846,18847,
91915 18848,18849,18850,18851,18852,18853,18854,18855,18856,18857,18858,18859,
91916 18860,18861,18862,18863,18864,18865,18866,18867,18868,18869,18870,18871,
91917 18872,18873,18874,18875,18876,18877,18878,18879,18880,18881,18882,18883,
91918 18884,18885,18886,18887,18888,18889,18890,18891,18892,18893,18894,18895,
91919 18896,18897,18898,18899,18900,18901,18902,18903,18904,18905,18906,18907,
91920 18908,18909,18910,18911,18912,18913,18914,18915,18916,18917,18918,18919,
91921 18920,18921,18922,18923,18924,18925,18926,18927,18928,18929,18930,18931,
91922 18932,18933,18934,18935,18936,18937,18938,18939,18940,18941,18942,18943,
91923 18944,18945,18946,18947,18948,18949,18950,18951,18952,18953,18954,18955,
91924 18956,18957,18958,18959,18960,18961,18962,18963,18964,18965,18966,18967,
91925 18968,18969,18970,18971,18972,18973,18974,18975,18976,18977,18978,18979,
91926 18980,18981,18982,18983,18984,18985,18986,18987,18988,18989,18990,18991,
91927 18992,18993,18994,18995,18996,18997,18998,18999,19000,19001,19002,19003,
91928 19004,19005,19006,19007,19008,19009,19010,19011,19012,19013,19014,19015,
91929 19016,19017,19018,19019,19020,19021,19022,19023,19024,19025,19026,19027,
91930 19028,19029,19030,19031,19032,19033,19034,19035,19036,19037,19038,19039,
91931 19040,19041,19042,19043,19044,19045,19046,19047,19048,19049,19050,19051,
91932 19052,19053,19054,19055,19056,19057,19058,19059,19060,19061,19062,19063,
91933 19064,19065,19066,19067,19068,19069,19070,19071,19072,19073,19074,19075,
91934 19076,19077,19078,19079,19080,19081,19082,19083,19084,19085,19086,19087,
91935 19088,19089,19090,19091,19092,19093,19094,19095,19096,19097,19098,19099,
91936 19100,19101,19102,19103,19104,19105,19106,19107,19108,19109,19110,19111,
91937 19112,19113,19114,19115,19116,19117,19118,19119,19120,19121,19122,19123,
91938 19124,19125,19126,19127,19128,19129,19130,19131,19132,19133,19134,19135,
91939 19136,19137,19138,19139,19140,19141,19142,19143,19144,19145,19146,19147,
91940 19148,19149,19150,19151,19152,19153,19154,19155,19156,19157,19158,19159,
91941 19160,19161,19162,19163,19164,19165,19166,19167,19168,19169,19170,19171,
91942 19172,19173,19174,19175,19176,19177,19178,19179,19180,19181,19182,19183,
91943 19184,19185,19186,19187,19188,19189,19190,19191,19192,19193,19194,19195,
91944 19196,19197,19198,19199,19200,19201,19202,19203,19204,19205,19206,19207,
91945 19208,19209,19210,19211,19212,19213,19214,19215,19216,19217,19218,19219,
91946 19220,19221,19222,19223,19224,19225,19226,19227,19228,19229,19230,19231,
91947 19232,19233,19234,19235,19236,19237,19238,19239,19240,19241,19242,19243,
91948 19244,19245,19246,19247,19248,19249,19250,19251,19252,19253,19254,19255,
91949 19256,19257,19258,19259,19260,19261,19262,19263,19264,19265,19266,19267,
91950 19268,19269,19270,19271,19272,19273,19274,19275,19276,19277,19278,19279,
91951 19280,19281,19282,19283,19284,19285,19286,19287,19288,19289,19290,19291,
91952 19292,19293,19294,19295,19296,19297,19298,19299,19300,19301,19302,19303,
91953 19304,19305,19306,19307,19308,19309,19310,19311,19312,19313,19314,19315,
91954 19316,19317,19318,19319,19320,19321,19322,19323,19324,19325,19326,19327,
91955 19328,19329,19330,19331,19332,19333,19334,19335,19336,19337,19338,19339,
91956 19340,19341,19342,19343,19344,19345,19346,19347,19348,19349,19350,19351,
91957 19352,19353,19354,19355,19356,19357,19358,19359,19360,19361,19362,19363,
91958 19364,19365,19366,19367,19368,19369,19370,19371,19372,19373,19374,19375,
91959 19376,19377,19378,19379,19380,19381,19382,19383,19384,19385,19386,19387,
91960 19388,19389,19390,19391,19392,19393,19394,19395,19396,19397,19398,19399,
91961 19400,19401,19402,19403,19404,19405,19406,19407,19408,19409,19410,19411,
91962 19412,19413,19414,19415,19416,19417,19418,19419,19420,19421,19422,19423,
91963 19424,19425,19426,19427,19428,19429,19430,19431,19432,19433,19434,19435,
91964 19436,19437,19438,19439,19440,19441,19442,19443,19444,19445,19446,19447,
91965 19448,19449,19450,19451,19452,19453,19454,19455,19456,19457,19458,19459,
91966 19460,19461,19462,19463,19464,19465,19466,19467,19468,19469,19470,19471,
91967 19472,19473,19474,19475,19476,19477,19478,19479,19480,19481,19482,19483,
91968 19484,19485,19486,19487,19488,19489,19490,19491,19492,19493,19494,19495,
91969 19496,19497,19498,19499,19500,19501,19502,19503,19504,19505,19506,19507,
91970 19508,19509,19510,19511,19512,19513,19514,19515,19516,19517,19518,19519,
91971 19520,19521,19522,19523,19524,19525,19526,19527,19528,19529,19530,19531,
91972 19532,19533,19534,19535,19536,19537,19538,19539,19540,19541,19542,19543,
91973 19544,19545,19546,19547,19548,19549,19550,19551,19552,19553,19554,19555,
91974 19556,19557,19558,19559,19560,19561,19562,19563,19564,19565,19566,19567,
91975 19568,19569,19570,19571,19572,19573,19574,19575,19576,19577,19578,19579,
91976 19580,19581,19582,19583,19584,19585,19586,19587,19588,19589,19590,19591,
91977 19592,19593,19594,19595,19596,19597,19598,19599,19600,19601,19602,19603,
91978 19604,19605,19606,19607,19608,19609,19610,19611,19612,19613,19614,19615,
91979 19616,19617,19618,19619,19620,19621,19622,19623,19624,19625,19626,19627,
91980 19628,19629,19630,19631,19632,19633,19634,19635,19636,19637,19638,19639,
91981 19640,19641,19642,19643,19644,19645,19646,19647,19648,19649,19650,19651,
91982 19652,19653,19654,19655,19656,19657,19658,19659,19660,19661,19662,19663,
91983 19664,19665,19666,19667,19668,19669,19670,19671,19672,19673,19674,19675,
91984 19676,19677,19678,19679,19680,19681,19682,19683,19684,19685,19686,19687,
91985 19688,19689,19690,19691,19692,19693,19694,19695,19696,19697,19698,19699,
91986 19700,19701,19702,19703,19704,19705,19706,19707,19708,19709,19710,19711,
91987 19712,19713,19714,19715,19716,19717,19718,19719,19720,19721,19722,19723,
91988 19724,19725,19726,19727,19728,19729,19730,19731,19732,19733,19734,19735,
91989 19736,19737,19738,19739,19740,19741,19742,19743,19744,19745,19746,19747,
91990 19748,19749,19750,19751,19752,19753,19754,19755,19756,19757,19758,19759,
91991 19760,19761,19762,19763,19764,19765,19766,19767,19768,19769,19770,19771,
91992 19772,19773,19774,19775,19776,19777,19778,19779,19780,19781,19782,19783,
91993 19784,19785,19786,19787,19788,19789,19790,19791,19792,19793,19794,19795,
91994 19796,19797,19798,19799,19800,19801,19802,19803,19804,19805,19806,19807,
91995 19808,19809,19810,19811,19812,19813,19814,19815,19816,19817,19818,19819,
91996 19820,19821,19822,19823,19824,19825,19826,19827,19828,19829,19830,19831,
91997 19832,19833,19834,19835,19836,19837,19838,19839,19840,19841,19842,19843,
91998 19844,19845,19846,19847,19848,19849,19850,19851,19852,19853,19854,19855,
91999 19856,19857,19858,19859,19860,19861,19862,19863,19864,19865,19866,19867,
92000 19868,19869,19870,19871,19872,19873,19874,19875,19876,19877,19878,19879,
92001 19880,19881,19882,19883,19884,19885,19886,19887,19888,19889,19890,19891,
92002 19892,19893,19894,19895,19896,19897,19898,19899,19900,19901,19902,19903,
92003 19904,19905,19906,19907,19908,19909,19910,19911,19912,19913,19914,19915,
92004 19916,19917,19918,19919,19920,19921,19922,19923,19924,19925,19926,19927,
92005 19928,19929,19930,19931,19932,19933,19934,19935,19936,19937,19938,19939,
92006 19940,19941,19942,19943,19944,19945,19946,19947,19948,19949,19950,19951,
92007 19952,19953,19954,19955,19956,19957,19958,19959,19960,19961,19962,19963,
92008 19964,19965,19966,19967,19968,19969,19970,19971,19972,19973,19974,19975,
92009 19976,19977,19978,19979,19980,19981,19982,19983,19984,19985,19986,19987,
92010 19988,19989,19990,19991,19992,19993,19994,19995,19996,19997,19998,19999,
92011 20000,20001,20002,20003,20004,20005,20006,20007,20008,20009,20010,20011,
92012 20012,20013,20014,20015,20016,20017,20018,20019,20020,20021,20022,20023,
92013 20024,20025,20026,20027,20028,20029,20030,20031,20032,20033,20034,20035,
92014 20036,20037,20038,20039,20040,20041,20042,20043,20044,20045,20046,20047,
92015 20048,20049,20050,20051,20052,20053,20054,20055,20056,20057,20058,20059,
92016 20060,20061,20062,20063,20064,20065,20066,20067,20068,20069,20070,20071,
92017 20072,20073,20074,20075,20076,20077,20078,20079,20080,20081,20082,20083,
92018 20084,20085,20086,20087,20088,20089,20090,20091,20092,20093,20094,20095,
92019 20096,20097,20098,20099,20100,20101,20102,20103,20104,20105,20106,20107,
92020 20108,20109,20110,20111,20112,20113,20114,20115,20116,20117,20118,20119,
92021 20120,20121,20122,20123,20124,20125,20126,20127,20128,20129,20130,20131,
92022 20132,20133,20134,20135,20136,20137,20138,20139,20140,20141,20142,20143,
92023 20144,20145,20146,20147,20148,20149,20150,20151,20152,20153,20154,20155,
92024 20156,20157,20158,20159,20160,20161,20162,20163,20164,20165,20166,20167,
92025 20168,20169,20170,20171,20172,20173,20174,20175,20176,20177,20178,20179,
92026 20180,20181,20182,20183,20184,20185,20186,20187,20188,20189,20190,20191,
92027 20192,20193,20194,20195,20196,20197,20198,20199,20200,20201,20202,20203,
92028 20204,20205,20206,20207,20208,20209,20210,20211,20212,20213,20214,20215,
92029 20216,20217,20218,20219,20220,20221,20222,20223,20224,20225,20226,20227,
92030 20228,20229,20230,20231,20232,20233,20234,20235,20236,20237,20238,20239,
92031 20240,20241,20242,20243,20244,20245,20246,20247,20248,20249,20250,20251,
92032 20252,20253,20254,20255,20256,20257,20258,20259,20260,20261,20262,20263,
92033 20264,20265,20266,20267,20268,20269,20270,20271,20272,20273,20274,20275,
92034 20276,20277,20278,20279,20280,20281,20282,20283,20284,20285,20286,20287,
92035 20288,20289,20290,20291,20292,20293,20294,20295,20296,20297,20298,20299,
92036 20300,20301,20302,20303,20304,20305,20306,20307,20308,20309,20310,20311,
92037 20312,20313,20314,20315,20316,20317,20318,20319,20320,20321,20322,20323,
92038 20324,20325,20326,20327,20328,20329,20330,20331,20332,20333,20334,20335,
92039 20336,20337,20338,20339,20340,20341,20342,20343,20344,20345,20346,20347,
92040 20348,20349,20350,20351,20352,20353,20354,20355,20356,20357,20358,20359,
92041 20360,20361,20362,20363,20364,20365,20366,20367,20368,20369,20370,20371,
92042 20372,20373,20374,20375,20376,20377,20378,20379,20380,20381,20382,20383,
92043 20384,20385,20386,20387,20388,20389,20390,20391,20392,20393,20394,20395,
92044 20396,20397,20398,20399,20400,20401,20402,20403,20404,20405,20406,20407,
92045 20408,20409,20410,20411,20412,20413,20414,20415,20416,20417,20418,20419,
92046 20420,20421,20422,20423,20424,20425,20426,20427,20428,20429,20430,20431,
92047 20432,20433,20434,20435,20436,20437,20438,20439,20440,20441,20442,20443,
92048 20444,20445,20446,20447,20448,20449,20450,20451,20452,20453,20454,20455,
92049 20456,20457,20458,20459,20460,20461,20462,20463,20464,20465,20466,20467,
92050 20468,20469,20470,20471,20472,20473,20474,20475,20476,20477,20478,20479,
92051 20480,20481,20482,20483,20484,20485,20486,20487,20488,20489,20490,20491,
92052 20492,20493,20494,20495,20496,20497,20498,20499,20500,20501,20502,20503,
92053 20504,20505,20506,20507,20508,20509,20510,20511,20512,20513,20514,20515,
92054 20516,20517,20518,20519,20520,20521,20522,20523,20524,20525,20526,20527,
92055 20528,20529,20530,20531,20532,20533,20534,20535,20536,20537,20538,20539,
92056 20540,20541,20542,20543,20544,20545,20546,20547,20548,20549,20550,20551,
92057 20552,20553,20554,20555,20556,20557,20558,20559,20560,20561,20562,20563,
92058 20564,20565,20566,20567,20568,20569,20570,20571,20572,20573,20574,20575,
92059 20576,20577,20578,20579,20580,20581,20582,20583,20584,20585,20586,20587,
92060 20588,20589,20590,20591,20592,20593,20594,20595,20596,20597,20598,20599,
92061 20600,20601,20602,20603,20604,20605,20606,20607,20608,20609,20610,20611,
92062 20612,20613,20614,20615,20616,20617,20618,20619,20620,20621,20622,20623,
92063 20624,20625,20626,20627,20628,20629,20630,20631,20632,20633,20634,20635,
92064 20636,20637,20638,20639,20640,20641,20642,20643,20644,20645,20646,20647,
92065 20648,20649,20650,20651,20652,20653,20654,20655,20656,20657,20658,20659,
92066 20660,20661,20662,20663,20664,20665,20666,20667,20668,20669,20670,20671,
92067 20672,20673,20674,20675,20676,20677,20678,20679,20680,20681,20682,20683,
92068 20684,20685,20686,20687,20688,20689,20690,20691,20692,20693,20694,20695,
92069 20696,20697,20698,20699,20700,20701,20702,20703,20704,20705,20706,20707,
92070 20708,20709,20710,20711,20712,20713,20714,20715,20716,20717,20718,20719,
92071 20720,20721,20722,20723,20724,20725,20726,20727,20728,20729,20730,20731,
92072 20732,20733,20734,20735,20736,20737,20738,20739,20740,20741,20742,20743,
92073 20744,20745,20746,20747,20748,20749,20750,20751,20752,20753,20754,20755,
92074 20756,20757,20758,20759,20760,20761,20762,20763,20764,20765,20766,20767,
92075 20768,20769,20770,20771,20772,20773,20774,20775,20776,20777,20778,20779,
92076 20780,20781,20782,20783,20784,20785,20786,20787,20788,20789,20790,20791,
92077 20792,20793,20794,20795,20796,20797,20798,20799,20800,20801,20802,20803,
92078 20804,20805,20806,20807,20808,20809,20810,20811,20812,20813,20814,20815,
92079 20816,20817,20818,20819,20820,20821,20822,20823,20824,20825,20826,20827,
92080 20828,20829,20830,20831,20832,20833,20834,20835,20836,20837,20838,20839,
92081 20840,20841,20842,20843,20844,20845,20846,20847,20848,20849,20850,20851,
92082 20852,20853,20854,20855,20856,20857,20858,20859,20860,20861,20862,20863,
92083 20864,20865,20866,20867,20868,20869,20870,20871,20872,20873,20874,20875,
92084 20876,20877,20878,20879,20880,20881,20882,20883,20884,20885,20886,20887,
92085 20888,20889,20890,20891,20892,20893,20894,20895,20896,20897,20898,20899,
92086 20900,20901,20902,20903,20904,20905,20906,20907,20908,20909,20910,20911,
92087 20912,20913,20914,20915,20916,20917,20918,20919,20920,20921,20922,20923,
92088 20924,20925,20926,20927,20928,20929,20930,20931,20932,20933,20934,20935,
92089 20936,20937,20938,20939,20940,20941,20942,20943,20944,20945,20946,20947,
92090 20948,20949,20950,20951,20952,20953,20954,20955,20956,20957,20958,20959,
92091 20960,20961,20962,20963,20964,20965,20966,20967,20968,20969,20970,20971,
92092 20972,20973,20974,20975,20976,20977,20978,20979,20980,20981,20982,20983,
92093 20984,20985,20986,20987,20988,20989,20990,20991,20992,20993,20994,20995,
92094 20996,20997,20998,20999,21000,21001,21002,21003,21004,21005,21006,21007,
92095 21008,21009,21010,21011,21012,21013,21014,21015,21016,21017,21018,21019,
92096 21020,21021,21022,21023,21024,21025,21026,21027,21028,21029,21030,21031,
92097 21032,21033,21034,21035,21036,21037,21038,21039,21040,21041,21042,21043,
92098 21044,21045,21046,21047,21048,21049,21050,21051,21052,21053,21054,21055,
92099 21056,21057,21058,21059,21060,21061,21062,21063,21064,21065,21066,21067,
92100 21068,21069,21070,21071,21072,21073,21074,21075,21076,21077,21078,21079,
92101 21080,21081,21082,21083,21084,21085,21086,21087,21088,21089,21090,21091,
92102 21092,21093,21094,21095,21096,21097,21098,21099,21100,21101,21102,21103,
92103 21104,21105,21106,21107,21108,21109,21110,21111,21112,21113,21114,21115,
92104 21116,21117,21118,21119,21120,21121,21122,21123,21124,21125,21126,21127,
92105 21128,21129,21130,21131,21132,21133,21134,21135,21136,21137,21138,21139,
92106 21140,21141,21142,21143,21144,21145,21146,21147,21148,21149,21150,21151,
92107 21152,21153,21154,21155,21156,21157,21158,21159,21160,21161,21162,21163,
92108 21164,21165,21166,21167,21168,21169,21170,21171,21172,21173,21174,21175,
92109 21176,21177,21178,21179,21180,21181,21182,21183,21184,21185,21186,21187,
92110 21188,21189,21190,21191,21192,21193,21194,21195,21196,21197,21198,21199,
92111 21200,21201,21202,21203,21204,21205,21206,21207,21208,21209,21210,21211,
92112 21212,21213,21214,21215,21216,21217,21218,21219,21220,21221,21222,21223,
92113 21224,21225,21226,21227,21228,21229,21230,21231,21232,21233,21234,21235,
92114 21236,21237,21238,21239,21240,21241,21242,21243,21244,21245,21246,21247,
92115 21248,21249,21250,21251,21252,21253,21254,21255,21256,21257,21258,21259,
92116 21260,21261,21262,21263,21264,21265,21266,21267,21268,21269,21270,21271,
92117 21272,21273,21274,21275,21276,21277,21278,21279,21280,21281,21282,21283,
92118 21284,21285,21286,21287,21288,21289,21290,21291,21292,21293,21294,21295,
92119 21296,21297,21298,21299,21300,21301,21302,21303,21304,21305,21306,21307,
92120 21308,21309,21310,21311,21312,21313,21314,21315,21316,21317,21318,21319,
92121 21320,21321,21322,21323,21324,21325,21326,21327,21328,21329,21330,21331,
92122 21332,21333,21334,21335,21336,21337,21338,21339,21340,21341,21342,21343,
92123 21344,21345,21346,21347,21348,21349,21350,21351,21352,21353,21354,21355,
92124 21356,21357,21358,21359,21360,21361,21362,21363,21364,21365,21366,21367,
92125 21368,21369,21370,21371,21372,21373,21374,21375,21376,21377,21378,21379,
92126 21380,21381,21382,21383,21384,21385,21386,21387,21388,21389,21390,21391,
92127 21392,21393,21394,21395,21396,21397,21398,21399,21400,21401,21402,21403,
92128 21404,21405,21406,21407,21408,21409,21410,21411,21412,21413,21414,21415,
92129 21416,21417,21418,21419,21420,21421,21422,21423,21424,21425,21426,21427,
92130 21428,21429,21430,21431,21432,21433,21434,21435,21436,21437,21438,21439,
92131 21440,21441,21442,21443,21444,21445,21446,21447,21448,21449,21450,21451,
92132 21452,21453,21454,21455,21456,21457,21458,21459,21460,21461,21462,21463,
92133 21464,21465,21466,21467,21468,21469,21470,21471,21472,21473,21474,21475,
92134 21476,21477,21478,21479,21480,21481,21482,21483,21484,21485,21486,21487,
92135 21488,21489,21490,21491,21492,21493,21494,21495,21496,21497,21498,21499,
92136 21500,21501,21502,21503,21504,21505,21506,21507,21508,21509,21510,21511,
92137 21512,21513,21514,21515,21516,21517,21518,21519,21520,21521,21522,21523,
92138 21524,21525,21526,21527,21528,21529,21530,21531,21532,21533,21534,21535,
92139 21536,21537,21538,21539,21540,21541,21542,21543,21544,21545,21546,21547,
92140 21548,21549,21550,21551,21552,21553,21554,21555,21556,21557,21558,21559,
92141 21560,21561,21562,21563,21564,21565,21566,21567,21568,21569,21570,21571,
92142 21572,21573,21574,21575,21576,21577,21578,21579,21580,21581,21582,21583,
92143 21584,21585,21586,21587,21588,21589,21590,21591,21592,21593,21594,21595,
92144 21596,21597,21598,21599,21600,21601,21602,21603,21604,21605,21606,21607,
92145 21608,21609,21610,21611,21612,21613,21614,21615,21616,21617,21618,21619,
92146 21620,21621,21622,21623,21624,21625,21626,21627,21628,21629,21630,21631,
92147 21632,21633,21634,21635,21636,21637,21638,21639,21640,21641,21642,21643,
92148 21644,21645,21646,21647,21648,21649,21650,21651,21652,21653,21654,21655,
92149 21656,21657,21658,21659,21660,21661,21662,21663,21664,21665,21666,21667,
92150 21668,21669,21670,21671,21672,21673,21674,21675,21676,21677,21678,21679,
92151 21680,21681,21682,21683,21684,21685,21686,21687,21688,21689,21690,21691,
92152 21692,21693,21694,21695,21696,21697,21698,21699,21700,21701,21702,21703,
92153 21704,21705,21706,21707,21708,21709,21710,21711,21712,21713,21714,21715,
92154 21716,21717,21718,21719,21720,21721,21722,21723,21724,21725,21726,21727,
92155 21728,21729,21730,21731,21732,21733,21734,21735,21736,21737,21738,21739,
92156 21740,21741,21742,21743,21744,21745,21746,21747,21748,21749,21750,21751,
92157 21752,21753,21754,21755,21756,21757,21758,21759,21760,21761,21762,21763,
92158 21764,21765,21766,21767,21768,21769,21770,21771,21772,21773,21774,21775,
92159 21776,21777,21778,21779,21780,21781,21782,21783,21784,21785,21786,21787,
92160 21788,21789,21790,21791,21792,21793,21794,21795,21796,21797,21798,21799,
92161 21800,21801,21802,21803,21804,21805,21806,21807,21808,21809,21810,21811,
92162 21812,21813,21814,21815,21816,21817,21818,21819,21820,21821,21822,21823,
92163 21824,21825,21826,21827,21828,21829,21830,21831,21832,21833,21834,21835,
92164 21836,21837,21838,21839,21840,21841,21842,21843,21844,21845,21846,21847,
92165 21848,21849,21850,21851,21852,21853,21854,21855,21856,21857,21858,21859,
92166 21860,21861,21862,21863,21864,21865,21866,21867,21868,21869,21870,21871,
92167 21872,21873,21874,21875,21876,21877,21878,21879,21880,21881,21882,21883,
92168 21884,21885,21886,21887,21888,21889,21890,21891,21892,21893,21894,21895,
92169 21896,21897,21898,21899,21900,21901,21902,21903,21904,21905,21906,21907,
92170 21908,21909,21910,21911,21912,21913,21914,21915,21916,21917,21918,21919,
92171 21920,21921,21922,21923,21924,21925,21926,21927,21928,21929,21930,21931,
92172 21932,21933,21934,21935,21936,21937,21938,21939,21940,21941,21942,21943,
92173 21944,21945,21946,21947,21948,21949,21950,21951,21952,21953,21954,21955,
92174 21956,21957,21958,21959,21960,21961,21962,21963,21964,21965,21966,21967,
92175 21968,21969,21970,21971,21972,21973,21974,21975,21976,21977,21978,21979,
92176 21980,21981,21982,21983,21984,21985,21986,21987,21988,21989,21990,21991,
92177 21992,21993,21994,21995,21996,21997,21998,21999,22000,22001,22002,22003,
92178 22004,22005,22006,22007,22008,22009,22010,22011,22012,22013,22014,22015,
92179 22016,22017,22018,22019,22020,22021,22022,22023,22024,22025,22026,22027,
92180 22028,22029,22030,22031,22032,22033,22034,22035,22036,22037,22038,22039,
92181 22040,22041,22042,22043,22044,22045,22046,22047,22048,22049,22050,22051,
92182 22052,22053,22054,22055,22056,22057,22058,22059,22060,22061,22062,22063,
92183 22064,22065,22066,22067,22068,22069,22070,22071,22072,22073,22074,22075,
92184 22076,22077,22078,22079,22080,22081,22082,22083,22084,22085,22086,22087,
92185 22088,22089,22090,22091,22092,22093,22094,22095,22096,22097,22098,22099,
92186 22100,22101,22102,22103,22104,22105,22106,22107,22108,22109,22110,22111,
92187 22112,22113,22114,22115,22116,22117,22118,22119,22120,22121,22122,22123,
92188 22124,22125,22126,22127,22128,22129,22130,22131,22132,22133,22134,22135,
92189 22136,22137,22138,22139,22140,22141,22142,22143,22144,22145,22146,22147,
92190 22148,22149,22150,22151,22152,22153,22154,22155,22156,22157,22158,22159,
92191 22160,22161,22162,22163,22164,22165,22166,22167,22168,22169,22170,22171,
92192 22172,22173,22174,22175,22176,22177,22178,22179,22180,22181,22182,22183,
92193 22184,22185,22186,22187,22188,22189,22190,22191,22192,22193,22194,22195,
92194 22196,22197,22198,22199,22200,22201,22202,22203,22204,22205,22206,22207,
92195 22208,22209,22210,22211,22212,22213,22214,22215,22216,22217,22218,22219,
92196 22220,22221,22222,22223,22224,22225,22226,22227,22228,22229,22230,22231,
92197 22232,22233,22234,22235,22236,22237,22238,22239,22240,22241,22242,22243,
92198 22244,22245,22246,22247,22248,22249,22250,22251,22252,22253,22254,22255,
92199 22256,22257,22258,22259,22260,22261,22262,22263,22264,22265,22266,22267,
92200 22268,22269,22270,22271,22272,22273,22274,22275,22276,22277,22278,22279,
92201 22280,22281,22282,22283,22284,22285,22286,22287,22288,22289,22290,22291,
92202 22292,22293,22294,22295,22296,22297,22298,22299,22300,22301,22302,22303,
92203 22304,22305,22306,22307,22308,22309,22310,22311,22312,22313,22314,22315,
92204 22316,22317,22318,22319,22320,22321,22322,22323,22324,22325,22326,22327,
92205 22328,22329,22330,22331,22332,22333,22334,22335,22336,22337,22338,22339,
92206 22340,22341,22342,22343,22344,22345,22346,22347,22348,22349,22350,22351,
92207 22352,22353,22354,22355,22356,22357,22358,22359,22360,22361,22362,22363,
92208 22364,22365,22366,22367,22368,22369,22370,22371,22372,22373,22374,22375,
92209 22376,22377,22378,22379,22380,22381,22382,22383,22384,22385,22386,22387,
92210 22388,22389,22390,22391,22392,22393,22394,22395,22396,22397,22398,22399,
92211 22400,22401,22402,22403,22404,22405,22406,22407,22408,22409,22410,22411,
92212 22412,22413,22414,22415,22416,22417,22418,22419,22420,22421,22422,22423,
92213 22424,22425,22426,22427,22428,22429,22430,22431,22432,22433,22434,22435,
92214 22436,22437,22438,22439,22440,22441,22442,22443,22444,22445,22446,22447,
92215 22448,22449,22450,22451,22452,22453,22454,22455,22456,22457,22458,22459,
92216 22460,22461,22462,22463,22464,22465,22466,22467,22468,22469,22470,22471,
92217 22472,22473,22474,22475,22476,22477,22478,22479,22480,22481,22482,22483,
92218 22484,22485,22486,22487,22488,22489,22490,22491,22492,22493,22494,22495,
92219 22496,22497,22498,22499,22500,22501,22502,22503,22504,22505,22506,22507,
92220 22508,22509,22510,22511,22512,22513,22514,22515,22516,22517,22518,22519,
92221 22520,22521,22522,22523,22524,22525,22526,22527,22528,22529,22530,22531,
92222 22532,22533,22534,22535,22536,22537,22538,22539,22540,22541,22542,22543,
92223 22544,22545,22546,22547,22548,22549,22550,22551,22552,22553,22554,22555,
92224 22556,22557,22558,22559,22560,22561,22562,22563,22564,22565,22566,22567,
92225 22568,22569,22570,22571,22572,22573,22574,22575,22576,22577,22578,22579,
92226 22580,22581,22582,22583,22584,22585,22586,22587,22588,22589,22590,22591,
92227 22592,22593,22594,22595,22596,22597,22598,22599,22600,22601,22602,22603,
92228 22604,22605,22606,22607,22608,22609,22610,22611,22612,22613,22614,22615,
92229 22616,22617,22618,22619,22620,22621,22622,22623,22624,22625,22626,22627,
92230 22628,22629,22630,22631,22632,22633,22634,22635,22636,22637,22638,22639,
92231 22640,22641,22642,22643,22644,22645,22646,22647,22648,22649,22650,22651,
92232 22652,22653,22654,22655,22656,22657,22658,22659,22660,22661,22662,22663,
92233 22664,22665,22666,22667,22668,22669,22670,22671,22672,22673,22674,22675,
92234 22676,22677,22678,22679,22680,22681,22682,22683,22684,22685,22686,22687,
92235 22688,22689,22690,22691,22692,22693,22694,22695,22696,22697,22698,22699,
92236 22700,22701,22702,22703,22704,22705,22706,22707,22708,22709,22710,22711,
92237 22712,22713,22714,22715,22716,22717,22718,22719,22720,22721,22722,22723,
92238 22724,22725,22726,22727,22728,22729,22730,22731,22732,22733,22734,22735,
92239 22736,22737,22738,22739,22740,22741,22742,22743,22744,22745,22746,22747,
92240 22748,22749,22750,22751,22752,22753,22754,22755,22756,22757,22758,22759,
92241 22760,22761,22762,22763,22764,22765,22766,22767,22768,22769,22770,22771,
92242 22772,22773,22774,22775,22776,22777,22778,22779,22780,22781,22782,22783,
92243 22784,22785,22786,22787,22788,22789,22790,22791,22792,22793,22794,22795,
92244 22796,22797,22798,22799,22800,22801,22802,22803,22804,22805,22806,22807,
92245 22808,22809,22810,22811,22812,22813,22814,22815,22816,22817,22818,22819,
92246 22820,22821,22822,22823,22824,22825,22826,22827,22828,22829,22830,22831,
92247 22832,22833,22834,22835,22836,22837,22838,22839,22840,22841,22842,22843,
92248 22844,22845,22846,22847,22848,22849,22850,22851,22852,22853,22854,22855,
92249 22856,22857,22858,22859,22860,22861,22862,22863,22864,22865,22866,22867,
92250 22868,22869,22870,22871,22872,22873,22874,22875,22876,22877,22878,22879,
92251 22880,22881,22882,22883,22884,22885,22886,22887,22888,22889,22890,22891,
92252 22892,22893,22894,22895,22896,22897,22898,22899,22900,22901,22902,22903,
92253 22904,22905,22906,22907,22908,22909,22910,22911,22912,22913,22914,22915,
92254 22916,22917,22918,22919,22920,22921,22922,22923,22924,22925,22926,22927,
92255 22928,22929,22930,22931,22932,22933,22934,22935,22936,22937,22938,22939,
92256 22940,22941,22942,22943,22944,22945,22946,22947,22948,22949,22950,22951,
92257 22952,22953,22954,22955,22956,22957,22958,22959,22960,22961,22962,22963,
92258 22964,22965,22966,22967,22968,22969,22970,22971,22972,22973,22974,22975,
92259 22976,22977,22978,22979,22980,22981,22982,22983,22984,22985,22986,22987,
92260 22988,22989,22990,22991,22992,22993,22994,22995,22996,22997,22998,22999,
92261 23000,23001,23002,23003,23004,23005,23006,23007,23008,23009,23010,23011,
92262 23012,23013,23014,23015,23016,23017,23018,23019,23020,23021,23022,23023,
92263 23024,23025,23026,23027,23028,23029,23030,23031,23032,23033,23034,23035,
92264 23036,23037,23038,23039,23040,23041,23042,23043,23044,23045,23046,23047,
92265 23048,23049,23050,23051,23052,23053,23054,23055,23056,23057,23058,23059,
92266 23060,23061,23062,23063,23064,23065,23066,23067,23068,23069,23070,23071,
92267 23072,23073,23074,23075,23076,23077,23078,23079,23080,23081,23082,23083,
92268 23084,23085,23086,23087,23088,23089,23090,23091,23092,23093,23094,23095,
92269 23096,23097,23098,23099,23100,23101,23102,23103,23104,23105,23106,23107,
92270 23108,23109,23110,23111,23112,23113,23114,23115,23116,23117,23118,23119,
92271 23120,23121,23122,23123,23124,23125,23126,23127,23128,23129,23130,23131,
92272 23132,23133,23134,23135,23136,23137,23138,23139,23140,23141,23142,23143,
92273 23144,23145,23146,23147,23148,23149,23150,23151,23152,23153,23154,23155,
92274 23156,23157,23158,23159,23160,23161,23162,23163,23164,23165,23166,23167,
92275 23168,23169,23170,23171,23172,23173,23174,23175,23176,23177,23178,23179,
92276 23180,23181,23182,23183,23184,23185,23186,23187,23188,23189,23190,23191,
92277 23192,23193,23194,23195,23196,23197,23198,23199,23200,23201,23202,23203,
92278 23204,23205,23206,23207,23208,23209,23210,23211,23212,23213,23214,23215,
92279 23216,23217,23218,23219,23220,23221,23222,23223,23224,23225,23226,23227,
92280 23228,23229,23230,23231,23232,23233,23234,23235,23236,23237,23238,23239,
92281 23240,23241,23242,23243,23244,23245,23246,23247,23248,23249,23250,23251,
92282 23252,23253,23254,23255,23256,23257,23258,23259,23260,23261,23262,23263,
92283 23264,23265,23266,23267,23268,23269,23270,23271,23272,23273,23274,23275,
92284 23276,23277,23278,23279,23280,23281,23282,23283,23284,23285,23286,23287,
92285 23288,23289,23290,23291,23292,23293,23294,23295,23296,23297,23298,23299,
92286 23300,23301,23302,23303,23304,23305,23306,23307,23308,23309,23310,23311,
92287 23312,23313,23314,23315,23316,23317,23318,23319,23320,23321,23322,23323,
92288 23324,23325,23326,23327,23328,23329,23330,23331,23332,23333,23334,23335,
92289 23336,23337,23338,23339,23340,23341,23342,23343,23344,23345,23346,23347,
92290 23348,23349,23350,23351,23352,23353,23354,23355,23356,23357,23358,23359,
92291 23360,23361,23362,23363,23364,23365,23366,23367,23368,23369,23370,23371,
92292 23372,23373,23374,23375,23376,23377,23378,23379,23380,23381,23382,23383,
92293 23384,23385,23386,23387,23388,23389,23390,23391,23392,23393,23394,23395,
92294 23396,23397,23398,23399,23400,23401,23402,23403,23404,23405,23406,23407,
92295 23408,23409,23410,23411,23412,23413,23414,23415,23416,23417,23418,23419,
92296 23420,23421,23422,23423,23424,23425,23426,23427,23428,23429,23430,23431,
92297 23432,23433,23434,23435,23436,23437,23438,23439,23440,23441,23442,23443,
92298 23444,23445,23446,23447,23448,23449,23450,23451,23452,23453,23454,23455,
92299 23456,23457,23458,23459,23460,23461,23462,23463,23464,23465,23466,23467,
92300 23468,23469,23470,23471,23472,23473,23474,23475,23476,23477,23478,23479,
92301 23480,23481,23482,23483,23484,23485,23486,23487,23488,23489,23490,23491,
92302 23492,23493,23494,23495,23496,23497,23498,23499,23500,23501,23502,23503,
92303 23504,23505,23506,23507,23508,23509,23510,23511,23512,23513,23514,23515,
92304 23516,23517,23518,23519,23520,23521,23522,23523,23524,23525,23526,23527,
92305 23528,23529,23530,23531,23532,23533,23534,23535,23536,23537,23538,23539,
92306 23540,23541,23542,23543,23544,23545,23546,23547,23548,23549,23550,23551,
92307 23552,23553,23554,23555,23556,23557,23558,23559,23560,23561,23562,23563,
92308 23564,23565,23566,23567,23568,23569,23570,23571,23572,23573,23574,23575,
92309 23576,23577,23578,23579,23580,23581,23582,23583,23584,23585,23586,23587,
92310 23588,23589,23590,23591,23592,23593,23594,23595,23596,23597,23598,23599,
92311 23600,23601,23602,23603,23604,23605,23606,23607,23608,23609,23610,23611,
92312 23612,23613,23614,23615,23616,23617,23618,23619,23620,23621,23622,23623,
92313 23624,23625,23626,23627,23628,23629,23630,23631,23632,23633,23634,23635,
92314 23636,23637,23638,23639,23640,23641,23642,23643,23644,23645,23646,23647,
92315 23648,23649,23650,23651,23652,23653,23654,23655,23656,23657,23658,23659,
92316 23660,23661,23662,23663,23664,23665,23666,23667,23668,23669,23670,23671,
92317 23672,23673,23674,23675,23676,23677,23678,23679,23680,23681,23682,23683,
92318 23684,23685,23686,23687,23688,23689,23690,23691,23692,23693,23694,23695,
92319 23696,23697,23698,23699,23700,23701,23702,23703,23704,23705,23706,23707,
92320 23708,23709,23710,23711,23712,23713,23714,23715,23716,23717,23718,23719,
92321 23720,23721,23722,23723,23724,23725,23726,23727,23728,23729,23730,23731,
92322 23732,23733,23734,23735,23736,23737,23738,23739,23740,23741,23742,23743,
92323 23744,23745,23746,23747,23748,23749,23750,23751,23752,23753,23754,23755,
92324 23756,23757,23758,23759,23760,23761,23762,23763,23764,23765,23766,23767,
92325 23768,23769,23770,23771,23772,23773,23774,23775,23776,23777,23778,23779,
92326 23780,23781,23782,23783,23784,23785,23786,23787,23788,23789,23790,23791,
92327 23792,23793,23794,23795,23796,23797,23798,23799,23800,23801,23802,23803,
92328 23804,23805,23806,23807,23808,23809,23810,23811,23812,23813,23814,23815,
92329 23816,23817,23818,23819,23820,23821,23822,23823,23824,23825,23826,23827,
92330 23828,23829,23830,23831,23832,23833,23834,23835,23836,23837,23838,23839,
92331 23840,23841,23842,23843,23844,23845,23846,23847,23848,23849,23850,23851,
92332 23852,23853,23854,23855,23856,23857,23858,23859,23860,23861,23862,23863,
92333 23864,23865,23866,23867,23868,23869,23870,23871,23872,23873,23874,23875,
92334 23876,23877,23878,23879,23880,23881,23882,23883,23884,23885,23886,23887,
92335 23888,23889,23890,23891,23892,23893,23894,23895,23896,23897,23898,23899,
92336 23900,23901,23902,23903,23904,23905,23906,23907,23908,23909,23910,23911,
92337 23912,23913,23914,23915,23916,23917,23918,23919,23920,23921,23922,23923,
92338 23924,23925,23926,23927,23928,23929,23930,23931,23932,23933,23934,23935,
92339 23936,23937,23938,23939,23940,23941,23942,23943,23944,23945,23946,23947,
92340 23948,23949,23950,23951,23952,23953,23954,23955,23956,23957,23958,23959,
92341 23960,23961,23962,23963,23964,23965,23966,23967,23968,23969,23970,23971,
92342 23972,23973,23974,23975,23976,23977,23978,23979,23980,23981,23982,23983,
92343 23984,23985,23986,23987,23988,23989,23990,23991,23992,23993,23994,23995,
92344 23996,23997,23998,23999,24000,24001,24002,24003,24004,24005,24006,24007,
92345 24008,24009,24010,24011,24012,24013,24014,24015,24016,24017,24018,24019,
92346 24020,24021,24022,24023,24024,24025,24026,24027,24028,24029,24030,24031,
92347 24032,24033,24034,24035,24036,24037,24038,24039,24040,24041,24042,24043,
92348 24044,24045,24046,24047,24048,24049,24050,24051,24052,24053,24054,24055,
92349 24056,24057,24058,24059,24060,24061,24062,24063,24064,24065,24066,24067,
92350 24068,24069,24070,24071,24072,24073,24074,24075,24076,24077,24078,24079,
92351 24080,24081,24082,24083,24084,24085,24086,24087,24088,24089,24090,24091,
92352 24092,24093,24094,24095,24096,24097,24098,24099,24100,24101,24102,24103,
92353 24104,24105,24106,24107,24108,24109,24110,24111,24112,24113,24114,24115,
92354 24116,24117,24118,24119,24120,24121,24122,24123,24124,24125,24126,24127,
92355 24128,24129,24130,24131,24132,24133,24134,24135,24136,24137,24138,24139,
92356 24140,24141,24142,24143,24144,24145,24146,24147,24148,24149,24150,24151,
92357 24152,24153,24154,24155,24156,24157,24158,24159,24160,24161,24162,24163,
92358 24164,24165,24166,24167,24168,24169,24170,24171,24172,24173,24174,24175,
92359 24176,24177,24178,24179,24180,24181,24182,24183,24184,24185,24186,24187,
92360 24188,24189,24190,24191,24192,24193,24194,24195,24196,24197,24198,24199,
92361 24200,24201,24202,24203,24204,24205,24206,24207,24208,24209,24210,24211,
92362 24212,24213,24214,24215,24216,24217,24218,24219,24220,24221,24222,24223,
92363 24224,24225,24226,24227,24228,24229,24230,24231,24232,24233,24234,24235,
92364 24236,24237,24238,24239,24240,24241,24242,24243,24244,24245,24246,24247,
92365 24248,24249,24250,24251,24252,24253,24254,24255,24256,24257,24258,24259,
92366 24260,24261,24262,24263,24264,24265,24266,24267,24268,24269,24270,24271,
92367 24272,24273,24274,24275,24276,24277,24278,24279,24280,24281,24282,24283,
92368 24284,24285,24286,24287,24288,24289,24290,24291,24292,24293,24294,24295,
92369 24296,24297,24298,24299,24300,24301,24302,24303,24304,24305,24306,24307,
92370 24308,24309,24310,24311,24312,24313,24314,24315,24316,24317,24318,24319,
92371 24320,24321,24322,24323,24324,24325,24326,24327,24328,24329,24330,24331,
92372 24332,24333,24334,24335,24336,24337,24338,24339,24340,24341,24342,24343,
92373 24344,24345,24346,24347,24348,24349,24350,24351,24352,24353,24354,24355,
92374 24356,24357,24358,24359,24360,24361,24362,24363,24364,24365,24366,24367,
92375 24368,24369,24370,24371,24372,24373,24374,24375,24376,24377,24378,24379,
92376 24380,24381,24382,24383,24384,24385,24386,24387,24388,24389,24390,24391,
92377 24392,24393,24394,24395,24396,24397,24398,24399,24400,24401,24402,24403,
92378 24404,24405,24406,24407,24408,24409,24410,24411,24412,24413,24414,24415,
92379 24416,24417,24418,24419,24420,24421,24422,24423,24424,24425,24426,24427,
92380 24428,24429,24430,24431,24432,24433,24434,24435,24436,24437,24438,24439,
92381 24440,24441,24442,24443,24444,24445,24446,24447,24448,24449,24450,24451,
92382 24452,24453,24454,24455,24456,24457,24458,24459,24460,24461,24462,24463,
92383 24464,24465,24466,24467,24468,24469,24470,24471,24472,24473,24474,24475,
92384 24476,24477,24478,24479,24480,24481,24482,24483,24484,24485,24486,24487,
92385 24488,24489,24490,24491,24492,24493,24494,24495,24496,24497,24498,24499,
92386 24500,24501,24502,24503,24504,24505,24506,24507,24508,24509,24510,24511,
92387 24512,24513,24514,24515,24516,24517,24518,24519,24520,24521,24522,24523,
92388 24524,24525,24526,24527,24528,24529,24530,24531,24532,24533,24534,24535,
92389 24536,24537,24538,24539,24540,24541,24542,24543,24544,24545,24546,24547,
92390 24548,24549,24550,24551,24552,24553,24554,24555,24556,24557,24558,24559,
92391 24560,24561,24562,24563,24564,24565,24566,24567,24568,24569,24570,24571,
92392 24572,24573,24574,24575,24576,24577,24578,24579,24580,24581,24582,24583,
92393 24584,24585,24586,24587,24588,24589,24590,24591,24592,24593,24594,24595,
92394 24596,24597,24598,24599,24600,24601,24602,24603,24604,24605,24606,24607,
92395 24608,24609,24610,24611,24612,24613,24614,24615,24616,24617,24618,24619,
92396 24620,24621,24622,24623,24624,24625,24626,24627,24628,24629,24630,24631,
92397 24632,24633,24634,24635,24636,24637,24638,24639,24640,24641,24642,24643,
92398 24644,24645,24646,24647,24648,24649,24650,24651,24652,24653,24654,24655,
92399 24656,24657,24658,24659,24660,24661,24662,24663,24664,24665,24666,24667,
92400 24668,24669,24670,24671,24672,24673,24674,24675,24676,24677,24678,24679,
92401 24680,24681,24682,24683,24684,24685,24686,24687,24688,24689,24690,24691,
92402 24692,24693,24694,24695,24696,24697,24698,24699,24700,24701,24702,24703,
92403 24704,24705,24706,24707,24708,24709,24710,24711,24712,24713,24714,24715,
92404 24716,24717,24718,24719,24720,24721,24722,24723,24724,24725,24726,24727,
92405 24728,24729,24730,24731,24732,24733,24734,24735,24736,24737,24738,24739,
92406 24740,24741,24742,24743,24744,24745,24746,24747,24748,24749,24750,24751,
92407 24752,24753,24754,24755,24756,24757,24758,24759,24760,24761,24762,24763,
92408 24764,24765,24766,24767,24768,24769,24770,24771,24772,24773,24774,24775,
92409 24776,24777,24778,24779,24780,24781,24782,24783,24784,24785,24786,24787,
92410 24788,24789,24790,24791,24792,24793,24794,24795,24796,24797,24798,24799,
92411 24800,24801,24802,24803,24804,24805,24806,24807,24808,24809,24810,24811,
92412 24812,24813,24814,24815,24816,24817,24818,24819,24820,24821,24822,24823,
92413 24824,24825,24826,24827,24828,24829,24830,24831,24832,24833,24834,24835,
92414 24836,24837,24838,24839,24840,24841,24842,24843,24844,24845,24846,24847,
92415 24848,24849,24850,24851,24852,24853,24854,24855,24856,24857,24858,24859,
92416 24860,24861,24862,24863,24864,24865,24866,24867,24868,24869,24870,24871,
92417 24872,24873,24874,24875,24876,24877,24878,24879,24880,24881,24882,24883,
92418 24884,24885,24886,24887,24888,24889,24890,24891,24892,24893,24894,24895,
92419 24896,24897,24898,24899,24900,24901,24902,24903,24904,24905,24906,24907,
92420 24908,24909,24910,24911,24912,24913,24914,24915,24916,24917,24918,24919,
92421 24920,24921,24922,24923,24924,24925,24926,24927,24928,24929,24930,24931,
92422 24932,24933,24934,24935,24936,24937,24938,24939,24940,24941,24942,24943,
92423 24944,24945,24946,24947,24948,24949,24950,24951,24952,24953,24954,24955,
92424 24956,24957,24958,24959,24960,24961,24962,24963,24964,24965,24966,24967,
92425 24968,24969,24970,24971,24972,24973,24974,24975,24976,24977,24978,24979,
92426 24980,24981,24982,24983,24984,24985,24986,24987,24988,24989,24990,24991,
92427 24992,24993,24994,24995,24996,24997,24998,24999,25000,25001,25002,25003,
92428 25004,25005,25006,25007,25008,25009,25010,25011,25012,25013,25014,25015,
92429 25016,25017,25018,25019,25020,25021,25022,25023,25024,25025,25026,25027,
92430 25028,25029,25030,25031,25032,25033,25034,25035,25036,25037,25038,25039,
92431 25040,25041,25042,25043,25044,25045,25046,25047,25048,25049,25050,25051,
92432 25052,25053,25054,25055,25056,25057,25058,25059,25060,25061,25062,25063,
92433 25064,25065,25066,25067,25068,25069,25070,25071,25072,25073,25074,25075,
92434 25076,25077,25078,25079,25080,25081,25082,25083,25084,25085,25086,25087,
92435 25088,25089,25090,25091,25092,25093,25094,25095,25096,25097,25098,25099,
92436 25100,25101,25102,25103,25104,25105,25106,25107,25108,25109,25110,25111,
92437 25112,25113,25114,25115,25116,25117,25118,25119,25120,25121,25122,25123,
92438 25124,25125,25126,25127,25128,25129,25130,25131,25132,25133,25134,25135,
92439 25136,25137,25138,25139,25140,25141,25142,25143,25144,25145,25146,25147,
92440 25148,25149,25150,25151,25152,25153,25154,25155,25156,25157,25158,25159,
92441 25160,25161,25162,25163,25164,25165,25166,25167,25168,25169,25170,25171,
92442 25172,25173,25174,25175,25176,25177,25178,25179,25180,25181,25182,25183,
92443 25184,25185,25186,25187,25188,25189,25190,25191,25192,25193,25194,25195,
92444 25196,25197,25198,25199,25200,25201,25202,25203,25204,25205,25206,25207,
92445 25208,25209,25210,25211,25212,25213,25214,25215,25216,25217,25218,25219,
92446 25220,25221,25222,25223,25224,25225,25226,25227,25228,25229,25230,25231,
92447 25232,25233,25234,25235,25236,25237,25238,25239,25240,25241,25242,25243,
92448 25244,25245,25246,25247,25248,25249,25250,25251,25252,25253,25254,25255,
92449 25256,25257,25258,25259,25260,25261,25262,25263,25264,25265,25266,25267,
92450 25268,25269,25270,25271,25272,25273,25274,25275,25276,25277,25278,25279,
92451 25280,25281,25282,25283,25284,25285,25286,25287,25288,25289,25290,25291,
92452 25292,25293,25294,25295,25296,25297,25298,25299,25300,25301,25302,25303,
92453 25304,25305,25306,25307,25308,25309,25310,25311,25312,25313,25314,25315,
92454 25316,25317,25318,25319,25320,25321,25322,25323,25324,25325,25326,25327,
92455 25328,25329,25330,25331,25332,25333,25334,25335,25336,25337,25338,25339,
92456 25340,25341,25342,25343,25344,25345,25346,25347,25348,25349,25350,25351,
92457 25352,25353,25354,25355,25356,25357,25358,25359,25360,25361,25362,25363,
92458 25364,25365,25366,25367,25368,25369,25370,25371,25372,25373,25374,25375,
92459 25376,25377,25378,25379,25380,25381,25382,25383,25384,25385,25386,25387,
92460 25388,25389,25390,25391,25392,25393,25394,25395,25396,25397,25398,25399,
92461 25400,25401,25402,25403,25404,25405,25406,25407,25408,25409,25410,25411,
92462 25412,25413,25414,25415,25416,25417,25418,25419,25420,25421,25422,25423,
92463 25424,25425,25426,25427,25428,25429,25430,25431,25432,25433,25434,25435,
92464 25436,25437,25438,25439,25440,25441,25442,25443,25444,25445,25446,25447,
92465 25448,25449,25450,25451,25452,25453,25454,25455,25456,25457,25458,25459,
92466 25460,25461,25462,25463,25464,25465,25466,25467,25468,25469,25470,25471,
92467 25472,25473,25474,25475,25476,25477,25478,25479,25480,25481,25482,25483,
92468 25484,25485,25486,25487,25488,25489,25490,25491,25492,25493,25494,25495,
92469 25496,25497,25498,25499,25500,25501,25502,25503,25504,25505,25506,25507,
92470 25508,25509,25510,25511,25512,25513,25514,25515,25516,25517,25518,25519,
92471 25520,25521,25522,25523,25524,25525,25526,25527,25528,25529,25530,25531,
92472 25532,25533,25534,25535,25536,25537,25538,25539,25540,25541,25542,25543,
92473 25544,25545,25546,25547,25548,25549,25550,25551,25552,25553,25554,25555,
92474 25556,25557,25558,25559,25560,25561,25562,25563,25564,25565,25566,25567,
92475 25568,25569,25570,25571,25572,25573,25574,25575,25576,25577,25578,25579,
92476 25580,25581,25582,25583,25584,25585,25586,25587,25588,25589,25590,25591,
92477 25592,25593,25594,25595,25596,25597,25598,25599,25600,25601,25602,25603,
92478 25604,25605,25606,25607,25608,25609,25610,25611,25612,25613,25614,25615,
92479 25616,25617,25618,25619,25620,25621,25622,25623,25624,25625,25626,25627,
92480 25628,25629,25630,25631,25632,25633,25634,25635,25636,25637,25638,25639,
92481 25640,25641,25642,25643,25644,25645,25646,25647,25648,25649,25650,25651,
92482 25652,25653,25654,25655,25656,25657,25658,25659,25660,25661,25662,25663,
92483 25664,25665,25666,25667,25668,25669,25670,25671,25672,25673,25674,25675,
92484 25676,25677,25678,25679,25680,25681,25682,25683,25684,25685,25686,25687,
92485 25688,25689,25690,25691,25692,25693,25694,25695,25696,25697,25698,25699,
92486 25700,25701,25702,25703,25704,25705,25706,25707,25708,25709,25710,25711,
92487 25712,25713,25714,25715,25716,25717,25718,25719,25720,25721,25722,25723,
92488 25724,25725,25726,25727,25728,25729,25730,25731,25732,25733,25734,25735,
92489 25736,25737,25738,25739,25740,25741,25742,25743,25744,25745,25746,25747,
92490 25748,25749,25750,25751,25752,25753,25754,25755,25756,25757,25758,25759,
92491 25760,25761,25762,25763,25764,25765,25766,25767,25768,25769,25770,25771,
92492 25772,25773,25774,25775,25776,25777,25778,25779,25780,25781,25782,25783,
92493 25784,25785,25786,25787,25788,25789,25790,25791,25792,25793,25794,25795,
92494 25796,25797,25798,25799,25800,25801,25802,25803,25804,25805,25806,25807,
92495 25808,25809,25810,25811,25812,25813,25814,25815,25816,25817,25818,25819,
92496 25820,25821,25822,25823,25824,25825,25826,25827,25828,25829,25830,25831,
92497 25832,25833,25834,25835,25836,25837,25838,25839,25840,25841,25842,25843,
92498 25844,25845,25846,25847,25848,25849,25850,25851,25852,25853,25854,25855,
92499 25856,25857,25858,25859,25860,25861,25862,25863,25864,25865,25866,25867,
92500 25868,25869,25870,25871,25872,25873,25874,25875,25876,25877,25878,25879,
92501 25880,25881,25882,25883,25884,25885,25886,25887,25888,25889,25890,25891,
92502 25892,25893,25894,25895,25896,25897,25898,25899,25900,25901,25902,25903,
92503 25904,25905,25906,25907,25908,25909,25910,25911,25912,25913,25914,25915,
92504 25916,25917,25918,25919,25920,25921,25922,25923,25924,25925,25926,25927,
92505 25928,25929,25930,25931,25932,25933,25934,25935,25936,25937,25938,25939,
92506 25940,25941,25942,25943,25944,25945,25946,25947,25948,25949,25950,25951,
92507 25952,25953,25954,25955,25956,25957,25958,25959,25960,25961,25962,25963,
92508 25964,25965,25966,25967,25968,25969,25970,25971,25972,25973,25974,25975,
92509 25976,25977,25978,25979,25980,25981,25982,25983,25984,25985,25986,25987,
92510 25988,25989,25990,25991,25992,25993,25994,25995,25996,25997,25998,25999,
92511 26000,26001,26002,26003,26004,26005,26006,26007,26008,26009,26010,26011,
92512 26012,26013,26014,26015,26016,26017,26018,26019,26020,26021,26022,26023,
92513 26024,26025,26026,26027,26028,26029,26030,26031,26032,26033,26034,26035,
92514 26036,26037,26038,26039,26040,26041,26042,26043,26044,26045,26046,26047,
92515 26048,26049,26050,26051,26052,26053,26054,26055,26056,26057,26058,26059,
92516 26060,26061,26062,26063,26064,26065,26066,26067,26068,26069,26070,26071,
92517 26072,26073,26074,26075,26076,26077,26078,26079,26080,26081,26082,26083,
92518 26084,26085,26086,26087,26088,26089,26090,26091,26092,26093,26094,26095,
92519 26096,26097,26098,26099,26100,26101,26102,26103,26104,26105,26106,26107,
92520 26108,26109,26110,26111,26112,26113,26114,26115,26116,26117,26118,26119,
92521 26120,26121,26122,26123,26124,26125,26126,26127,26128,26129,26130,26131,
92522 26132,26133,26134,26135,26136,26137,26138,26139,26140,26141,26142,26143,
92523 26144,26145,26146,26147,26148,26149,26150,26151,26152,26153,26154,26155,
92524 26156,26157,26158,26159,26160,26161,26162,26163,26164,26165,26166,26167,
92525 26168,26169,26170,26171,26172,26173,26174,26175,26176,26177,26178,26179,
92526 26180,26181,26182,26183,26184,26185,26186,26187,26188,26189,26190,26191,
92527 26192,26193,26194,26195,26196,26197,26198,26199,26200,26201,26202,26203,
92528 26204,26205,26206,26207,26208,26209,26210,26211,26212,26213,26214,26215,
92529 26216,26217,26218,26219,26220,26221,26222,26223,26224,26225,26226,26227,
92530 26228,26229,26230,26231,26232,26233,26234,26235,26236,26237,26238,26239,
92531 26240,26241,26242,26243,26244,26245,26246,26247,26248,26249,26250,26251,
92532 26252,26253,26254,26255,26256,26257,26258,26259,26260,26261,26262,26263,
92533 26264,26265,26266,26267,26268,26269,26270,26271,26272,26273,26274,26275,
92534 26276,26277,26278,26279,26280,26281,26282,26283,26284,26285,26286,26287,
92535 26288,26289,26290,26291,26292,26293,26294,26295,26296,26297,26298,26299,
92536 26300,26301,26302,26303,26304,26305,26306,26307,26308,26309,26310,26311,
92537 26312,26313,26314,26315,26316,26317,26318,26319,26320,26321,26322,26323,
92538 26324,26325,26326,26327,26328,26329,26330,26331,26332,26333,26334,26335,
92539 26336,26337,26338,26339,26340,26341,26342,26343,26344,26345,26346,26347,
92540 26348,26349,26350,26351,26352,26353,26354,26355,26356,26357,26358,26359,
92541 26360,26361,26362,26363,26364,26365,26366,26367,26368,26369,26370,26371,
92542 26372,26373,26374,26375,26376,26377,26378,26379,26380,26381,26382,26383,
92543 26384,26385,26386,26387,26388,26389,26390,26391,26392,26393,26394,26395,
92544 26396,26397,26398,26399,26400,26401,26402,26403,26404,26405,26406,26407,
92545 26408,26409,26410,26411,26412,26413,26414,26415,26416,26417,26418,26419,
92546 26420,26421,26422,26423,26424,26425,26426,26427,26428,26429,26430,26431,
92547 26432,26433,26434,26435,26436,26437,26438,26439,26440,26441,26442,26443,
92548 26444,26445,26446,26447,26448,26449,26450,26451,26452,26453,26454,26455,
92549 26456,26457,26458,26459,26460,26461,26462,26463,26464,26465,26466,26467,
92550 26468,26469,26470,26471,26472,26473,26474,26475,26476,26477,26478,26479,
92551 26480,26481,26482,26483,26484,26485,26486,26487,26488,26489,26490,26491,
92552 26492,26493,26494,26495,26496,26497,26498,26499,26500,26501,26502,26503,
92553 26504,26505,26506,26507,26508,26509,26510,26511,26512,26513,26514,26515,
92554 26516,26517,26518,26519,26520,26521,26522,26523,26524,26525,26526,26527,
92555 26528,26529,26530,26531,26532,26533,26534,26535,26536,26537,26538,26539,
92556 26540,26541,26542,26543,26544,26545,26546,26547,26548,26549,26550,26551,
92557 26552,26553,26554,26555,26556,26557,26558,26559,26560,26561,26562,26563,
92558 26564,26565,26566,26567,26568,26569,26570,26571,26572,26573,26574,26575,
92559 26576,26577,26578,26579,26580,26581,26582,26583,26584,26585,26586,26587,
92560 26588,26589,26590,26591,26592,26593,26594,26595,26596,26597,26598,26599,
92561 26600,26601,26602,26603,26604,26605,26606,26607,26608,26609,26610,26611,
92562 26612,26613,26614,26615,26616,26617,26618,26619,26620,26621,26622,26623,
92563 26624,26625,26626,26627,26628,26629,26630,26631,26632,26633,26634,26635,
92564 26636,26637,26638,26639,26640,26641,26642,26643,26644,26645,26646,26647,
92565 26648,26649,26650,26651,26652,26653,26654,26655,26656,26657,26658,26659,
92566 26660,26661,26662,26663,26664,26665,26666,26667,26668,26669,26670,26671,
92567 26672,26673,26674,26675,26676,26677,26678,26679,26680,26681,26682,26683,
92568 26684,26685,26686,26687,26688,26689,26690,26691,26692,26693,26694,26695,
92569 26696,26697,26698,26699,26700,26701,26702,26703,26704,26705,26706,26707,
92570 26708,26709,26710,26711,26712,26713,26714,26715,26716,26717,26718,26719,
92571 26720,26721,26722,26723,26724,26725,26726,26727,26728,26729,26730,26731,
92572 26732,26733,26734,26735,26736,26737,26738,26739,26740,26741,26742,26743,
92573 26744,26745,26746,26747,26748,26749,26750,26751,26752,26753,26754,26755,
92574 26756,26757,26758,26759,26760,26761,26762,26763,26764,26765,26766,26767,
92575 26768,26769,26770,26771,26772,26773,26774,26775,26776,26777,26778,26779,
92576 26780,26781,26782,26783,26784,26785,26786,26787,26788,26789,26790,26791,
92577 26792,26793,26794,26795,26796,26797,26798,26799,26800,26801,26802,26803,
92578 26804,26805,26806,26807,26808,26809,26810,26811,26812,26813,26814,26815,
92579 26816,26817,26818,26819,26820,26821,26822,26823,26824,26825,26826,26827,
92580 26828,26829,26830,26831,26832,26833,26834,26835,26836,26837,26838,26839,
92581 26840,26841,26842,26843,26844,26845,26846,26847,26848,26849,26850,26851,
92582 26852,26853,26854,26855,26856,26857,26858,26859,26860,26861,26862,26863,
92583 26864,26865,26866,26867,26868,26869,26870,26871,26872,26873,26874,26875,
92584 26876,26877,26878,26879,26880,26881,26882,26883,26884,26885,26886,26887,
92585 26888,26889,26890,26891,26892,26893,26894,26895,26896,26897,26898,26899,
92586 26900,26901,26902,26903,26904,26905,26906,26907,26908,26909,26910,26911,
92587 26912,26913,26914,26915,26916,26917,26918,26919,26920,26921,26922,26923,
92588 26924,26925,26926,26927,26928,26929,26930,26931,26932,26933,26934,26935,
92589 26936,26937,26938,26939,26940,26941,26942,26943,26944,26945,26946,26947,
92590 26948,26949,26950,26951,26952,26953,26954,26955,26956,26957,26958,26959,
92591 26960,26961,26962,26963,26964,26965,26966,26967,26968,26969,26970,26971,
92592 26972,26973,26974,26975,26976,26977,26978,26979,26980,26981,26982,26983,
92593 26984,26985,26986,26987,26988,26989,26990,26991,26992,26993,26994,26995,
92594 26996,26997,26998,26999,27000,27001,27002,27003,27004,27005,27006,27007,
92595 27008,27009,27010,27011,27012,27013,27014,27015,27016,27017,27018,27019,
92596 27020,27021,27022,27023,27024,27025,27026,27027,27028,27029,27030,27031,
92597 27032,27033,27034,27035,27036,27037,27038,27039,27040,27041,27042,27043,
92598 27044,27045,27046,27047,27048,27049,27050,27051,27052,27053,27054,27055,
92599 27056,27057,27058,27059,27060,27061,27062,27063,27064,27065,27066,27067,
92600 27068,27069,27070,27071,27072,27073,27074,27075,27076,27077,27078,27079,
92601 27080,27081,27082,27083,27084,27085,27086,27087,27088,27089,27090,27091,
92602 27092,27093,27094,27095,27096,27097,27098,27099,27100,27101,27102,27103,
92603 27104,27105,27106,27107,27108,27109,27110,27111,27112,27113,27114,27115,
92604 27116,27117,27118,27119,27120,27121,27122,27123,27124,27125,27126,27127,
92605 27128,27129,27130,27131,27132,27133,27134,27135,27136,27137,27138,27139,
92606 27140,27141,27142,27143,27144,27145,27146,27147,27148,27149,27150,27151,
92607 27152,27153,27154,27155,27156,27157,27158,27159,27160,27161,27162,27163,
92608 27164,27165,27166,27167,27168,27169,27170,27171,27172,27173,27174,27175,
92609 27176,27177,27178,27179,27180,27181,27182,27183,27184,27185,27186,27187,
92610 27188,27189,27190,27191,27192,27193,27194,27195,27196,27197,27198,27199,
92611 27200,27201,27202,27203,27204,27205,27206,27207,27208,27209,27210,27211,
92612 27212,27213,27214,27215,27216,27217,27218,27219,27220,27221,27222,27223,
92613 27224,27225,27226,27227,27228,27229,27230,27231,27232,27233,27234,27235,
92614 27236,27237,27238,27239,27240,27241,27242,27243,27244,27245,27246,27247,
92615 27248,27249,27250,27251,27252,27253,27254,27255,27256,27257,27258,27259,
92616 27260,27261,27262,27263,27264,27265,27266,27267,27268,27269,27270,27271,
92617 27272,27273,27274,27275,27276,27277,27278,27279,27280,27281,27282,27283,
92618 27284,27285,27286,27287,27288,27289,27290,27291,27292,27293,27294,27295,
92619 27296,27297,27298,27299,27300,27301,27302,27303,27304,27305,27306,27307,
92620 27308,27309,27310,27311,27312,27313,27314,27315,27316,27317,27318,27319,
92621 27320,27321,27322,27323,27324,27325,27326,27327,27328,27329,27330,27331,
92622 27332,27333,27334,27335,27336,27337,27338,27339,27340,27341,27342,27343,
92623 27344,27345,27346,27347,27348,27349,27350,27351,27352,27353,27354,27355,
92624 27356,27357,27358,27359,27360,27361,27362,27363,27364,27365,27366,27367,
92625 27368,27369,27370,27371,27372,27373,27374,27375,27376,27377,27378,27379,
92626 27380,27381,27382,27383,27384,27385,27386,27387,27388,27389,27390,27391,
92627 27392,27393,27394,27395,27396,27397,27398,27399,27400,27401,27402,27403,
92628 27404,27405,27406,27407,27408,27409,27410,27411,27412,27413,27414,27415,
92629 27416,27417,27418,27419,27420,27421,27422,27423,27424,27425,27426,27427,
92630 27428,27429,27430,27431,27432,27433,27434,27435,27436,27437,27438,27439,
92631 27440,27441,27442,27443,27444,27445,27446,27447,27448,27449,27450,27451,
92632 27452,27453,27454,27455,27456,27457,27458,27459,27460,27461,27462,27463,
92633 27464,27465,27466,27467,27468,27469,27470,27471,27472,27473,27474,27475,
92634 27476,27477,27478,27479,27480,27481,27482,27483,27484,27485,27486,27487,
92635 27488,27489,27490,27491,27492,27493,27494,27495,27496,27497,27498,27499,
92636 27500,27501,27502,27503,27504,27505,27506,27507,27508,27509,27510,27511,
92637 27512,27513,27514,27515,27516,27517,27518,27519,27520,27521,27522,27523,
92638 27524,27525,27526,27527,27528,27529,27530,27531,27532,27533,27534,27535,
92639 27536,27537,27538,27539,27540,27541,27542,27543,27544,27545,27546,27547,
92640 27548,27549,27550,27551,27552,27553,27554,27555,27556,27557,27558,27559,
92641 27560,27561,27562,27563,27564,27565,27566,27567,27568,27569,27570,27571,
92642 27572,27573,27574,27575,27576,27577,27578,27579,27580,27581,27582,27583,
92643 27584,27585,27586,27587,27588,27589,27590,27591,27592,27593,27594,27595,
92644 27596,27597,27598,27599,27600,27601,27602,27603,27604,27605,27606,27607,
92645 27608,27609,27610,27611,27612,27613,27614,27615,27616,27617,27618,27619,
92646 27620,27621,27622,27623,27624,27625,27626,27627,27628,27629,27630,27631,
92647 27632,27633,27634,27635,27636,27637,27638,27639,27640,27641,27642,27643,
92648 27644,27645,27646,27647,27648,27649,27650,27651,27652,27653,27654,27655,
92649 27656,27657,27658,27659,27660,27661,27662,27663,27664,27665,27666,27667,
92650 27668,27669,27670,27671,27672,27673,27674,27675,27676,27677,27678,27679,
92651 27680,27681,27682,27683,27684,27685,27686,27687,27688,27689,27690,27691,
92652 27692,27693,27694,27695,27696,27697,27698,27699,27700,27701,27702,27703,
92653 27704,27705,27706,27707,27708,27709,27710,27711,27712,27713,27714,27715,
92654 27716,27717,27718,27719,27720,27721,27722,27723,27724,27725,27726,27727,
92655 27728,27729,27730,27731,27732,27733,27734,27735,27736,27737,27738,27739,
92656 27740,27741,27742,27743,27744,27745,27746,27747,27748,27749,27750,27751,
92657 27752,27753,27754,27755,27756,27757,27758,27759,27760,27761,27762,27763,
92658 27764,27765,27766,27767,27768,27769,27770,27771,27772,27773,27774,27775,
92659 27776,27777,27778,27779,27780,27781,27782,27783,27784,27785,27786,27787,
92660 27788,27789,27790,27791,27792,27793,27794,27795,27796,27797,27798,27799,
92661 27800,27801,27802,27803,27804,27805,27806,27807,27808,27809,27810,27811,
92662 27812,27813,27814,27815,27816,27817,27818,27819,27820,27821,27822,27823,
92663 27824,27825,27826,27827,27828,27829,27830,27831,27832,27833,27834,27835,
92664 27836,27837,27838,27839,27840,27841,27842,27843,27844,27845,27846,27847,
92665 27848,27849,27850,27851,27852,27853,27854,27855,27856,27857,27858,27859,
92666 27860,27861,27862,27863,27864,27865,27866,27867,27868,27869,27870,27871,
92667 27872,27873,27874,27875,27876,27877,27878,27879,27880,27881,27882,27883,
92668 27884,27885,27886,27887,27888,27889,27890,27891,27892,27893,27894,27895,
92669 27896,27897,27898,27899,27900,27901,27902,27903,27904,27905,27906,27907,
92670 27908,27909,27910,27911,27912,27913,27914,27915,27916,27917,27918,27919,
92671 27920,27921,27922,27923,27924,27925,27926,27927,27928,27929,27930,27931,
92672 27932,27933,27934,27935,27936,27937,27938,27939,27940,27941,27942,27943,
92673 27944,27945,27946,27947,27948,27949,27950,27951,27952,27953,27954,27955,
92674 27956,27957,27958,27959,27960,27961,27962,27963,27964,27965,27966,27967,
92675 27968,27969,27970,27971,27972,27973,27974,27975,27976,27977,27978,27979,
92676 27980,27981,27982,27983,27984,27985,27986,27987,27988,27989,27990,27991,
92677 27992,27993,27994,27995,27996,27997,27998,27999,28000,28001,28002,28003,
92678 28004,28005,28006,28007,28008,28009,28010,28011,28012,28013,28014,28015,
92679 28016,28017,28018,28019,28020,28021,28022,28023,28024,28025,28026,28027,
92680 28028,28029,28030,28031,28032,28033,28034,28035,28036,28037,28038,28039,
92681 28040,28041,28042,28043,28044,28045,28046,28047,28048,28049,28050,28051,
92682 28052,28053,28054,28055,28056,28057,28058,28059,28060,28061,28062,28063,
92683 28064,28065,28066,28067,28068,28069,28070,28071,28072,28073,28074,28075,
92684 28076,28077,28078,28079,28080,28081,28082,28083,28084,28085,28086,28087,
92685 28088,28089,28090,28091,28092,28093,28094,28095,28096,28097,28098,28099,
92686 28100,28101,28102,28103,28104,28105,28106,28107,28108,28109,28110,28111,
92687 28112,28113,28114,28115,28116,28117,28118,28119,28120,28121,28122,28123,
92688 28124,28125,28126,28127,28128,28129,28130,28131,28132,28133,28134,28135,
92689 28136,28137,28138,28139,28140,28141,28142,28143,28144,28145,28146,28147,
92690 28148,28149,28150,28151,28152,28153,28154,28155,28156,28157,28158,28159,
92691 28160,28161,28162,28163,28164,28165,28166,28167,28168,28169,28170,28171,
92692 28172,28173,28174,28175,28176,28177,28178,28179,28180,28181,28182,28183,
92693 28184,28185,28186,28187,28188,28189,28190,28191,28192,28193,28194,28195,
92694 28196,28197,28198,28199,28200,28201,28202,28203,28204,28205,28206,28207,
92695 28208,28209,28210,28211,28212,28213,28214,28215,28216,28217,28218,28219,
92696 28220,28221,28222,28223,28224,28225,28226,28227,28228,28229,28230,28231,
92697 28232,28233,28234,28235,28236,28237,28238,28239,28240,28241,28242,28243,
92698 28244,28245,28246,28247,28248,28249,28250,28251,28252,28253,28254,28255,
92699 28256,28257,28258,28259,28260,28261,28262,28263,28264,28265,28266,28267,
92700 28268,28269,28270,28271,28272,28273,28274,28275,28276,28277,28278,28279,
92701 28280,28281,28282,28283,28284,28285,28286,28287,28288,28289,28290,28291,
92702 28292,28293,28294,28295,28296,28297,28298,28299,28300,28301,28302,28303,
92703 28304,28305,28306,28307,28308,28309,28310,28311,28312,28313,28314,28315,
92704 28316,28317,28318,28319,28320,28321,28322,28323,28324,28325,28326,28327,
92705 28328,28329,28330,28331,28332,28333,28334,28335,28336,28337,28338,28339,
92706 28340,28341,28342,28343,28344,28345,28346,28347,28348,28349,28350,28351,
92707 28352,28353,28354,28355,28356,28357,28358,28359,28360,28361,28362,28363,
92708 28364,28365,28366,28367,28368,28369,28370,28371,28372,28373,28374,28375,
92709 28376,28377,28378,28379,28380,28381,28382,28383,28384,28385,28386,28387,
92710 28388,28389,28390,28391,28392,28393,28394,28395,28396,28397,28398,28399,
92711 28400,28401,28402,28403,28404,28405,28406,28407,28408,28409,28410,28411,
92712 28412,28413,28414,28415,28416,28417,28418,28419,28420,28421,28422,28423,
92713 28424,28425,28426,28427,28428,28429,28430,28431,28432,28433,28434,28435,
92714 28436,28437,28438,28439,28440,28441,28442,28443,28444,28445,28446,28447,
92715 28448,28449,28450,28451,28452,28453,28454,28455,28456,28457,28458,28459,
92716 28460,28461,28462,28463,28464,28465,28466,28467,28468,28469,28470,28471,
92717 28472,28473,28474,28475,28476,28477,28478,28479,28480,28481,28482,28483,
92718 28484,28485,28486,28487,28488,28489,28490,28491,28492,28493,28494,28495,
92719 28496,28497,28498,28499,28500,28501,28502,28503,28504,28505,28506,28507,
92720 28508,28509,28510,28511,28512,28513,28514,28515,28516,28517,28518,28519,
92721 28520,28521,28522,28523,28524,28525,28526,28527,28528,28529,28530,28531,
92722 28532,28533,28534,28535,28536,28537,28538,28539,28540,28541,28542,28543,
92723 28544,28545,28546,28547,28548,28549,28550,28551,28552,28553,28554,28555,
92724 28556,28557,28558,28559,28560,28561,28562,28563,28564,28565,28566,28567,
92725 28568,28569,28570,28571,28572,28573,28574,28575,28576,28577,28578,28579,
92726 28580,28581,28582,28583,28584,28585,28586,28587,28588,28589,28590,28591,
92727 28592,28593,28594,28595,28596,28597,28598,28599,28600,28601,28602,28603,
92728 28604,28605,28606,28607,28608,28609,28610,28611,28612,28613,28614,28615,
92729 28616,28617,28618,28619,28620,28621,28622,28623,28624,28625,28626,28627,
92730 28628,28629,28630,28631,28632,28633,28634,28635,28636,28637,28638,28639,
92731 28640,28641,28642,28643,28644,28645,28646,28647,28648,28649,28650,28651,
92732 28652,28653,28654,28655,28656,28657,28658,28659,28660,28661,28662,28663,
92733 28664,28665,28666,28667,28668,28669,28670,28671,28672,28673,28674,28675,
92734 28676,28677,28678,28679,28680,28681,28682,28683,28684,28685,28686,28687,
92735 28688,28689,28690,28691,28692,28693,28694,28695,28696,28697,28698,28699,
92736 28700,28701,28702,28703,28704,28705,28706,28707,28708,28709,28710,28711,
92737 28712,28713,28714,28715,28716,28717,28718,28719,28720,28721,28722,28723,
92738 28724,28725,28726,28727,28728,28729,28730,28731,28732,28733,28734,28735,
92739 28736,28737,28738,28739,28740,28741,28742,28743,28744,28745,28746,28747,
92740 28748,28749,28750,28751,28752,28753,28754,28755,28756,28757,28758,28759,
92741 28760,28761,28762,28763,28764,28765,28766,28767,28768,28769,28770,28771,
92742 28772,28773,28774,28775,28776,28777,28778,28779,28780,28781,28782,28783,
92743 28784,28785,28786,28787,28788,28789,28790,28791,28792,28793,28794,28795,
92744 28796,28797,28798,28799,28800,28801,28802,28803,28804,28805,28806,28807,
92745 28808,28809,28810,28811,28812,28813,28814,28815,28816,28817,28818,28819,
92746 28820,28821,28822,28823,28824,28825,28826,28827,28828,28829,28830,28831,
92747 28832,28833,28834,28835,28836,28837,28838,28839,28840,28841,28842,28843,
92748 28844,28845,28846,28847,28848,28849,28850,28851,28852,28853,28854,28855,
92749 28856,28857,28858,28859,28860,28861,28862,28863,28864,28865,28866,28867,
92750 28868,28869,28870,28871,28872,28873,28874,28875,28876,28877,28878,28879,
92751 28880,28881,28882,28883,28884,28885,28886,28887,28888,28889,28890,28891,
92752 28892,28893,28894,28895,28896,28897,28898,28899,28900,28901,28902,28903,
92753 28904,28905,28906,28907,28908,28909,28910,28911,28912,28913,28914,28915,
92754 28916,28917,28918,28919,28920,28921,28922,28923,28924,28925,28926,28927,
92755 28928,28929,28930,28931,28932,28933,28934,28935,28936,28937,28938,28939,
92756 28940,28941,28942,28943,28944,28945,28946,28947,28948,28949,28950,28951,
92757 28952,28953,28954,28955,28956,28957,28958,28959,28960,28961,28962,28963,
92758 28964,28965,28966,28967,28968,28969,28970,28971,28972,28973,28974,28975,
92759 28976,28977,28978,28979,28980,28981,28982,28983,28984,28985,28986,28987,
92760 28988,28989,28990,28991,28992,28993,28994,28995,28996,28997,28998,28999,
92761 29000,29001,29002,29003,29004,29005,29006,29007,29008,29009,29010,29011,
92762 29012,29013,29014,29015,29016,29017,29018,29019,29020,29021,29022,29023,
92763 29024,29025,29026,29027,29028,29029,29030,29031,29032,29033,29034,29035,
92764 29036,29037,29038,29039,29040,29041,29042,29043,29044,29045,29046,29047,
92765 29048,29049,29050,29051,29052,29053,29054,29055,29056,29057,29058,29059,
92766 29060,29061,29062,29063,29064,29065,29066,29067,29068,29069,29070,29071,
92767 29072,29073,29074,29075,29076,29077,29078,29079,29080,29081,29082,29083,
92768 29084,29085,29086,29087,29088,29089,29090,29091,29092,29093,29094,29095,
92769 29096,29097,29098,29099,29100,29101,29102,29103,29104,29105,29106,29107,
92770 29108,29109,29110,29111,29112,29113,29114,29115,29116,29117,29118,29119,
92771 29120,29121,29122,29123,29124,29125,29126,29127,29128,29129,29130,29131,
92772 29132,29133,29134,29135,29136,29137,29138,29139,29140,29141,29142,29143,
92773 29144,29145,29146,29147,29148,29149,29150,29151,29152,29153,29154,29155,
92774 29156,29157,29158,29159,29160,29161,29162,29163,29164,29165,29166,29167,
92775 29168,29169,29170,29171,29172,29173,29174,29175,29176,29177,29178,29179,
92776 29180,29181,29182,29183,29184,29185,29186,29187,29188,29189,29190,29191,
92777 29192,29193,29194,29195,29196,29197,29198,29199,29200,29201,29202,29203,
92778 29204,29205,29206,29207,29208,29209,29210,29211,29212,29213,29214,29215,
92779 29216,29217,29218,29219,29220,29221,29222,29223,29224,29225,29226,29227,
92780 29228,29229,29230,29231,29232,29233,29234,29235,29236,29237,29238,29239,
92781 29240,29241,29242,29243,29244,29245,29246,29247,29248,29249,29250,29251,
92782 29252,29253,29254,29255,29256,29257,29258,29259,29260,29261,29262,29263,
92783 29264,29265,29266,29267,29268,29269,29270,29271,29272,29273,29274,29275,
92784 29276,29277,29278,29279,29280,29281,29282,29283,29284,29285,29286,29287,
92785 29288,29289,29290,29291,29292,29293,29294,29295,29296,29297,29298,29299,
92786 29300,29301,29302,29303,29304,29305,29306,29307,29308,29309,29310,29311,
92787 29312,29313,29314,29315,29316,29317,29318,29319,29320,29321,29322,29323,
92788 29324,29325,29326,29327,29328,29329,29330,29331,29332,29333,29334,29335,
92789 29336,29337,29338,29339,29340,29341,29342,29343,29344,29345,29346,29347,
92790 29348,29349,29350,29351,29352,29353,29354,29355,29356,29357,29358,29359,
92791 29360,29361,29362,29363,29364,29365,29366,29367,29368,29369,29370,29371,
92792 29372,29373,29374,29375,29376,29377,29378,29379,29380,29381,29382,29383,
92793 29384,29385,29386,29387,29388,29389,29390,29391,29392,29393,29394,29395,
92794 29396,29397,29398,29399,29400,29401,29402,29403,29404,29405,29406,29407,
92795 29408,29409,29410,29411,29412,29413,29414,29415,29416,29417,29418,29419,
92796 29420,29421,29422,29423,29424,29425,29426,29427,29428,29429,29430,29431,
92797 29432,29433,29434,29435,29436,29437,29438,29439,29440,29441,29442,29443,
92798 29444,29445,29446,29447,29448,29449,29450,29451,29452,29453,29454,29455,
92799 29456,29457,29458,29459,29460,29461,29462,29463,29464,29465,29466,29467,
92800 29468,29469,29470,29471,29472,29473,29474,29475,29476,29477,29478,29479,
92801 29480,29481,29482,29483,29484,29485,29486,29487,29488,29489,29490,29491,
92802 29492,29493,29494,29495,29496,29497,29498,29499,29500,29501,29502,29503,
92803 29504,29505,29506,29507,29508,29509,29510,29511,29512,29513,29514,29515,
92804 29516,29517,29518,29519,29520,29521,29522,29523,29524,29525,29526,29527,
92805 29528,29529,29530,29531,29532,29533,29534,29535,29536,29537,29538,29539,
92806 29540,29541,29542,29543,29544,29545,29546,29547,29548,29549,29550,29551,
92807 29552,29553,29554,29555,29556,29557,29558,29559,29560,29561,29562,29563,
92808 29564,29565,29566,29567,29568,29569,29570,29571,29572,29573,29574,29575,
92809 29576,29577,29578,29579,29580,29581,29582,29583,29584,29585,29586,29587,
92810 29588,29589,29590,29591,29592,29593,29594,29595,29596,29597,29598,29599,
92811 29600,29601,29602,29603,29604,29605,29606,29607,29608,29609,29610,29611,
92812 29612,29613,29614,29615,29616,29617,29618,29619,29620,29621,29622,29623,
92813 29624,29625,29626,29627,29628,29629,29630,29631,29632,29633,29634,29635,
92814 29636,29637,29638,29639,29640,29641,29642,29643,29644,29645,29646,29647,
92815 29648,29649,29650,29651,29652,29653,29654,29655,29656,29657,29658,29659,
92816 29660,29661,29662,29663,29664,29665,29666,29667,29668,29669,29670,29671,
92817 29672,29673,29674,29675,29676,29677,29678,29679,29680,29681,29682,29683,
92818 29684,29685,29686,29687,29688,29689,29690,29691,29692,29693,29694,29695,
92819 29696,29697,29698,29699,29700,29701,29702,29703,29704,29705,29706,29707,
92820 29708,29709,29710,29711,29712,29713,29714,29715,29716,29717,29718,29719,
92821 29720,29721,29722,29723,29724,29725,29726,29727,29728,29729,29730,29731,
92822 29732,29733,29734,29735,29736,29737,29738,29739,29740,29741,29742,29743,
92823 29744,29745,29746,29747,29748,29749,29750,29751,29752,29753,29754,29755,
92824 29756,29757,29758,29759,29760,29761,29762,29763,29764,29765,29766,29767,
92825 29768,29769,29770,29771,29772,29773,29774,29775,29776,29777,29778,29779,
92826 29780,29781,29782,29783,29784,29785,29786,29787,29788,29789,29790,29791,
92827 29792,29793,29794,29795,29796,29797,29798,29799,29800,29801,29802,29803,
92828 29804,29805,29806,29807,29808,29809,29810,29811,29812,29813,29814,29815,
92829 29816,29817,29818,29819,29820,29821,29822,29823,29824,29825,29826,29827,
92830 29828,29829,29830,29831,29832,29833,29834,29835,29836,29837,29838,29839,
92831 29840,29841,29842,29843,29844,29845,29846,29847,29848,29849,29850,29851,
92832 29852,29853,29854,29855,29856,29857,29858,29859,29860,29861,29862,29863,
92833 29864,29865,29866,29867,29868,29869,29870,29871,29872,29873,29874,29875,
92834 29876,29877,29878,29879,29880,29881,29882,29883,29884,29885,29886,29887,
92835 29888,29889,29890,29891,29892,29893,29894,29895,29896,29897,29898,29899,
92836 29900,29901,29902,29903,29904,29905,29906,29907,29908,29909,29910,29911,
92837 29912,29913,29914,29915,29916,29917,29918,29919,29920,29921,29922,29923,
92838 29924,29925,29926,29927,29928,29929,29930,29931,29932,29933,29934,29935,
92839 29936,29937,29938,29939,29940,29941,29942,29943,29944,29945,29946,29947,
92840 29948,29949,29950,29951,29952,29953,29954,29955,29956,29957,29958,29959,
92841 29960,29961,29962,29963,29964,29965,29966,29967,29968,29969,29970,29971,
92842 29972,29973,29974,29975,29976,29977,29978,29979,29980,29981,29982,29983,
92843 29984,29985,29986,29987,29988,29989,29990,29991,29992,29993,29994,29995,
92844 29996,29997,29998,29999,30000,30001,30002,30003,30004,30005,30006,30007,
92845 30008,30009,30010,30011,30012,30013,30014,30015,30016,30017,30018,30019,
92846 30020,30021,30022,30023,30024,30025,30026,30027,30028,30029,30030,30031,
92847 30032,30033,30034,30035,30036,30037,30038,30039,30040,30041,30042,30043,
92848 30044,30045,30046,30047,30048,30049,30050,30051,30052,30053,30054,30055,
92849 30056,30057,30058,30059,30060,30061,30062,30063,30064,30065,30066,30067,
92850 30068,30069,30070,30071,30072,30073,30074,30075,30076,30077,30078,30079,
92851 30080,30081,30082,30083,30084,30085,30086,30087,30088,30089,30090,30091,
92852 30092,30093,30094,30095,30096,30097,30098,30099,30100,30101,30102,30103,
92853 30104,30105,30106,30107,30108,30109,30110,30111,30112,30113,30114,30115,
92854 30116,30117,30118,30119,30120,30121,30122,30123,30124,30125,30126,30127,
92855 30128,30129,30130,30131,30132,30133,30134,30135,30136,30137,30138,30139,
92856 30140,30141,30142,30143,30144,30145,30146,30147,30148,30149,30150,30151,
92857 30152,30153,30154,30155,30156,30157,30158,30159,30160,30161,30162,30163,
92858 30164,30165,30166,30167,30168,30169,30170,30171,30172,30173,30174,30175,
92859 30176,30177,30178,30179,30180,30181,30182,30183,30184,30185,30186,30187,
92860 30188,30189,30190,30191,30192,30193,30194,30195,30196,30197,30198,30199,
92861 30200,30201,30202,30203,30204,30205,30206,30207,30208,30209,30210,30211,
92862 30212,30213,30214,30215,30216,30217,30218,30219,30220,30221,30222,30223,
92863 30224,30225,30226,30227,30228,30229,30230,30231,30232,30233,30234,30235,
92864 30236,30237,30238,30239,30240,30241,30242,30243,30244,30245,30246,30247,
92865 30248,30249,30250,30251,30252,30253,30254,30255,30256,30257,30258,30259,
92866 30260,30261,30262,30263,30264,30265,30266,30267,30268,30269,30270,30271,
92867 30272,30273,30274,30275,30276,30277,30278,30279,30280,30281,30282,30283,
92868 30284,30285,30286,30287,30288,30289,30290,30291,30292,30293,30294,30295,
92869 30296,30297,30298,30299,30300,30301,30302,30303,30304,30305,30306,30307,
92870 30308,30309,30310,30311,30312,30313,30314,30315,30316,30317,30318,30319,
92871 30320,30321,30322,30323,30324,30325,30326,30327,30328,30329,30330,30331,
92872 30332,30333,30334,30335,30336,30337,30338,30339,30340,30341,30342,30343,
92873 30344,30345,30346,30347,30348,30349,30350,30351,30352,30353,30354,30355,
92874 30356,30357,30358,30359,30360,30361,30362,30363,30364,30365,30366,30367,
92875 30368,30369,30370,30371,30372,30373,30374,30375,30376,30377,30378,30379,
92876 30380,30381,30382,30383,30384,30385,30386,30387,30388,30389,30390,30391,
92877 30392,30393,30394,30395,30396,30397,30398,30399,30400,30401,30402,30403,
92878 30404,30405,30406,30407,30408,30409,30410,30411,30412,30413,30414,30415,
92879 30416,30417,30418,30419,30420,30421,30422,30423,30424,30425,30426,30427,
92880 30428,30429,30430,30431,30432,30433,30434,30435,30436,30437,30438,30439,
92881 30440,30441,30442,30443,30444,30445,30446,30447,30448,30449,30450,30451,
92882 30452,30453,30454,30455,30456,30457,30458,30459,30460,30461,30462,30463,
92883 30464,30465,30466,30467,30468,30469,30470,30471,30472,30473,30474,30475,
92884 30476,30477,30478,30479,30480,30481,30482,30483,30484,30485,30486,30487,
92885 30488,30489,30490,30491,30492,30493,30494,30495,30496,30497,30498,30499,
92886 30500,30501,30502,30503,30504,30505,30506,30507,30508,30509,30510,30511,
92887 30512,30513,30514,30515,30516,30517,30518,30519,30520,30521,30522,30523,
92888 30524,30525,30526,30527,30528,30529,30530,30531,30532,30533,30534,30535,
92889 30536,30537,30538,30539,30540,30541,30542,30543,30544,30545,30546,30547,
92890 30548,30549,30550,30551,30552,30553,30554,30555,30556,30557,30558,30559,
92891 30560,30561,30562,30563,30564,30565,30566,30567,30568,30569,30570,30571,
92892 30572,30573,30574,30575,30576,30577,30578,30579,30580,30581,30582,30583,
92893 30584,30585,30586,30587,30588,30589,30590,30591,30592,30593,30594,30595,
92894 30596,30597,30598,30599,30600,30601,30602,30603,30604,30605,30606,30607,
92895 30608,30609,30610,30611,30612,30613,30614,30615,30616,30617,30618,30619,
92896 30620,30621,30622,30623,30624,30625,30626,30627,30628,30629,30630,30631,
92897 30632,30633,30634,30635,30636,30637,30638,30639,30640,30641,30642,30643,
92898 30644,30645,30646,30647,30648,30649,30650,30651,30652,30653,30654,30655,
92899 30656,30657,30658,30659,30660,30661,30662,30663,30664,30665,30666,30667,
92900 30668,30669,30670,30671,30672,30673,30674,30675,30676,30677,30678,30679,
92901 30680,30681,30682,30683,30684,30685,30686,30687,30688,30689,30690,30691,
92902 30692,30693,30694,30695,30696,30697,30698,30699,30700,30701,30702,30703,
92903 30704,30705,30706,30707,30708,30709,30710,30711,30712,30713,30714,30715,
92904 30716,30717,30718,30719,30720,30721,30722,30723,30724,30725,30726,30727,
92905 30728,30729,30730,30731,30732,30733,30734,30735,30736,30737,30738,30739,
92906 30740,30741,30742,30743,30744,30745,30746,30747,30748,30749,30750,30751,
92907 30752,30753,30754,30755,30756,30757,30758,30759,30760,30761,30762,30763,
92908 30764,30765,30766,30767,30768,30769,30770,30771,30772,30773,30774,30775,
92909 30776,30777,30778,30779,30780,30781,30782,30783,30784,30785,30786,30787,
92910 30788,30789,30790,30791,30792,30793,30794,30795,30796,30797,30798,30799,
92911 30800,30801,30802,30803,30804,30805,30806,30807,30808,30809,30810,30811,
92912 30812,30813,30814,30815,30816,30817,30818,30819,30820,30821,30822,30823,
92913 30824,30825,30826,30827,30828,30829,30830,30831,30832,30833,30834,30835,
92914 30836,30837,30838,30839,30840,30841,30842,30843,30844,30845,30846,30847,
92915 30848,30849,30850,30851,30852,30853,30854,30855,30856,30857,30858,30859,
92916 30860,30861,30862,30863,30864,30865,30866,30867,30868,30869,30870,30871,
92917 30872,30873,30874,30875,30876,30877,30878,30879,30880,30881,30882,30883,
92918 30884,30885,30886,30887,30888,30889,30890,30891,30892,30893,30894,30895,
92919 30896,30897,30898,30899,30900,30901,30902,30903,30904,30905,30906,30907,
92920 30908,30909,30910,30911,30912,30913,30914,30915,30916,30917,30918,30919,
92921 30920,30921,30922,30923,30924,30925,30926,30927,30928,30929,30930,30931,
92922 30932,30933,30934,30935,30936,30937,30938,30939,30940,30941,30942,30943,
92923 30944,30945,30946,30947,30948,30949,30950,30951,30952,30953,30954,30955,
92924 30956,30957,30958,30959,30960,30961,30962,30963,30964,30965,30966,30967,
92925 30968,30969,30970,30971,30972,30973,30974,30975,30976,30977,30978,30979,
92926 30980,30981,30982,30983,30984,30985,30986,30987,30988,30989,30990,30991,
92927 30992,30993,30994,30995,30996,30997,30998,30999,31000,31001,31002,31003,
92928 31004,31005,31006,31007,31008,31009,31010,31011,31012,31013,31014,31015,
92929 31016,31017,31018,31019,31020,31021,31022,31023,31024,31025,31026,31027,
92930 31028,31029,31030,31031,31032,31033,31034,31035,31036,31037,31038,31039,
92931 31040,31041,31042,31043,31044,31045,31046,31047,31048,31049,31050,31051,
92932 31052,31053,31054,31055,31056,31057,31058,31059,31060,31061,31062,31063,
92933 31064,31065,31066,31067,31068,31069,31070,31071,31072,31073,31074,31075,
92934 31076,31077,31078,31079,31080,31081,31082,31083,31084,31085,31086,31087,
92935 31088,31089,31090,31091,31092,31093,31094,31095,31096,31097,31098,31099,
92936 31100,31101,31102,31103,31104,31105,31106,31107,31108,31109,31110,31111,
92937 31112,31113,31114,31115,31116,31117,31118,31119,31120,31121,31122,31123,
92938 31124,31125,31126,31127,31128,31129,31130,31131,31132,31133,31134,31135,
92939 31136,31137,31138,31139,31140,31141,31142,31143,31144,31145,31146,31147,
92940 31148,31149,31150,31151,31152,31153,31154,31155,31156,31157,31158,31159,
92941 31160,31161,31162,31163,31164,31165,31166,31167,31168,31169,31170,31171,
92942 31172,31173,31174,31175,31176,31177,31178,31179,31180,31181,31182,31183,
92943 31184,31185,31186,31187,31188,31189,31190,31191,31192,31193,31194,31195,
92944 31196,31197,31198,31199,31200,31201,31202,31203,31204,31205,31206,31207,
92945 31208,31209,31210,31211,31212,31213,31214,31215,31216,31217,31218,31219,
92946 31220,31221,31222,31223,31224,31225,31226,31227,31228,31229,31230,31231,
92947 31232,31233,31234,31235,31236,31237,31238,31239,31240,31241,31242,31243,
92948 31244,31245,31246,31247,31248,31249,31250,31251,31252,31253,31254,31255,
92949 31256,31257,31258,31259,31260,31261,31262,31263,31264,31265,31266,31267,
92950 31268,31269,31270,31271,31272,31273,31274,31275,31276,31277,31278,31279,
92951 31280,31281,31282,31283,31284,31285,31286,31287,31288,31289,31290,31291,
92952 31292,31293,31294,31295,31296,31297,31298,31299,31300,31301,31302,31303,
92953 31304,31305,31306,31307,31308,31309,31310,31311,31312,31313,31314,31315,
92954 31316,31317,31318,31319,31320,31321,31322,31323,31324,31325,31326,31327,
92955 31328,31329,31330,31331,31332,31333,31334,31335,31336,31337,31338,31339,
92956 31340,31341,31342,31343,31344,31345,31346,31347,31348,31349,31350,31351,
92957 31352,31353,31354,31355,31356,31357,31358,31359,31360,31361,31362,31363,
92958 31364,31365,31366,31367,31368,31369,31370,31371,31372,31373,31374,31375,
92959 31376,31377,31378,31379,31380,31381,31382,31383,31384,31385,31386,31387,
92960 31388,31389,31390,31391,31392,31393,31394,31395,31396,31397,31398,31399,
92961 31400,31401,31402,31403,31404,31405,31406,31407,31408,31409,31410,31411,
92962 31412,31413,31414,31415,31416,31417,31418,31419,31420,31421,31422,31423,
92963 31424,31425,31426,31427,31428,31429,31430,31431,31432,31433,31434,31435,
92964 31436,31437,31438,31439,31440,31441,31442,31443,31444,31445,31446,31447,
92965 31448,31449,31450,31451,31452,31453,31454,31455,31456,31457,31458,31459,
92966 31460,31461,31462,31463,31464,31465,31466,31467,31468,31469,31470,31471,
92967 31472,31473,31474,31475,31476,31477,31478,31479,31480,31481,31482,31483,
92968 31484,31485,31486,31487,31488,31489,31490,31491,31492,31493,31494,31495,
92969 31496,31497,31498,31499,31500,31501,31502,31503,31504,31505,31506,31507,
92970 31508,31509,31510,31511,31512,31513,31514,31515,31516,31517,31518,31519,
92971 31520,31521,31522,31523,31524,31525,31526,31527,31528,31529,31530,31531,
92972 31532,31533,31534,31535,31536,31537,31538,31539,31540,31541,31542,31543,
92973 31544,31545,31546,31547,31548,31549,31550,31551,31552,31553,31554,31555,
92974 31556,31557,31558,31559,31560,31561,31562,31563,31564,31565,31566,31567,
92975 31568,31569,31570,31571,31572,31573,31574,31575,31576,31577,31578,31579,
92976 31580,31581,31582,31583,31584,31585,31586,31587,31588,31589,31590,31591,
92977 31592,31593,31594,31595,31596,31597,31598,31599,31600,31601,31602,31603,
92978 31604,31605,31606,31607,31608,31609,31610,31611,31612,31613,31614,31615,
92979 31616,31617,31618,31619,31620,31621,31622,31623,31624,31625,31626,31627,
92980 31628,31629,31630,31631,31632,31633,31634,31635,31636,31637,31638,31639,
92981 31640,31641,31642,31643,31644,31645,31646,31647,31648,31649,31650,31651,
92982 31652,31653,31654,31655,31656,31657,31658,31659,31660,31661,31662,31663,
92983 31664,31665,31666,31667,31668,31669,31670,31671,31672,31673,31674,31675,
92984 31676,31677,31678,31679,31680,31681,31682,31683,31684,31685,31686,31687,
92985 31688,31689,31690,31691,31692,31693,31694,31695,31696,31697,31698,31699,
92986 31700,31701,31702,31703,31704,31705,31706,31707,31708,31709,31710,31711,
92987 31712,31713,31714,31715,31716,31717,31718,31719,31720,31721,31722,31723,
92988 31724,31725,31726,31727,31728,31729,31730,31731,31732,31733,31734,31735,
92989 31736,31737,31738,31739,31740,31741,31742,31743,31744,31745,31746,31747,
92990 31748,31749,31750,31751,31752,31753,31754,31755,31756,31757,31758,31759,
92991 31760,31761,31762,31763,31764,31765,31766,31767,31768,31769,31770,31771,
92992 31772,31773,31774,31775,31776,31777,31778,31779,31780,31781,31782,31783,
92993 31784,31785,31786,31787,31788,31789,31790,31791,31792,31793,31794,31795,
92994 31796,31797,31798,31799,31800,31801,31802,31803,31804,31805,31806,31807,
92995 31808,31809,31810,31811,31812,31813,31814,31815,31816,31817,31818,31819,
92996 31820,31821,31822,31823,31824,31825,31826,31827,31828,31829,31830,31831,
92997 31832,31833,31834,31835,31836,31837,31838,31839,31840,31841,31842,31843,
92998 31844,31845,31846,31847,31848,31849,31850,31851,31852,31853,31854,31855,
92999 31856,31857,31858,31859,31860,31861,31862,31863,31864,31865,31866,31867,
93000 31868,31869,31870,31871,31872,31873,31874,31875,31876,31877,31878,31879,
93001 31880,31881,31882,31883,31884,31885,31886,31887,31888,31889,31890,31891,
93002 31892,31893,31894,31895,31896,31897,31898,31899,31900,31901,31902,31903,
93003 31904,31905,31906,31907,31908,31909,31910,31911,31912,31913,31914,31915,
93004 31916,31917,31918,31919,31920,31921,31922,31923,31924,31925,31926,31927,
93005 31928,31929,31930,31931,31932,31933,31934,31935,31936,31937,31938,31939,
93006 31940,31941,31942,31943,31944,31945,31946,31947,31948,31949,31950,31951,
93007 31952,31953,31954,31955,31956,31957,31958,31959,31960,31961,31962,31963,
93008 31964,31965,31966,31967,31968,31969,31970,31971,31972,31973,31974,31975,
93009 31976,31977,31978,31979,31980,31981,31982,31983,31984,31985,31986,31987,
93010 31988,31989,31990,31991,31992,31993,31994,31995,31996,31997,31998,31999,
93011 32000,32001,32002,32003,32004,32005,32006,32007,32008,32009,32010,32011,
93012 32012,32013,32014,32015,32016,32017,32018,32019,32020,32021,32022,32023,
93013 32024,32025,32026,32027,32028,32029,32030,32031,32032,32033,32034,32035,
93014 32036,32037,32038,32039,32040,32041,32042,32043,32044,32045,32046,32047,
93015 32048,32049,32050,32051,32052,32053,32054,32055,32056,32057,32058,32059,
93016 32060,32061,32062,32063,32064,32065,32066,32067,32068,32069,32070,32071,
93017 32072,32073,32074,32075,32076,32077,32078,32079,32080,32081,32082,32083,
93018 32084,32085,32086,32087,32088,32089,32090,32091,32092,32093,32094,32095,
93019 32096,32097,32098,32099,32100,32101,32102,32103,32104,32105,32106,32107,
93020 32108,32109,32110,32111,32112,32113,32114,32115,32116,32117,32118,32119,
93021 32120,32121,32122,32123,32124,32125,32126,32127,32128,32129,32130,32131,
93022 32132,32133,32134,32135,32136,32137,32138,32139,32140,32141,32142,32143,
93023 32144,32145,32146,32147,32148,32149,32150,32151,32152,32153,32154,32155,
93024 32156,32157,32158,32159,32160,32161,32162,32163,32164,32165,32166,32167,
93025 32168,32169,32170,32171,32172,32173,32174,32175,32176,32177,32178,32179,
93026 32180,32181,32182,32183,32184,32185,32186,32187,32188,32189,32190,32191,
93027 32192,32193,32194,32195,32196,32197,32198,32199,32200,32201,32202,32203,
93028 32204,32205,32206,32207,32208,32209,32210,32211,32212,32213,32214,32215,
93029 32216,32217,32218,32219,32220,32221,32222,32223,32224,32225,32226,32227,
93030 32228,32229,32230,32231,32232,32233,32234,32235,32236,32237,32238,32239,
93031 32240,32241,32242,32243,32244,32245,32246,32247,32248,32249,32250,32251,
93032 32252,32253,32254,32255,32256,32257,32258,32259,32260,32261,32262,32263,
93033 32264,32265,32266,32267,32268,32269,32270,32271,32272,32273,32274,32275,
93034 32276,32277,32278,32279,32280,32281,32282,32283,32284,32285,32286,32287,
93035 32288,32289,32290,32291,32292,32293,32294,32295,32296,32297,32298,32299,
93036 32300,32301,32302,32303,32304,32305,32306,32307,32308,32309,32310,32311,
93037 32312,32313,32314,32315,32316,32317,32318,32319,32320,32321,32322,32323,
93038 32324,32325,32326,32327,32328,32329,32330,32331,32332,32333,32334,32335,
93039 32336,32337,32338,32339,32340,32341,32342,32343,32344,32345,32346,32347,
93040 32348,32349,32350,32351,32352,32353,32354,32355,32356,32357,32358,32359,
93041 32360,32361,32362,32363,32364,32365,32366,32367,32368,32369,32370,32371,
93042 32372,32373,32374,32375,32376,32377,32378,32379,32380,32381,32382,32383,
93043 32384,32385,32386,32387,32388,32389,32390,32391,32392,32393,32394,32395,
93044 32396,32397,32398,32399,32400,32401,32402,32403,32404,32405,32406,32407,
93045 32408,32409,32410,32411,32412,32413,32414,32415,32416,32417,32418,32419,
93046 32420,32421,32422,32423,32424,32425,32426,32427,32428,32429,32430,32431,
93047 32432,32433,32434,32435,32436,32437,32438,32439,32440,32441,32442,32443,
93048 32444,32445,32446,32447,32448,32449,32450,32451,32452,32453,32454,32455,
93049 32456,32457,32458,32459,32460,32461,32462,32463,32464,32465,32466,32467,
93050 32468,32469,32470,32471,32472,32473,32474,32475,32476,32477,32478,32479,
93051 32480,32481,32482,32483,32484,32485,32486,32487,32488,32489,32490,32491,
93052 32492,32493,32494,32495,32496,32497,32498,32499,32500,32501,32502,32503,
93053 32504,32505,32506,32507,32508,32509,32510,32511,32512,32513,32514,32515,
93054 32516,32517,32518,32519,32520,32521,32522,32523,32524,32525,32526,32527,
93055 32528,32529,32530,32531,32532,32533,32534,32535,32536,32537,32538,32539,
93056 32540,32541,32542,32543,32544,32545,32546,32547,32548,32549,32550,32551,
93057 32552,32553,32554,32555,32556,32557,32558,32559,32560,32561,32562,32563,
93058 32564,32565,32566,32567,32568,32569,32570,32571,32572,32573,32574,32575,
93059 32576,32577,32578,32579,32580,32581,32582,32583,32584,32585,32586,32587,
93060 32588,32589,32590,32591,32592,32593,32594,32595,32596,32597,32598,32599,
93061 32600,32601,32602,32603,32604,32605,32606,32607,32608,32609,32610,32611,
93062 32612,32613,32614,32615,32616,32617,32618,32619,32620,32621,32622,32623,
93063 32624,32625,32626,32627,32628,32629,32630,32631,32632,32633,32634,32635,
93064 32636,32637,32638,32639,32640,32641,32642,32643,32644,32645,32646,32647,
93065 32648,32649,32650,32651,32652,32653,32654,32655,32656,32657,32658,32659,
93066 32660,32661,32662,32663,32664,32665,32666,32667,32668,32669,32670,32671,
93067 32672,32673,32674,32675,32676,32677,32678,32679,32680,32681,32682,32683,
93068 32684,32685,32686,32687,32688,32689,32690,32691,32692,32693,32694,32695,
93069 32696,32697,32698,32699,32700,32701,32702,32703,32704,32705,32706,32707,
93070 32708,32709,32710,32711,32712,32713,32714,32715,32716,32717,32718,32719,
93071 32720,32721,32722,32723,32724,32725,32726,32727,32728,32729,32730,32731,
93072 32732,32733,32734,32735,32736,32737,32738,32739,32740,32741,32742,32743,
93073 32744,32745,32746,32747,32748,32749,32750,32751,32752,32753,32754,32755,
93074 32756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,
93075 32768L,32769L,32770L,32771L,32772L,32773L,32774L,32775L,32776L,32777L,
93076 32778L,32779L,32780L,32781L,32782L,32783L,32784L,32785L,32786L,32787L,
93077 32788L,32789L,32790L,32791L,32792L,32793L,32794L,32795L,32796L,32797L,
93078 32798L,32799L,32800L,32801L,32802L,32803L,32804L,32805L,32806L,32807L,
93079 32808L,32809L,32810L,32811L,32812L,32813L,32814L,32815L,32816L,32817L,
93080 32818L,32819L,32820L,32821L,32822L,32823L,32824L,32825L,32826L,32827L,
93081 32828L,32829L,32830L,32831L,32832L,32833L,32834L,32835L,32836L,32837L,
93082 32838L,32839L,32840L,32841L,32842L,32843L,32844L,32845L,32846L,32847L,
93083 32848L,32849L,32850L,32851L,32852L,32853L,32854L,32855L,32856L,32857L,
93084 32858L,32859L,32860L,32861L,32862L,32863L,32864L,32865L,32866L,32867L,
93085 32868L,32869L,32870L,32871L,32872L,32873L,32874L,32875L,32876L,32877L,
93086 32878L,32879L,32880L,32881L,32882L,32883L,32884L,32885L,32886L,32887L,
93087 32888L,32889L,32890L,32891L,32892L,32893L,32894L,32895L,32896L,32897L,
93088 32898L,32899L,32900L,32901L,32902L,32903L,32904L,32905L,32906L,32907L,
93089 32908L,32909L,32910L,32911L,32912L,32913L,32914L,32915L,32916L,32917L,
93090 32918L,32919L,32920L,32921L,32922L,32923L,32924L,32925L,32926L,32927L,
93091 32928L,32929L,32930L,32931L,32932L,32933L,32934L,32935L,32936L,32937L,
93092 32938L,32939L,32940L,32941L,32942L,32943L,32944L,32945L,32946L,32947L,
93093 32948L,32949L,32950L,32951L,32952L,32953L,32954L,32955L,32956L,32957L,
93094 32958L,32959L,32960L,32961L,32962L,32963L,32964L,32965L,32966L,32967L,
93095 32968L,32969L,32970L,32971L,32972L,32973L,32974L,32975L,32976L,32977L,
93096 32978L,32979L,32980L,32981L,32982L,32983L,32984L,32985L,32986L,32987L,
93097 32988L,32989L,32990L,32991L,32992L,32993L,32994L,32995L,32996L,32997L,
93098 32998L,32999L,33000L,33001L,33002L,33003L,33004L,33005L,33006L,33007L,
93099 33008L,33009L,33010L,33011L,33012L,33013L,33014L,33015L,33016L,33017L,
93100 33018L,33019L,33020L,33021L,33022L,33023L,33024L,33025L,33026L,33027L,
93101 33028L,33029L,33030L,33031L,33032L,33033L,33034L,33035L,33036L,33037L,
93102 33038L,33039L,33040L,33041L,33042L,33043L,33044L,33045L,33046L,33047L,
93103 33048L,33049L,33050L,33051L,33052L,33053L,33054L,33055L,33056L,33057L,
93104 33058L,33059L,33060L,33061L,33062L,33063L,33064L,33065L,33066L,33067L,
93105 33068L,33069L,33070L,33071L,33072L,33073L,33074L,33075L,33076L,33077L,
93106 33078L,33079L,33080L,33081L,33082L,33083L,33084L,33085L,33086L,33087L,
93107 33088L,33089L,33090L,33091L,33092L,33093L,33094L,33095L,33096L,33097L,
93108 33098L,33099L,33100L,33101L,33102L,33103L,33104L,33105L,33106L,33107L,
93109 33108L,33109L,33110L,33111L,33112L,33113L,33114L,33115L,33116L,33117L,
93110 33118L,33119L,33120L,33121L,33122L,33123L,33124L,33125L,33126L,33127L,
93111 33128L,33129L,33130L,33131L,33132L,33133L,33134L,33135L,33136L,33137L,
93112 33138L,33139L,33140L,33141L,33142L,33143L,33144L,33145L,33146L,33147L,
93113 33148L,33149L,33150L,33151L,33152L,33153L,33154L,33155L,33156L,33157L,
93114 33158L,33159L,33160L,33161L,33162L,33163L,33164L,33165L,33166L,33167L,
93115 33168L,33169L,33170L,33171L,33172L,33173L,33174L,33175L,33176L,33177L,
93116 33178L,33179L,33180L,33181L,33182L,33183L,33184L,33185L,33186L,33187L,
93117 33188L,33189L,33190L,33191L,33192L,33193L,33194L,33195L,33196L,33197L,
93118 33198L,33199L,33200L,33201L,33202L,33203L,33204L,33205L,33206L,33207L,
93119 33208L,33209L,33210L,33211L,33212L,33213L,33214L,33215L,33216L,33217L,
93120 33218L,33219L,33220L,33221L,33222L,33223L,33224L,33225L,33226L,33227L,
93121 33228L,33229L,33230L,33231L,33232L,33233L,33234L,33235L,33236L,33237L,
93122 33238L,33239L,33240L,33241L,33242L,33243L,33244L,33245L,33246L,33247L,
93123 33248L,33249L,33250L,33251L,33252L,33253L,33254L,33255L,33256L,33257L,
93124 33258L,33259L,33260L,33261L,33262L,33263L,33264L,33265L,33266L,33267L,
93125 33268L,33269L,33270L,33271L,33272L,33273L,33274L,33275L,33276L,33277L,
93126 33278L,33279L,33280L,33281L,33282L,33283L,33284L,33285L,33286L,33287L,
93127 33288L,33289L,33290L,33291L,33292L,33293L,33294L,33295L,33296L,33297L,
93128 33298L,33299L,33300L,33301L,33302L,33303L,33304L,33305L,33306L,33307L,
93129 33308L,33309L,33310L,33311L,33312L,33313L,33314L,33315L,33316L,33317L,
93130 33318L,33319L,33320L,33321L,33322L,33323L,33324L,33325L,33326L,33327L,
93131 33328L,33329L,33330L,33331L,33332L,33333L,33334L,33335L,33336L,33337L,
93132 33338L,33339L,33340L,33341L,33342L,33343L,33344L,33345L,33346L,33347L,
93133 33348L,33349L,33350L,33351L,33352L,33353L,33354L,33355L,33356L,33357L,
93134 33358L,33359L,33360L,33361L,33362L,33363L,33364L,33365L,33366L,33367L,
93135 33368L,33369L,33370L,33371L,33372L,33373L,33374L,33375L,33376L,33377L,
93136 33378L,33379L,33380L,33381L,33382L,33383L,33384L,33385L,33386L,33387L,
93137 33388L,33389L,33390L,33391L,33392L,33393L,33394L,33395L,33396L,33397L,
93138 33398L,33399L,33400L,33401L,33402L,33403L,33404L,33405L,33406L,33407L,
93139 33408L,33409L,33410L,33411L,33412L,33413L,33414L,33415L,33416L,33417L,
93140 33418L,33419L,33420L,33421L,33422L,33423L,33424L,33425L,33426L,33427L,
93141 33428L,33429L,33430L,33431L,33432L,33433L,33434L,33435L,33436L,33437L,
93142 33438L,33439L,33440L,33441L,33442L,33443L,33444L,33445L,33446L,33447L,
93143 33448L,33449L,33450L,33451L,33452L,33453L,33454L,33455L,33456L,33457L,
93144 33458L,33459L,33460L,33461L,33462L,33463L,33464L,33465L,33466L,33467L,
93145 33468L,33469L,33470L,33471L,33472L,33473L,33474L,33475L,33476L,33477L,
93146 33478L,33479L,33480L,33481L,33482L,33483L,33484L,33485L,33486L,33487L,
93147 33488L,33489L,33490L,33491L,33492L,33493L,33494L,33495L,33496L,33497L,
93148 33498L,33499L,33500L,33501L,33502L,33503L,33504L,33505L,33506L,33507L,
93149 33508L,33509L,33510L,33511L,33512L,33513L,33514L,33515L,33516L,33517L,
93150 33518L,33519L,33520L,33521L,33522L,33523L,33524L,33525L,33526L,33527L,
93151 33528L,33529L,33530L,33531L,33532L,33533L,33534L,33535L,33536L,33537L,
93152 33538L,33539L,33540L,33541L,33542L,33543L,33544L,33545L,33546L,33547L,
93153 33548L,33549L,33550L,33551L,33552L,33553L,33554L,33555L,33556L,33557L,
93154 33558L,33559L,33560L,33561L,33562L,33563L,33564L,33565L,33566L,33567L,
93155 33568L,33569L,33570L,33571L,33572L,33573L,33574L,33575L,33576L,33577L,
93156 33578L,33579L,33580L,33581L,33582L,33583L,33584L,33585L,33586L,33587L,
93157 33588L,33589L,33590L,33591L,33592L,33593L,33594L,33595L,33596L,33597L,
93158 33598L,33599L,33600L,33601L,33602L,33603L,33604L,33605L,33606L,33607L,
93159 33608L,33609L,33610L,33611L,33612L,33613L,33614L,33615L,33616L,33617L,
93160 33618L,33619L,33620L,33621L,33622L,33623L,33624L,33625L,33626L,33627L,
93161 33628L,33629L,33630L,33631L,33632L,33633L,33634L,33635L,33636L,33637L,
93162 33638L,33639L,33640L,33641L,33642L,33643L,33644L,33645L,33646L,33647L,
93163 33648L,33649L,33650L,33651L,33652L,33653L,33654L,33655L,33656L,33657L,
93164 33658L,33659L,33660L,33661L,33662L,33663L,33664L,33665L,33666L,33667L,
93165 33668L,33669L,33670L,33671L,33672L,33673L,33674L,33675L,33676L,33677L,
93166 33678L,33679L,33680L,33681L,33682L,33683L,33684L,33685L,33686L,33687L,
93167 33688L,33689L,33690L,33691L,33692L,33693L,33694L,33695L,33696L,33697L,
93168 33698L,33699L,33700L,33701L,33702L,33703L,33704L,33705L,33706L,33707L,
93169 33708L,33709L,33710L,33711L,33712L,33713L,33714L,33715L,33716L,33717L,
93170 33718L,33719L,33720L,33721L,33722L,33723L,33724L,33725L,33726L,33727L,
93171 33728L,33729L,33730L,33731L,33732L,33733L,33734L,33735L,33736L,33737L,
93172 33738L,33739L,33740L,33741L,33742L,33743L,33744L,33745L,33746L,33747L,
93173 33748L,33749L,33750L,33751L,33752L,33753L,33754L,33755L,33756L,33757L,
93174 33758L,33759L,33760L,33761L,33762L,33763L,33764L,33765L,33766L,33767L,
93175 33768L,33769L,33770L,33771L,33772L,33773L,33774L,33775L,33776L,33777L,
93176 33778L,33779L,33780L,33781L,33782L,33783L,33784L,33785L,33786L,33787L,
93177 33788L,33789L,33790L,33791L,33792L,33793L,33794L,33795L,33796L,33797L,
93178 33798L,33799L,33800L,33801L,33802L,33803L,33804L,33805L,33806L,33807L,
93179 33808L,33809L,33810L,33811L,33812L,33813L,33814L,33815L,33816L,33817L,
93180 33818L,33819L,33820L,33821L,33822L,33823L,33824L,33825L,33826L,33827L,
93181 33828L,33829L,33830L,33831L,33832L,33833L,33834L,33835L,33836L,33837L,
93182 33838L,33839L,33840L,33841L,33842L,33843L,33844L,33845L,33846L,33847L,
93183 33848L,33849L,33850L,33851L,33852L,33853L,33854L,33855L,33856L,33857L,
93184 33858L,33859L,33860L,33861L,33862L,33863L,33864L,33865L,33866L,33867L,
93185 33868L,33869L,33870L,33871L,33872L,33873L,33874L,33875L,33876L,33877L,
93186 33878L,33879L,33880L,33881L,33882L,33883L,33884L,33885L,33886L,33887L,
93187 33888L,33889L,33890L,33891L,33892L,33893L,33894L,33895L,33896L,33897L,
93188 33898L,33899L,33900L,33901L,33902L,33903L,33904L,33905L,33906L,33907L,
93189 33908L,33909L,33910L,33911L,33912L,33913L,33914L,33915L,33916L,33917L,
93190 33918L,33919L,33920L,33921L,33922L,33923L,33924L,33925L,33926L,33927L,
93191 33928L,33929L,33930L,33931L,33932L,33933L,33934L,33935L,33936L,33937L,
93192 33938L,33939L,33940L,33941L,33942L,33943L,33944L,33945L,33946L,33947L,
93193 33948L,33949L,33950L,33951L,33952L,33953L,33954L,33955L,33956L,33957L,
93194 33958L,33959L,33960L,33961L,33962L,33963L,33964L,33965L,33966L,33967L,
93195 33968L,33969L,33970L,33971L,33972L,33973L,33974L,33975L,33976L,33977L,
93196 33978L,33979L,33980L,33981L,33982L,33983L,33984L,33985L,33986L,33987L,
93197 33988L,33989L,33990L,33991L,33992L,33993L,33994L,33995L,33996L,33997L,
93198 33998L,33999L,34000L,34001L,34002L,34003L,34004L,34005L,34006L,34007L,
93199 34008L,34009L,34010L,34011L,34012L,34013L,34014L,34015L,34016L,34017L,
93200 34018L,34019L,34020L,34021L,34022L,34023L,34024L,34025L,34026L,34027L,
93201 34028L,34029L,34030L,34031L,34032L,34033L,34034L,34035L,34036L,34037L,
93202 34038L,34039L,34040L,34041L,34042L,34043L,34044L,34045L,34046L,34047L,
93203 34048L,34049L,34050L,34051L,34052L,34053L,34054L,34055L,34056L,34057L,
93204 34058L,34059L,34060L,34061L,34062L,34063L,34064L,34065L,34066L,34067L,
93205 34068L,34069L,34070L,34071L,34072L,34073L,34074L,34075L,34076L,34077L,
93206 34078L,34079L,34080L,34081L,34082L,34083L,34084L,34085L,34086L,34087L,
93207 34088L,34089L,34090L,34091L,34092L,34093L,34094L,34095L,34096L,34097L,
93208 34098L,34099L,34100L,34101L,34102L,34103L,34104L,34105L,34106L,34107L,
93209 34108L,34109L,34110L,34111L,34112L,34113L,34114L,34115L,34116L,34117L,
93210 34118L,34119L,34120L,34121L,34122L,34123L,34124L,34125L,34126L,34127L,
93211 34128L,34129L,34130L,34131L,34132L,34133L,34134L,34135L,34136L,34137L,
93212 34138L,34139L,34140L,34141L,34142L,34143L,34144L,34145L,34146L,34147L,
93213 34148L,34149L,34150L,34151L,34152L,34153L,34154L,34155L,34156L,34157L,
93214 34158L,34159L,34160L,34161L,34162L,34163L,34164L,34165L,34166L,34167L,
93215 34168L,34169L,34170L,34171L,34172L,34173L,34174L,34175L,34176L,34177L,
93216 34178L,34179L,34180L,34181L,34182L,34183L,34184L,34185L,34186L,34187L,
93217 34188L,34189L,34190L,34191L,34192L,34193L,34194L,34195L,34196L,34197L,
93218 34198L,34199L,34200L,34201L,34202L,34203L,34204L,34205L,34206L,34207L,
93219 34208L,34209L,34210L,34211L,34212L,34213L,34214L,34215L,34216L,34217L,
93220 34218L,34219L,34220L,34221L,34222L,34223L,34224L,34225L,34226L,34227L,
93221 34228L,34229L,34230L,34231L,34232L,34233L,34234L,34235L,34236L,34237L,
93222 34238L,34239L,34240L,34241L,34242L,34243L,34244L,34245L,34246L,34247L,
93223 34248L,34249L,34250L,34251L,34252L,34253L,34254L,34255L,34256L,34257L,
93224 34258L,34259L,34260L,34261L,34262L,34263L,34264L,34265L,34266L,34267L,
93225 34268L,34269L,34270L,34271L,34272L,34273L,34274L,34275L,34276L,34277L,
93226 34278L,34279L,34280L,34281L,34282L,34283L,34284L,34285L,34286L,34287L,
93227 34288L,34289L,34290L,34291L,34292L,34293L,34294L,34295L,34296L,34297L,
93228 34298L,34299L,34300L,34301L,34302L,34303L,34304L,34305L,34306L,34307L,
93229 34308L,34309L,34310L,34311L,34312L,34313L,34314L,34315L,34316L,34317L,
93230 34318L,34319L,34320L,34321L,34322L,34323L,34324L,34325L,34326L,34327L,
93231 34328L,34329L,34330L,34331L,34332L,34333L,34334L,34335L,34336L,34337L,
93232 34338L,34339L,34340L,34341L,34342L,34343L,34344L,34345L,34346L,34347L,
93233 34348L,34349L,34350L,34351L,34352L,34353L,34354L,34355L,34356L,34357L,
93234 34358L,34359L,34360L,34361L,34362L,34363L,34364L,34365L,34366L,34367L,
93235 34368L,34369L,34370L,34371L,34372L,34373L,34374L,34375L,34376L,34377L,
93236 34378L,34379L,34380L,34381L,34382L,34383L,34384L,34385L,34386L,34387L,
93237 34388L,34389L,34390L,34391L,34392L,34393L,34394L,34395L,34396L,34397L,
93238 34398L,34399L,34400L,34401L,34402L,34403L,34404L,34405L,34406L,34407L,
93239 34408L,34409L,34410L,34411L,34412L,34413L,34414L,34415L,34416L,34417L,
93240 34418L,34419L,34420L,34421L,34422L,34423L,34424L,34425L,34426L,34427L,
93241 34428L,34429L,34430L,34431L,34432L,34433L,34434L,34435L,34436L,34437L,
93242 34438L,34439L,34440L,34441L,34442L,34443L,34444L,34445L,34446L,34447L,
93243 34448L,34449L,34450L,34451L,34452L,34453L,34454L,34455L,34456L,34457L,
93244 34458L,34459L,34460L,34461L,34462L,34463L,34464L,34465L,34466L,34467L,
93245 34468L,34469L,34470L,34471L,34472L,34473L,34474L,34475L,34476L,34477L,
93246 34478L,34479L,34480L,34481L,34482L,34483L,34484L,34485L,34486L,34487L,
93247 34488L,34489L,34490L,34491L,34492L,34493L,34494L,34495L,34496L,34497L,
93248 34498L,34499L,34500L,34501L,34502L,34503L,34504L,34505L,34506L,34507L,
93249 34508L,34509L,34510L,34511L,34512L,34513L,34514L,34515L,34516L,34517L,
93250 34518L,34519L,34520L,34521L,34522L,34523L,34524L,34525L,34526L,34527L,
93251 34528L,34529L,34530L,34531L,34532L,34533L,34534L,34535L,34536L,34537L,
93252 34538L,34539L,34540L,34541L,34542L,34543L,34544L,34545L,34546L,34547L,
93253 34548L,34549L,34550L,34551L,34552L,34553L,34554L,34555L,34556L,34557L,
93254 34558L,34559L,34560L,34561L,34562L,34563L,34564L,34565L,34566L,34567L,
93255 34568L,34569L,34570L,34571L,34572L,34573L,34574L,34575L,34576L,34577L,
93256 34578L,34579L,34580L,34581L,34582L,34583L,34584L,34585L,34586L,34587L,
93257 34588L,34589L,34590L,34591L,34592L,34593L,34594L,34595L,34596L,34597L,
93258 34598L,34599L,34600L,34601L,34602L,34603L,34604L,34605L,34606L,34607L,
93259 34608L,34609L,34610L,34611L,34612L,34613L,34614L,34615L,34616L,34617L,
93260 34618L,34619L,34620L,34621L,34622L,34623L,34624L,34625L,34626L,34627L,
93261 34628L,34629L,34630L,34631L,34632L,34633L,34634L,34635L,34636L,34637L,
93262 34638L,34639L,34640L,34641L,34642L,34643L,34644L,34645L,34646L,34647L,
93263 34648L,34649L,34650L,34651L,34652L,34653L,34654L,34655L,34656L,34657L,
93264 34658L,34659L,34660L,34661L,34662L,34663L,34664L,34665L,34666L,34667L,
93265 34668L,34669L,34670L,34671L,34672L,34673L,34674L,34675L,34676L,34677L,
93266 34678L,34679L,34680L,34681L,34682L,34683L,34684L,34685L,34686L,34687L,
93267 34688L,34689L,34690L,34691L,34692L,34693L,34694L,34695L,34696L,34697L,
93268 34698L,34699L,34700L,34701L,34702L,34703L,34704L,34705L,34706L,34707L,
93269 34708L,34709L,34710L,34711L,34712L,34713L,34714L,34715L,34716L,34717L,
93270 34718L,34719L,34720L,34721L,34722L,34723L,34724L,34725L,34726L,34727L,
93271 34728L,34729L,34730L,34731L,34732L,34733L,34734L,34735L,34736L,34737L,
93272 34738L,34739L,34740L,34741L,34742L,34743L,34744L,34745L,34746L,34747L,
93273 34748L,34749L,34750L,34751L,34752L,34753L,34754L,34755L,34756L,34757L,
93274 34758L,34759L,34760L,34761L,34762L,34763L,34764L,34765L,34766L,34767L,
93275 34768L,34769L,34770L,34771L,34772L,34773L,34774L,34775L,34776L,34777L,
93276 34778L,34779L,34780L,34781L,34782L,34783L,34784L,34785L,34786L,34787L,
93277 34788L,34789L,34790L,34791L,34792L,34793L,34794L,34795L,34796L,34797L,
93278 34798L,34799L,34800L,34801L,34802L,34803L,34804L,34805L,34806L,34807L,
93279 34808L,34809L,34810L,34811L,34812L,34813L,34814L,34815L,34816L,34817L,
93280 34818L,34819L,34820L,34821L,34822L,34823L,34824L,34825L,34826L,34827L,
93281 34828L,34829L,34830L,34831L,34832L,34833L,34834L,34835L,34836L,34837L,
93282 34838L,34839L,34840L,34841L,34842L,34843L,34844L,34845L,34846L,34847L,
93283 34848L,34849L,34850L,34851L,34852L,34853L,34854L,34855L,34856L,34857L,
93284 34858L,34859L,34860L,34861L,34862L,34863L,34864L,34865L,34866L,34867L,
93285 34868L,34869L,34870L,34871L,34872L,34873L,34874L,34875L,34876L,34877L,
93286 34878L,34879L,34880L,34881L,34882L,34883L,34884L,34885L,34886L,34887L,
93287 34888L,34889L,34890L,34891L,34892L,34893L,34894L,34895L,34896L,34897L,
93288 34898L,34899L,34900L,34901L,34902L,34903L,34904L,34905L,34906L,34907L,
93289 34908L,34909L,34910L,34911L,34912L,34913L,34914L,34915L,34916L,34917L,
93290 34918L,34919L,34920L,34921L,34922L,34923L,34924L,34925L,34926L,34927L,
93291 34928L,34929L,34930L,34931L,34932L,34933L,34934L,34935L,34936L,34937L,
93292 34938L,34939L,34940L,34941L,34942L,34943L,34944L,34945L,34946L,34947L,
93293 34948L,34949L,34950L,34951L,34952L,34953L,34954L,34955L,34956L,34957L,
93294 34958L,34959L,34960L,34961L,34962L,34963L,34964L,34965L,34966L,34967L,
93295 34968L,34969L,34970L,34971L,34972L,34973L,34974L,34975L,34976L,34977L,
93296 34978L,34979L,34980L,34981L,34982L,34983L,34984L,34985L,34986L,34987L,
93297 34988L,34989L,34990L,34991L,34992L,34993L,34994L,34995L,34996L,34997L,
93298 34998L,34999L,35000L,35001L,35002L,35003L,35004L,35005L,35006L,35007L,
93299 35008L,35009L,35010L,35011L,35012L,35013L,35014L,35015L,35016L,35017L,
93300 35018L,35019L,35020L,35021L,35022L,35023L,35024L,35025L,35026L,35027L,
93301 35028L,35029L,35030L,35031L,35032L,35033L,35034L,35035L,35036L,35037L,
93302 35038L,35039L,35040L,35041L,35042L,35043L,35044L,35045L,35046L,35047L,
93303 35048L,35049L,35050L,35051L,35052L,35053L,35054L,35055L,35056L,35057L,
93304 35058L,35059L,35060L,35061L,35062L,35063L,35064L,35065L,35066L,35067L,
93305 35068L,35069L,35070L,35071L,35072L,35073L,35074L,35075L,35076L,35077L,
93306 35078L,35079L,35080L,35081L,35082L,35083L,35084L,35085L,35086L,35087L,
93307 35088L,35089L,35090L,35091L,35092L,35093L,35094L,35095L,35096L,35097L,
93308 35098L,35099L,35100L,35101L,35102L,35103L,35104L,35105L,35106L,35107L,
93309 35108L,35109L,35110L,35111L,35112L,35113L,35114L,35115L,35116L,35117L,
93310 35118L,35119L,35120L,35121L,35122L,35123L,35124L,35125L,35126L,35127L,
93311 35128L,35129L,35130L,35131L,35132L,35133L,35134L,35135L,35136L,35137L,
93312 35138L,35139L,35140L,35141L,35142L,35143L,35144L,35145L,35146L,35147L,
93313 35148L,35149L,35150L,35151L,35152L,35153L,35154L,35155L,35156L,35157L,
93314 35158L,35159L,35160L,35161L,35162L,35163L,35164L,35165L,35166L,35167L,
93315 35168L,35169L,35170L,35171L,35172L,35173L,35174L,35175L,35176L,35177L,
93316 35178L,35179L,35180L,35181L,35182L,35183L,35184L,35185L,35186L,35187L,
93317 35188L,35189L,35190L,35191L,35192L,35193L,35194L,35195L,35196L,35197L,
93318 35198L,35199L,35200L,35201L,35202L,35203L,35204L,35205L,35206L,35207L,
93319 35208L,35209L,35210L,35211L,35212L,35213L,35214L,35215L,35216L,35217L,
93320 35218L,35219L,35220L,35221L,35222L,35223L,35224L,35225L,35226L,35227L,
93321 35228L,35229L,35230L,35231L,35232L,35233L,35234L,35235L,35236L,35237L,
93322 35238L,35239L,35240L,35241L,35242L,35243L,35244L,35245L,35246L,35247L,
93323 35248L,35249L,35250L,35251L,35252L,35253L,35254L,35255L,35256L,35257L,
93324 35258L,35259L,35260L,35261L,35262L,35263L,35264L,35265L,35266L,35267L,
93325 35268L,35269L,35270L,35271L,35272L,35273L,35274L,35275L,35276L,35277L,
93326 35278L,35279L,35280L,35281L,35282L,35283L,35284L,35285L,35286L,35287L,
93327 35288L,35289L,35290L,35291L,35292L,35293L,35294L,35295L,35296L,35297L,
93328 35298L,35299L,35300L,35301L,35302L,35303L,35304L,35305L,35306L,35307L,
93329 35308L,35309L,35310L,35311L,35312L,35313L,35314L,35315L,35316L,35317L,
93330 35318L,35319L,35320L,35321L,35322L,35323L,35324L,35325L,35326L,35327L,
93331 35328L,35329L,35330L,35331L,35332L,35333L,35334L,35335L,35336L,35337L,
93332 35338L,35339L,35340L,35341L,35342L,35343L,35344L,35345L,35346L,35347L,
93333 35348L,35349L,35350L,35351L,35352L,35353L,35354L,35355L,35356L,35357L,
93334 35358L,35359L,35360L,35361L,35362L,35363L,35364L,35365L,35366L,35367L,
93335 35368L,35369L,35370L,35371L,35372L,35373L,35374L,35375L,35376L,35377L,
93336 35378L,35379L,35380L,35381L,35382L,35383L,35384L,35385L,35386L,35387L,
93337 35388L,35389L,35390L,35391L,35392L,35393L,35394L,35395L,35396L,35397L,
93338 35398L,35399L,35400L,35401L,35402L,35403L,35404L,35405L,35406L,35407L,
93339 35408L,35409L,35410L,35411L,35412L,35413L,35414L,35415L,35416L,35417L,
93340 35418L,35419L,35420L,35421L,35422L,35423L,35424L,35425L,35426L,35427L,
93341 35428L,35429L,35430L,35431L,35432L,35433L,35434L,35435L,35436L,35437L,
93342 35438L,35439L,35440L,35441L,35442L,35443L,35444L,35445L,35446L,35447L,
93343 35448L,35449L,35450L,35451L,35452L,35453L,35454L,35455L,35456L,35457L,
93344 35458L,35459L,35460L,35461L,35462L,35463L,35464L,35465L,35466L,35467L,
93345 35468L,35469L,35470L,35471L,35472L,35473L,35474L,35475L,35476L,35477L,
93346 35478L,35479L,35480L,35481L,35482L,35483L,35484L,35485L,35486L,35487L,
93347 35488L,35489L,35490L,35491L,35492L,35493L,35494L,35495L,35496L,35497L,
93348 35498L,35499L,35500L,35501L,35502L,35503L,35504L,35505L,35506L,35507L,
93349 35508L,35509L,35510L,35511L,35512L,35513L,35514L,35515L,35516L,35517L,
93350 35518L,35519L,35520L,35521L,35522L,35523L,35524L,35525L,35526L,35527L,
93351 35528L,35529L,35530L,35531L,35532L,35533L,35534L,35535L,35536L,35537L,
93352 35538L,35539L,35540L,35541L,35542L,35543L,35544L,35545L,35546L,35547L,
93353 35548L,35549L,35550L,35551L,35552L,35553L,35554L,35555L,35556L,35557L,
93354 35558L,35559L,35560L,35561L,35562L,35563L,35564L,35565L,35566L,35567L,
93355 35568L,35569L,35570L,35571L,35572L,35573L,35574L,35575L,35576L,35577L,
93356 35578L,35579L,35580L,35581L,35582L,35583L,35584L,35585L,35586L,35587L,
93357 35588L,35589L,35590L,35591L,35592L,35593L,35594L,35595L,35596L,35597L,
93358 35598L,35599L,35600L,35601L,35602L,35603L,35604L,35605L,35606L,35607L,
93359 35608L,35609L,35610L,35611L,35612L,35613L,35614L,35615L,35616L,35617L,
93360 35618L,35619L,35620L,35621L,35622L,35623L,35624L,35625L,35626L,35627L,
93361 35628L,35629L,35630L,35631L,35632L,35633L,35634L,35635L,35636L,35637L,
93362 35638L,35639L,35640L,35641L,35642L,35643L,35644L,35645L,35646L,35647L,
93363 35648L,35649L,35650L,35651L,35652L,35653L,35654L,35655L,35656L,35657L,
93364 35658L,35659L,35660L,35661L,35662L,35663L,35664L,35665L,35666L,35667L,
93365 35668L,35669L,35670L,35671L,35672L,35673L,35674L,35675L,35676L,35677L,
93366 35678L,35679L,35680L,35681L,35682L,35683L,35684L,35685L,35686L,35687L,
93367 35688L,35689L,35690L,35691L,35692L,35693L,35694L,35695L,35696L,35697L,
93368 35698L,35699L,35700L,35701L,35702L,35703L,35704L,35705L,35706L,35707L,
93369 35708L,35709L,35710L,35711L,35712L,35713L,35714L,35715L,35716L,35717L,
93370 35718L,35719L,35720L,35721L,35722L,35723L,35724L,35725L,35726L,35727L,
93371 35728L,35729L,35730L,35731L,35732L,35733L,35734L,35735L,35736L,35737L,
93372 35738L,35739L,35740L,35741L,35742L,35743L,35744L,35745L,35746L,35747L,
93373 35748L,35749L,35750L,35751L,35752L,35753L,35754L,35755L,35756L,35757L,
93374 35758L,35759L,35760L,35761L,35762L,35763L,35764L,35765L,35766L,35767L,
93375 35768L,35769L,35770L,35771L,35772L,35773L,35774L,35775L,35776L,35777L,
93376 35778L,35779L,35780L,35781L,35782L,35783L,35784L,35785L,35786L,35787L,
93377 35788L,35789L,35790L,35791L,35792L,35793L,35794L,35795L,35796L,35797L,
93378 35798L,35799L,35800L,35801L,35802L,35803L,35804L,35805L,35806L,35807L,
93379 35808L,35809L,35810L,35811L,35812L,35813L,35814L,35815L,35816L,35817L,
93380 35818L,35819L,35820L,35821L,35822L,35823L,35824L,35825L,35826L,35827L,
93381 35828L,35829L,35830L,35831L,35832L,35833L,35834L,35835L,35836L,35837L,
93382 35838L,35839L,35840L,35841L,35842L,35843L,35844L,35845L,35846L,35847L,
93383 35848L,35849L,35850L,35851L,35852L,35853L,35854L,35855L,35856L,35857L,
93384 35858L,35859L,35860L,35861L,35862L,35863L,35864L,35865L,35866L,35867L,
93385 35868L,35869L,35870L,35871L,35872L,35873L,35874L,35875L,35876L,35877L,
93386 35878L,35879L,35880L,35881L,35882L,35883L,35884L,35885L,35886L,35887L,
93387 35888L,35889L,35890L,35891L,35892L,35893L,35894L,35895L,35896L,35897L,
93388 35898L,35899L,35900L,35901L,35902L,35903L,35904L,35905L,35906L,35907L,
93389 35908L,35909L,35910L,35911L,35912L,35913L,35914L,35915L,35916L,35917L,
93390 35918L,35919L,35920L,35921L,35922L,35923L,35924L,35925L,35926L,35927L,
93391 35928L,35929L,35930L,35931L,35932L,35933L,35934L,35935L,35936L,35937L,
93392 35938L,35939L,35940L,35941L,35942L,35943L,35944L,35945L,35946L,35947L,
93393 35948L,35949L,35950L,35951L,35952L,35953L,35954L,35955L,35956L,35957L,
93394 35958L,35959L,35960L,35961L,35962L,35963L,35964L,35965L,35966L,35967L,
93395 35968L,35969L,35970L,35971L,35972L,35973L,35974L,35975L,35976L,35977L,
93396 35978L,35979L,35980L,35981L,35982L,35983L,35984L,35985L,35986L,35987L,
93397 35988L,35989L,35990L,35991L,35992L,35993L,35994L,35995L,35996L,35997L,
93398 35998L,35999L,36000L,36001L,36002L,36003L,36004L,36005L,36006L,36007L,
93399 36008L,36009L,36010L,36011L,36012L,36013L,36014L,36015L,36016L,36017L,
93400 36018L,36019L,36020L,36021L,36022L,36023L,36024L,36025L,36026L,36027L,
93401 36028L,36029L,36030L,36031L,36032L,36033L,36034L,36035L,36036L,36037L,
93402 36038L,36039L,36040L,36041L,36042L,36043L,36044L,36045L,36046L,36047L,
93403 36048L,36049L,36050L,36051L,36052L,36053L,36054L,36055L,36056L,36057L,
93404 36058L,36059L,36060L,36061L,36062L,36063L,36064L,36065L,36066L,36067L,
93405 36068L,36069L,36070L,36071L,36072L,36073L,36074L,36075L,36076L,36077L,
93406 36078L,36079L,36080L,36081L,36082L,36083L,36084L,36085L,36086L,36087L,
93407 36088L,36089L,36090L,36091L,36092L,36093L,36094L,36095L,36096L,36097L,
93408 36098L,36099L,36100L,36101L,36102L,36103L,36104L,36105L,36106L,36107L,
93409 36108L,36109L,36110L,36111L,36112L,36113L,36114L,36115L,36116L,36117L,
93410 36118L,36119L,36120L,36121L,36122L,36123L,36124L,36125L,36126L,36127L,
93411 36128L,36129L,36130L,36131L,36132L,36133L,36134L,36135L,36136L,36137L,
93412 36138L,36139L,36140L,36141L,36142L,36143L,36144L,36145L,36146L,36147L,
93413 36148L,36149L,36150L,36151L,36152L,36153L,36154L,36155L,36156L,36157L,
93414 36158L,36159L,36160L,36161L,36162L,36163L,36164L,36165L,36166L,36167L,
93415 36168L,36169L,36170L,36171L,36172L,36173L,36174L,36175L,36176L,36177L,
93416 36178L,36179L,36180L,36181L,36182L,36183L,36184L,36185L,36186L,36187L,
93417 36188L,36189L,36190L,36191L,36192L,36193L,36194L,36195L,36196L,36197L,
93418 36198L,36199L,36200L,36201L,36202L,36203L,36204L,36205L,36206L,36207L,
93419 36208L,36209L,36210L,36211L,36212L,36213L,36214L,36215L,36216L,36217L,
93420 36218L,36219L,36220L,36221L,36222L,36223L,36224L,36225L,36226L,36227L,
93421 36228L,36229L,36230L,36231L,36232L,36233L,36234L,36235L,36236L,36237L,
93422 36238L,36239L,36240L,36241L,36242L,36243L,36244L,36245L,36246L,36247L,
93423 36248L,36249L,36250L,36251L,36252L,36253L,36254L,36255L,36256L,36257L,
93424 36258L,36259L,36260L,36261L,36262L,36263L,36264L,36265L,36266L,36267L,
93425 36268L,36269L,36270L,36271L,36272L,36273L,36274L,36275L,36276L,36277L,
93426 36278L,36279L,36280L,36281L,36282L,36283L,36284L,36285L,36286L,36287L,
93427 36288L,36289L,36290L,36291L,36292L,36293L,36294L,36295L,36296L,36297L,
93428 36298L,36299L,36300L,36301L,36302L,36303L,36304L,36305L,36306L,36307L,
93429 36308L,36309L,36310L,36311L,36312L,36313L,36314L,36315L,36316L,36317L,
93430 36318L,36319L,36320L,36321L,36322L,36323L,36324L,36325L,36326L,36327L,
93431 36328L,36329L,36330L,36331L,36332L,36333L,36334L,36335L,36336L,36337L,
93432 36338L,36339L,36340L,36341L,36342L,36343L,36344L,36345L,36346L,36347L,
93433 36348L,36349L,36350L,36351L,36352L,36353L,36354L,36355L,36356L,36357L,
93434 36358L,36359L,36360L,36361L,36362L,36363L,36364L,36365L,36366L,36367L,
93435 36368L,36369L,36370L,36371L,36372L,36373L,36374L,36375L,36376L,36377L,
93436 36378L,36379L,36380L,36381L,36382L,36383L,36384L,36385L,36386L,36387L,
93437 36388L,36389L,36390L,36391L,36392L,36393L,36394L,36395L,36396L,36397L,
93438 36398L,36399L,36400L,36401L,36402L,36403L,36404L,36405L,36406L,36407L,
93439 36408L,36409L,36410L,36411L,36412L,36413L,36414L,36415L,36416L,36417L,
93440 36418L,36419L,36420L,36421L,36422L,36423L,36424L,36425L,36426L,36427L,
93441 36428L,36429L,36430L,36431L,36432L,36433L,36434L,36435L,36436L,36437L,
93442 36438L,36439L,36440L,36441L,36442L,36443L,36444L,36445L,36446L,36447L,
93443 36448L,36449L,36450L,36451L,36452L,36453L,36454L,36455L,36456L,36457L,
93444 36458L,36459L,36460L,36461L,36462L,36463L,36464L,36465L,36466L,36467L,
93445 36468L,36469L,36470L,36471L,36472L,36473L,36474L,36475L,36476L,36477L,
93446 36478L,36479L,36480L,36481L,36482L,36483L,36484L,36485L,36486L,36487L,
93447 36488L,36489L,36490L,36491L,36492L,36493L,36494L,36495L,36496L,36497L,
93448 36498L,36499L,36500L,36501L,36502L,36503L,36504L,36505L,36506L,36507L,
93449 36508L,36509L,36510L,36511L,36512L,36513L,36514L,36515L,36516L,36517L,
93450 36518L,36519L,36520L,36521L,36522L,36523L,36524L,36525L,36526L,36527L,
93451 36528L,36529L,36530L,36531L,36532L,36533L,36534L,36535L,36536L,36537L,
93452 36538L,36539L,36540L,36541L,36542L,36543L,36544L,36545L,36546L,36547L,
93453 36548L,36549L,36550L,36551L,36552L,36553L,36554L,36555L,36556L,36557L,
93454 36558L,36559L,36560L,36561L,36562L,36563L,36564L,36565L,36566L,36567L,
93455 36568L,36569L,36570L,36571L,36572L,36573L,36574L,36575L,36576L,36577L,
93456 36578L,36579L,36580L,36581L,36582L,36583L,36584L,36585L,36586L,36587L,
93457 36588L,36589L,36590L,36591L,36592L,36593L,36594L,36595L,36596L,36597L,
93458 36598L,36599L,36600L,36601L,36602L,36603L,36604L,36605L,36606L,36607L,
93459 36608L,36609L,36610L,36611L,36612L,36613L,36614L,36615L,36616L,36617L,
93460 36618L,36619L,36620L,36621L,36622L,36623L,36624L,36625L,36626L,36627L,
93461 36628L,36629L,36630L,36631L,36632L,36633L,36634L,36635L,36636L,36637L,
93462 36638L,36639L,36640L,36641L,36642L,36643L,36644L,36645L,36646L,36647L,
93463 36648L,36649L,36650L,36651L,36652L,36653L,36654L,36655L,36656L,36657L,
93464 36658L,36659L,36660L,36661L,36662L,36663L,36664L,36665L,36666L,36667L,
93465 36668L,36669L,36670L,36671L,36672L,36673L,36674L,36675L,36676L,36677L,
93466 36678L,36679L,36680L,36681L,36682L,36683L,36684L,36685L,36686L,36687L,
93467 36688L,36689L,36690L,36691L,36692L,36693L,36694L,36695L,36696L,36697L,
93468 36698L,36699L,36700L,36701L,36702L,36703L,36704L,36705L,36706L,36707L,
93469 36708L,36709L,36710L,36711L,36712L,36713L,36714L,36715L,36716L,36717L,
93470 36718L,36719L,36720L,36721L,36722L,36723L,36724L,36725L,36726L,36727L,
93471 36728L,36729L,36730L,36731L,36732L,36733L,36734L,36735L,36736L,36737L,
93472 36738L,36739L,36740L,36741L,36742L,36743L,36744L,36745L,36746L,36747L,
93473 36748L,36749L,36750L,36751L,36752L,36753L,36754L,36755L,36756L,36757L,
93474 36758L,36759L,36760L,36761L,36762L,36763L,36764L,36765L,36766L,36767L,
93475 36768L,36769L,36770L,36771L,36772L,36773L,36774L,36775L,36776L,36777L,
93476 36778L,36779L,36780L,36781L,36782L,36783L,36784L,36785L,36786L,36787L,
93477 36788L,36789L,36790L,36791L,36792L,36793L,36794L,36795L,36796L,36797L,
93478 36798L,36799L,36800L,36801L,36802L,36803L,36804L,36805L,36806L,36807L,
93479 36808L,36809L,36810L,36811L,36812L,36813L,36814L,36815L,36816L,36817L,
93480 36818L,36819L,36820L,36821L,36822L,36823L,36824L,36825L,36826L,36827L,
93481 36828L,36829L,36830L,36831L,36832L,36833L,36834L,36835L,36836L,36837L,
93482 36838L,36839L,36840L,36841L,36842L,36843L,36844L,36845L,36846L,36847L,
93483 36848L,36849L,36850L,36851L,36852L,36853L,36854L,36855L,36856L,36857L,
93484 36858L,36859L,36860L,36861L,36862L,36863L,36864L,36865L,36866L,36867L,
93485 36868L,36869L,36870L,36871L,36872L,36873L,36874L,36875L,36876L,36877L,
93486 36878L,36879L,36880L,36881L,36882L,36883L,36884L,36885L,36886L,36887L,
93487 36888L,36889L,36890L,36891L,36892L,36893L,36894L,36895L,36896L,36897L,
93488 36898L,36899L,36900L,36901L,36902L,36903L,36904L,36905L,36906L,36907L,
93489 36908L,36909L,36910L,36911L,36912L,36913L,36914L,36915L,36916L,36917L,
93490 36918L,36919L,36920L,36921L,36922L,36923L,36924L,36925L,36926L,36927L,
93491 36928L,36929L,36930L,36931L,36932L,36933L,36934L,36935L,36936L,36937L,
93492 36938L,36939L,36940L,36941L,36942L,36943L,36944L,36945L,36946L,36947L,
93493 36948L,36949L,36950L,36951L,36952L,36953L,36954L,36955L,36956L,36957L,
93494 36958L,36959L,36960L,36961L,36962L,36963L,36964L,36965L,36966L,36967L,
93495 36968L,36969L,36970L,36971L,36972L,36973L,36974L,36975L,36976L,36977L,
93496 36978L,36979L,36980L,36981L,36982L,36983L,36984L,36985L,36986L,36987L,
93497 36988L,36989L,36990L,36991L,36992L,36993L,36994L,36995L,36996L,36997L,
93498 36998L,36999L,37000L,37001L,37002L,37003L,37004L,37005L,37006L,37007L,
93499 37008L,37009L,37010L,37011L,37012L,37013L,37014L,37015L,37016L,37017L,
93500 37018L,37019L,37020L,37021L,37022L,37023L,37024L,37025L,37026L,37027L,
93501 37028L,37029L,37030L,37031L,37032L,37033L,37034L,37035L,37036L,37037L,
93502 37038L,37039L,37040L,37041L,37042L,37043L,37044L,37045L,37046L,37047L,
93503 37048L,37049L,37050L,37051L,37052L,37053L,37054L,37055L,37056L,37057L,
93504 37058L,37059L,37060L,37061L,37062L,37063L,37064L,37065L,37066L,37067L,
93505 37068L,37069L,37070L,37071L,37072L,37073L,37074L,37075L,37076L,37077L,
93506 37078L,37079L,37080L,37081L,37082L,37083L,37084L,37085L,37086L,37087L,
93507 37088L,37089L,37090L,37091L,37092L,37093L,37094L,37095L,37096L,37097L,
93508 37098L,37099L,37100L,37101L,37102L,37103L,37104L,37105L,37106L,37107L,
93509 37108L,37109L,37110L,37111L,37112L,37113L,37114L,37115L,37116L,37117L,
93510 37118L,37119L,37120L,37121L,37122L,37123L,37124L,37125L,37126L,37127L,
93511 37128L,37129L,37130L,37131L,37132L,37133L,37134L,37135L,37136L,37137L,
93512 37138L,37139L,37140L,37141L,37142L,37143L,37144L,37145L,37146L,37147L,
93513 37148L,37149L,37150L,37151L,37152L,37153L,37154L,37155L,37156L,37157L,
93514 37158L,37159L,37160L,37161L,37162L,37163L,37164L,37165L,37166L,37167L,
93515 37168L,37169L,37170L,37171L,37172L,37173L,37174L,37175L,37176L,37177L,
93516 37178L,37179L,37180L,37181L,37182L,37183L,37184L,37185L,37186L,37187L,
93517 37188L,37189L,37190L,37191L,37192L,37193L,37194L,37195L,37196L,37197L,
93518 37198L,37199L,37200L,37201L,37202L,37203L,37204L,37205L,37206L,37207L,
93519 37208L,37209L,37210L,37211L,37212L,37213L,37214L,37215L,37216L,37217L,
93520 37218L,37219L,37220L,37221L,37222L,37223L,37224L,37225L,37226L,37227L,
93521 37228L,37229L,37230L,37231L,37232L,37233L,37234L,37235L,37236L,37237L,
93522 37238L,37239L,37240L,37241L,37242L,37243L,37244L,37245L,37246L,37247L,
93523 37248L,37249L,37250L,37251L,37252L,37253L,37254L,37255L,37256L,37257L,
93524 37258L,37259L,37260L,37261L,37262L,37263L,37264L,37265L,37266L,37267L,
93525 37268L,37269L,37270L,37271L,37272L,37273L,37274L,37275L,37276L,37277L,
93526 37278L,37279L,37280L,37281L,37282L,37283L,37284L,37285L,37286L,37287L,
93527 37288L,37289L,37290L,37291L,37292L,37293L,37294L,37295L,37296L,37297L,
93528 37298L,37299L,37300L,37301L,37302L,37303L,37304L,37305L,37306L,37307L,
93529 37308L,37309L,37310L,37311L,37312L,37313L,37314L,37315L,37316L,37317L,
93530 37318L,37319L,37320L,37321L,37322L,37323L,37324L,37325L,37326L,37327L,
93531 37328L,37329L,37330L,37331L,37332L,37333L,37334L,37335L,37336L,37337L,
93532 37338L,37339L,37340L,37341L,37342L,37343L,37344L,37345L,37346L,37347L,
93533 37348L,37349L,37350L,37351L,37352L,37353L,37354L,37355L,37356L,37357L,
93534 37358L,37359L,37360L,37361L,37362L,37363L,37364L,37365L,37366L,37367L,
93535 37368L,37369L,37370L,37371L,37372L,37373L,37374L,37375L,37376L,37377L,
93536 37378L,37379L,37380L,37381L,37382L,37383L,37384L,37385L,37386L,37387L,
93537 37388L,37389L,37390L,37391L,37392L,37393L,37394L,37395L,37396L,37397L,
93538 37398L,37399L,37400L,37401L,37402L,37403L,37404L,37405L,37406L,37407L,
93539 37408L,37409L,37410L,37411L,37412L,37413L,37414L,37415L,37416L,37417L,
93540 37418L,37419L,37420L,37421L,37422L,37423L,37424L,37425L,37426L,37427L,
93541 37428L,37429L,37430L,37431L,37432L,37433L,37434L,37435L,37436L,37437L,
93542 37438L,37439L,37440L,37441L,37442L,37443L,37444L,37445L,37446L,37447L,
93543 37448L,37449L,37450L,37451L,37452L,37453L,37454L,37455L,37456L,37457L,
93544 37458L,37459L,37460L,37461L,37462L,37463L,37464L,37465L,37466L,37467L,
93545 37468L,37469L,37470L,37471L,37472L,37473L,37474L,37475L,37476L,37477L,
93546 37478L,37479L,37480L,37481L,37482L,37483L,37484L,37485L,37486L,37487L,
93547 37488L,37489L,37490L,37491L,37492L,37493L,37494L,37495L,37496L,37497L,
93548 37498L,37499L,37500L,37501L,37502L,37503L,37504L,37505L,37506L,37507L,
93549 37508L,37509L,37510L,37511L,37512L,37513L,37514L,37515L,37516L,37517L,
93550 37518L,37519L,37520L,37521L,37522L,37523L,37524L,37525L,37526L,37527L,
93551 37528L,37529L,37530L,37531L,37532L,37533L,37534L,37535L,37536L,37537L,
93552 37538L,37539L,37540L,37541L,37542L,37543L,37544L,37545L,37546L,37547L,
93553 37548L,37549L,37550L,37551L,37552L,37553L,37554L,37555L,37556L,37557L,
93554 37558L,37559L,37560L,37561L,37562L,37563L,37564L,37565L,37566L,37567L,
93555 37568L,37569L,37570L,37571L,37572L,37573L,37574L,37575L,37576L,37577L,
93556 37578L,37579L,37580L,37581L,37582L,37583L,37584L,37585L,37586L,37587L,
93557 37588L,37589L,37590L,37591L,37592L,37593L,37594L,37595L,37596L,37597L,
93558 37598L,37599L,37600L,37601L,37602L,37603L,37604L,37605L,37606L,37607L,
93559 37608L,37609L,37610L,37611L,37612L,37613L,37614L,37615L,37616L,37617L,
93560 37618L,37619L,37620L,37621L,37622L,37623L,37624L,37625L,37626L,37627L,
93561 37628L,37629L,37630L,37631L,37632L,37633L,37634L,37635L,37636L,37637L,
93562 37638L,37639L,37640L,37641L,37642L,37643L,37644L,37645L,37646L,37647L,
93563 37648L,37649L,37650L,37651L,37652L,37653L,37654L,37655L,37656L,37657L,
93564 37658L,37659L,37660L,37661L,37662L,37663L,37664L,37665L,37666L,37667L,
93565 37668L,37669L,37670L,37671L,37672L,37673L,37674L,37675L,37676L,37677L,
93566 37678L,37679L,37680L,37681L,37682L,37683L,37684L,37685L,37686L,37687L,
93567 37688L,37689L,37690L,37691L,37692L,37693L,37694L,37695L,37696L,37697L,
93568 37698L,37699L,37700L,37701L,37702L,37703L,37704L,37705L,37706L,37707L,
93569 37708L,37709L,37710L,37711L,37712L,37713L,37714L,37715L,37716L,37717L,
93570 37718L,37719L,37720L,37721L,37722L,37723L,37724L,37725L,37726L,37727L,
93571 37728L,37729L,37730L,37731L,37732L,37733L,37734L,37735L,37736L,37737L,
93572 37738L,37739L,37740L,37741L,37742L,37743L,37744L,37745L,37746L,37747L,
93573 37748L,37749L,37750L,37751L,37752L,37753L,37754L,37755L,37756L,37757L,
93574 37758L,37759L,37760L,37761L,37762L,37763L,37764L,37765L,37766L,37767L,
93575 37768L,37769L,37770L,37771L,37772L,37773L,37774L,37775L,37776L,37777L,
93576 37778L,37779L,37780L,37781L,37782L,37783L,37784L,37785L,37786L,37787L,
93577 37788L,37789L,37790L,37791L,37792L,37793L,37794L,37795L,37796L,37797L,
93578 37798L,37799L,37800L,37801L,37802L,37803L,37804L,37805L,37806L,37807L,
93579 37808L,37809L,37810L,37811L,37812L,37813L,37814L,37815L,37816L,37817L,
93580 37818L,37819L,37820L,37821L,37822L,37823L,37824L,37825L,37826L,37827L,
93581 37828L,37829L,37830L,37831L,37832L,37833L,37834L,37835L,37836L,37837L,
93582 37838L,37839L,37840L,37841L,37842L,37843L,37844L,37845L,37846L,37847L,
93583 37848L,37849L,37850L,37851L,37852L,37853L,37854L,37855L,37856L,37857L,
93584 37858L,37859L,37860L,37861L,37862L,37863L,37864L,37865L,37866L,37867L,
93585 37868L,37869L,37870L,37871L,37872L,37873L,37874L,37875L,37876L,37877L,
93586 37878L,37879L,37880L,37881L,37882L,37883L,37884L,37885L,37886L,37887L,
93587 37888L,37889L,37890L,37891L,37892L,37893L,37894L,37895L,37896L,37897L,
93588 37898L,37899L,37900L,37901L,37902L,37903L,37904L,37905L,37906L,37907L,
93589 37908L,37909L,37910L,37911L,37912L,37913L,37914L,37915L,37916L,37917L,
93590 37918L,37919L,37920L,37921L,37922L,37923L,37924L,37925L,37926L,37927L,
93591 37928L,37929L,37930L,37931L,37932L,37933L,37934L,37935L,37936L,37937L,
93592 37938L,37939L,37940L,37941L,37942L,37943L,37944L,37945L,37946L,37947L,
93593 37948L,37949L,37950L,37951L,37952L,37953L,37954L,37955L,37956L,37957L,
93594 37958L,37959L,37960L,37961L,37962L,37963L,37964L,37965L,37966L,37967L,
93595 37968L,37969L,37970L,37971L,37972L,37973L,37974L,37975L,37976L,37977L,
93596 37978L,37979L,37980L,37981L,37982L,37983L,37984L,37985L,37986L,37987L,
93597 37988L,37989L,37990L,37991L,37992L,37993L,37994L,37995L,37996L,37997L,
93598 37998L,37999L,38000L,38001L,38002L,38003L,38004L,38005L,38006L,38007L,
93599 38008L,38009L,38010L,38011L,38012L,38013L,38014L,38015L,38016L,38017L,
93600 38018L,38019L,38020L,38021L,38022L,38023L,38024L,38025L,38026L,38027L,
93601 38028L,38029L,38030L,38031L,38032L,38033L,38034L,38035L,38036L,38037L,
93602 38038L,38039L,38040L,38041L,38042L,38043L,38044L,38045L,38046L,38047L,
93603 38048L,38049L,38050L,38051L,38052L,38053L,38054L,38055L,38056L,38057L,
93604 38058L,38059L,38060L,38061L,38062L,38063L,38064L,38065L,38066L,38067L,
93605 38068L,38069L,38070L,38071L,38072L,38073L,38074L,38075L,38076L,38077L,
93606 38078L,38079L,38080L,38081L,38082L,38083L,38084L,38085L,38086L,38087L,
93607 38088L,38089L,38090L,38091L,38092L,38093L,38094L,38095L,38096L,38097L,
93608 38098L,38099L,38100L,38101L,38102L,38103L,38104L,38105L,38106L,38107L,
93609 38108L,38109L,38110L,38111L,38112L,38113L,38114L,38115L,38116L,38117L,
93610 38118L,38119L,38120L,38121L,38122L,38123L,38124L,38125L,38126L,38127L,
93611 38128L,38129L,38130L,38131L,38132L,38133L,38134L,38135L,38136L,38137L,
93612 38138L,38139L,38140L,38141L,38142L,38143L,38144L,38145L,38146L,38147L,
93613 38148L,38149L,38150L,38151L,38152L,38153L,38154L,38155L,38156L,38157L,
93614 38158L,38159L,38160L,38161L,38162L,38163L,38164L,38165L,38166L,38167L,
93615 38168L,38169L,38170L,38171L,38172L,38173L,38174L,38175L,38176L,38177L,
93616 38178L,38179L,38180L,38181L,38182L,38183L,38184L,38185L,38186L,38187L,
93617 38188L,38189L,38190L,38191L,38192L,38193L,38194L,38195L,38196L,38197L,
93618 38198L,38199L,38200L,38201L,38202L,38203L,38204L,38205L,38206L,38207L,
93619 38208L,38209L,38210L,38211L,38212L,38213L,38214L,38215L,38216L,38217L,
93620 38218L,38219L,38220L,38221L,38222L,38223L,38224L,38225L,38226L,38227L,
93621 38228L,38229L,38230L,38231L,38232L,38233L,38234L,38235L,38236L,38237L,
93622 38238L,38239L,38240L,38241L,38242L,38243L,38244L,38245L,38246L,38247L,
93623 38248L,38249L,38250L,38251L,38252L,38253L,38254L,38255L,38256L,38257L,
93624 38258L,38259L,38260L,38261L,38262L,38263L,38264L,38265L,38266L,38267L,
93625 38268L,38269L,38270L,38271L,38272L,38273L,38274L,38275L,38276L,38277L,
93626 38278L,38279L,38280L,38281L,38282L,38283L,38284L,38285L,38286L,38287L,
93627 38288L,38289L,38290L,38291L,38292L,38293L,38294L,38295L,38296L,38297L,
93628 38298L,38299L,38300L,38301L,38302L,38303L,38304L,38305L,38306L,38307L,
93629 38308L,38309L,38310L,38311L,38312L,38313L,38314L,38315L,38316L,38317L,
93630 38318L,38319L,38320L,38321L,38322L,38323L,38324L,38325L,38326L,38327L,
93631 38328L,38329L,38330L,38331L,38332L,38333L,38334L,38335L,38336L,38337L,
93632 38338L,38339L,38340L,38341L,38342L,38343L,38344L,38345L,38346L,38347L,
93633 38348L,38349L,38350L,38351L,38352L,38353L,38354L,38355L,38356L,38357L,
93634 38358L,38359L,38360L,38361L,38362L,38363L,38364L,38365L,38366L,38367L,
93635 38368L,38369L,38370L,38371L,38372L,38373L,38374L,38375L,38376L,38377L,
93636 38378L,38379L,38380L,38381L,38382L,38383L,38384L,38385L,38386L,38387L,
93637 38388L,38389L,38390L,38391L,38392L,38393L,38394L,38395L,38396L,38397L,
93638 38398L,38399L,38400L,38401L,38402L,38403L,38404L,38405L,38406L,38407L,
93639 38408L,38409L,38410L,38411L,38412L,38413L,38414L,38415L,38416L,38417L,
93640 38418L,38419L,38420L,38421L,38422L,38423L,38424L,38425L,38426L,38427L,
93641 38428L,38429L,38430L,38431L,38432L,38433L,38434L,38435L,38436L,38437L,
93642 38438L,38439L,38440L,38441L,38442L,38443L,38444L,38445L,38446L,38447L,
93643 38448L,38449L,38450L,38451L,38452L,38453L,38454L,38455L,38456L,38457L,
93644 38458L,38459L,38460L,38461L,38462L,38463L,38464L,38465L,38466L,38467L,
93645 38468L,38469L,38470L,38471L,38472L,38473L,38474L,38475L,38476L,38477L,
93646 38478L,38479L,38480L,38481L,38482L,38483L,38484L,38485L,38486L,38487L,
93647 38488L,38489L,38490L,38491L,38492L,38493L,38494L,38495L,38496L,38497L,
93648 38498L,38499L,38500L,38501L,38502L,38503L,38504L,38505L,38506L,38507L,
93649 38508L,38509L,38510L,38511L,38512L,38513L,38514L,38515L,38516L,38517L,
93650 38518L,38519L,38520L,38521L,38522L,38523L,38524L,38525L,38526L,38527L,
93651 38528L,38529L,38530L,38531L,38532L,38533L,38534L,38535L,38536L,38537L,
93652 38538L,38539L,38540L,38541L,38542L,38543L,38544L,38545L,38546L,38547L,
93653 38548L,38549L,38550L,38551L,38552L,38553L,38554L,38555L,38556L,38557L,
93654 38558L,38559L,38560L,38561L,38562L,38563L,38564L,38565L,38566L,38567L,
93655 38568L,38569L,38570L,38571L,38572L,38573L,38574L,38575L,38576L,38577L,
93656 38578L,38579L,38580L,38581L,38582L,38583L,38584L,38585L,38586L,38587L,
93657 38588L,38589L,38590L,38591L,38592L,38593L,38594L,38595L,38596L,38597L,
93658 38598L,38599L,38600L,38601L,38602L,38603L,38604L,38605L,38606L,38607L,
93659 38608L,38609L,38610L,38611L,38612L,38613L,38614L,38615L,38616L,38617L,
93660 38618L,38619L,38620L,38621L,38622L,38623L,38624L,38625L,38626L,38627L,
93661 38628L,38629L,38630L,38631L,38632L,38633L,38634L,38635L,38636L,38637L,
93662 38638L,38639L,38640L,38641L,38642L,38643L,38644L,38645L,38646L,38647L,
93663 38648L,38649L,38650L,38651L,38652L,38653L,38654L,38655L,38656L,38657L,
93664 38658L,38659L,38660L,38661L,38662L,38663L,38664L,38665L,38666L,38667L,
93665 38668L,38669L,38670L,38671L,38672L,38673L,38674L,38675L,38676L,38677L,
93666 38678L,38679L,38680L,38681L,38682L,38683L,38684L,38685L,38686L,38687L,
93667 38688L,38689L,38690L,38691L,38692L,38693L,38694L,38695L,38696L,38697L,
93668 38698L,38699L,38700L,38701L,38702L,38703L,38704L,38705L,38706L,38707L,
93669 38708L,38709L,38710L,38711L,38712L,38713L,38714L,38715L,38716L,38717L,
93670 38718L,38719L,38720L,38721L,38722L,38723L,38724L,38725L,38726L,38727L,
93671 38728L,38729L,38730L,38731L,38732L,38733L,38734L,38735L,38736L,38737L,
93672 38738L,38739L,38740L,38741L,38742L,38743L,38744L,38745L,38746L,38747L,
93673 38748L,38749L,38750L,38751L,38752L,38753L,38754L,38755L,38756L,38757L,
93674 38758L,38759L,38760L,38761L,38762L,38763L,38764L,38765L,38766L,38767L,
93675 38768L,38769L,38770L,38771L,38772L,38773L,38774L,38775L,38776L,38777L,
93676 38778L,38779L,38780L,38781L,38782L,38783L,38784L,38785L,38786L,38787L,
93677 38788L,38789L,38790L,38791L,38792L,38793L,38794L,38795L,38796L,38797L,
93678 38798L,38799L,38800L,38801L,38802L,38803L,38804L,38805L,38806L,38807L,
93679 38808L,38809L,38810L,38811L,38812L,38813L,38814L,38815L,38816L,38817L,
93680 38818L,38819L,38820L,38821L,38822L,38823L,38824L,38825L,38826L,38827L,
93681 38828L,38829L,38830L,38831L,38832L,38833L,38834L,38835L,38836L,38837L,
93682 38838L,38839L,38840L,38841L,38842L,38843L,38844L,38845L,38846L,38847L,
93683 38848L,38849L,38850L,38851L,38852L,38853L,38854L,38855L,38856L,38857L,
93684 38858L,38859L,38860L,38861L,38862L,38863L,38864L,38865L,38866L,38867L,
93685 38868L,38869L,38870L,38871L,38872L,38873L,38874L,38875L,38876L,38877L,
93686 38878L,38879L,38880L,38881L,38882L,38883L,38884L,38885L,38886L,38887L,
93687 38888L,38889L,38890L,38891L,38892L,38893L,38894L,38895L,38896L,38897L,
93688 38898L,38899L,38900L,38901L,38902L,38903L,38904L,38905L,38906L,38907L,
93689 38908L,38909L,38910L,38911L,38912L,38913L,38914L,38915L,38916L,38917L,
93690 38918L,38919L,38920L,38921L,38922L,38923L,38924L,38925L,38926L,38927L,
93691 38928L,38929L,38930L,38931L,38932L,38933L,38934L,38935L,38936L,38937L,
93692 38938L,38939L,38940L,38941L,38942L,38943L,38944L,38945L,38946L,38947L,
93693 38948L,38949L,38950L,38951L,38952L,38953L,38954L,38955L,38956L,38957L,
93694 38958L,38959L,38960L,38961L,38962L,38963L,38964L,38965L,38966L,38967L,
93695 38968L,38969L,38970L,38971L,38972L,38973L,38974L,38975L,38976L,38977L,
93696 38978L,38979L,38980L,38981L,38982L,38983L,38984L,38985L,38986L,38987L,
93697 38988L,38989L,38990L,38991L,38992L,38993L,38994L,38995L,38996L,38997L,
93698 38998L,38999L,39000L,39001L,39002L,39003L,39004L,39005L,39006L,39007L,
93699 39008L,39009L,39010L,39011L,39012L,39013L,39014L,39015L,39016L,39017L,
93700 39018L,39019L,39020L,39021L,39022L,39023L,39024L,39025L,39026L,39027L,
93701 39028L,39029L,39030L,39031L,39032L,39033L,39034L,39035L,39036L,39037L,
93702 39038L,39039L,39040L,39041L,39042L,39043L,39044L,39045L,39046L,39047L,
93703 39048L,39049L,39050L,39051L,39052L,39053L,39054L,39055L,39056L,39057L,
93704 39058L,39059L,39060L,39061L,39062L,39063L,39064L,39065L,39066L,39067L,
93705 39068L,39069L,39070L,39071L,39072L,39073L,39074L,39075L,39076L,39077L,
93706 39078L,39079L,39080L,39081L,39082L,39083L,39084L,39085L,39086L,39087L,
93707 39088L,39089L,39090L,39091L,39092L,39093L,39094L,39095L,39096L,39097L,
93708 39098L,39099L,39100L,39101L,39102L,39103L,39104L,39105L,39106L,39107L,
93709 39108L,39109L,39110L,39111L,39112L,39113L,39114L,39115L,39116L,39117L,
93710 39118L,39119L,39120L,39121L,39122L,39123L,39124L,39125L,39126L,39127L,
93711 39128L,39129L,39130L,39131L,39132L,39133L,39134L,39135L,39136L,39137L,
93712 39138L,39139L,39140L,39141L,39142L,39143L,39144L,39145L,39146L,39147L,
93713 39148L,39149L,39150L,39151L,39152L,39153L,39154L,39155L,39156L,39157L,
93714 39158L,39159L,39160L,39161L,39162L,39163L,39164L,39165L,39166L,39167L,
93715 39168L,39169L,39170L,39171L,39172L,39173L,39174L,39175L,39176L,39177L,
93716 39178L,39179L,39180L,39181L,39182L,39183L,39184L,39185L,39186L,39187L,
93717 39188L,39189L,39190L,39191L,39192L,39193L,39194L,39195L,39196L,39197L,
93718 39198L,39199L,39200L,39201L,39202L,39203L,39204L,39205L,39206L,39207L,
93719 39208L,39209L,39210L,39211L,39212L,39213L,39214L,39215L,39216L,39217L,
93720 39218L,39219L,39220L,39221L,39222L,39223L,39224L,39225L,39226L,39227L,
93721 39228L,39229L,39230L,39231L,39232L,39233L,39234L,39235L,39236L,39237L,
93722 39238L,39239L,39240L,39241L,39242L,39243L,39244L,39245L,39246L,39247L,
93723 39248L,39249L,39250L,39251L,39252L,39253L,39254L,39255L,39256L,39257L,
93724 39258L,39259L,39260L,39261L,39262L,39263L,39264L,39265L,39266L,39267L,
93725 39268L,39269L,39270L,39271L,39272L,39273L,39274L,39275L,39276L,39277L,
93726 39278L,39279L,39280L,39281L,39282L,39283L,39284L,39285L,39286L,39287L,
93727 39288L,39289L,39290L,39291L,39292L,39293L,39294L,39295L,39296L,39297L,
93728 39298L,39299L,39300L,39301L,39302L,39303L,39304L,39305L,39306L,39307L,
93729 39308L,39309L,39310L,39311L,39312L,39313L,39314L,39315L,39316L,39317L,
93730 39318L,39319L,39320L,39321L,39322L,39323L,39324L,39325L,39326L,39327L,
93731 39328L,39329L,39330L,39331L,39332L,39333L,39334L,39335L,39336L,39337L,
93732 39338L,39339L,39340L,39341L,39342L,39343L,39344L,39345L,39346L,39347L,
93733 39348L,39349L,39350L,39351L,39352L,39353L,39354L,39355L,39356L,39357L,
93734 39358L,39359L,39360L,39361L,39362L,39363L,39364L,39365L,39366L,39367L,
93735 39368L,39369L,39370L,39371L,39372L,39373L,39374L,39375L,39376L,39377L,
93736 39378L,39379L,39380L,39381L,39382L,39383L,39384L,39385L,39386L,39387L,
93737 39388L,39389L,39390L,39391L,39392L,39393L,39394L,39395L,39396L,39397L,
93738 39398L,39399L,39400L,39401L,39402L,39403L,39404L,39405L,39406L,39407L,
93739 39408L,39409L,39410L,39411L,39412L,39413L,39414L,39415L,39416L,39417L,
93740 39418L,39419L,39420L,39421L,39422L,39423L,39424L,39425L,39426L,39427L,
93741 39428L,39429L,39430L,39431L,39432L,39433L,39434L,39435L,39436L,39437L,
93742 39438L,39439L,39440L,39441L,39442L,39443L,39444L,39445L,39446L,39447L,
93743 39448L,39449L,39450L,39451L,39452L,39453L,39454L,39455L,39456L,39457L,
93744 39458L,39459L,39460L,39461L,39462L,39463L,39464L,39465L,39466L,39467L,
93745 39468L,39469L,39470L,39471L,39472L,39473L,39474L,39475L,39476L,39477L,
93746 39478L,39479L,39480L,39481L,39482L,39483L,39484L,39485L,39486L,39487L,
93747 39488L,39489L,39490L,39491L,39492L,39493L,39494L,39495L,39496L,39497L,
93748 39498L,39499L,39500L,39501L,39502L,39503L,39504L,39505L,39506L,39507L,
93749 39508L,39509L,39510L,39511L,39512L,39513L,39514L,39515L,39516L,39517L,
93750 39518L,39519L,39520L,39521L,39522L,39523L,39524L,39525L,39526L,39527L,
93751 39528L,39529L,39530L,39531L,39532L,39533L,39534L,39535L,39536L,39537L,
93752 39538L,39539L,39540L,39541L,39542L,39543L,39544L,39545L,39546L,39547L,
93753 39548L,39549L,39550L,39551L,39552L,39553L,39554L,39555L,39556L,39557L,
93754 39558L,39559L,39560L,39561L,39562L,39563L,39564L,39565L,39566L,39567L,
93755 39568L,39569L,39570L,39571L,39572L,39573L,39574L,39575L,39576L,39577L,
93756 39578L,39579L,39580L,39581L,39582L,39583L,39584L,39585L,39586L,39587L,
93757 39588L,39589L,39590L,39591L,39592L,39593L,39594L,39595L,39596L,39597L,
93758 39598L,39599L,39600L,39601L,39602L,39603L,39604L,39605L,39606L,39607L,
93759 39608L,39609L,39610L,39611L,39612L,39613L,39614L,39615L,39616L,39617L,
93760 39618L,39619L,39620L,39621L,39622L,39623L,39624L,39625L,39626L,39627L,
93761 39628L,39629L,39630L,39631L,39632L,39633L,39634L,39635L,39636L,39637L,
93762 39638L,39639L,39640L,39641L,39642L,39643L,39644L,39645L,39646L,39647L,
93763 39648L,39649L,39650L,39651L,39652L,39653L,39654L,39655L,39656L,39657L,
93764 39658L,39659L,39660L,39661L,39662L,39663L,39664L,39665L,39666L,39667L,
93765 39668L,39669L,39670L,39671L,39672L,39673L,39674L,39675L,39676L,39677L,
93766 39678L,39679L,39680L,39681L,39682L,39683L,39684L,39685L,39686L,39687L,
93767 39688L,39689L,39690L,39691L,39692L,39693L,39694L,39695L,39696L,39697L,
93768 39698L,39699L,39700L,39701L,39702L,39703L,39704L,39705L,39706L,39707L,
93769 39708L,39709L,39710L,39711L,39712L,39713L,39714L,39715L,39716L,39717L,
93770 39718L,39719L,39720L,39721L,39722L,39723L,39724L,39725L,39726L,39727L,
93771 39728L,39729L,39730L,39731L,39732L,39733L,39734L,39735L,39736L,39737L,
93772 39738L,39739L,39740L,39741L,39742L,39743L,39744L,39745L,39746L,39747L,
93773 39748L,39749L,39750L,39751L,39752L,39753L,39754L,39755L,39756L,39757L,
93774 39758L,39759L,39760L,39761L,39762L,39763L,39764L,39765L,39766L,39767L,
93775 39768L,39769L,39770L,39771L,39772L,39773L,39774L,39775L,39776L,39777L,
93776 39778L,39779L,39780L,39781L,39782L,39783L,39784L,39785L,39786L,39787L,
93777 39788L,39789L,39790L,39791L,39792L,39793L,39794L,39795L,39796L,39797L,
93778 39798L,39799L,39800L,39801L,39802L,39803L,39804L,39805L,39806L,39807L,
93779 39808L,39809L,39810L,39811L,39812L,39813L,39814L,39815L,39816L,39817L,
93780 39818L,39819L,39820L,39821L,39822L,39823L,39824L,39825L,39826L,39827L,
93781 39828L,39829L,39830L,39831L,39832L,39833L,39834L,39835L,39836L,39837L,
93782 39838L,39839L,39840L,39841L,39842L,39843L,39844L,39845L,39846L,39847L,
93783 39848L,39849L,39850L,39851L,39852L,39853L,39854L,39855L,39856L,39857L,
93784 39858L,39859L,39860L,39861L,39862L,39863L,39864L,39865L,39866L,39867L,
93785 39868L,39869L,39870L,39871L,39872L,39873L,39874L,39875L,39876L,39877L,
93786 39878L,39879L,39880L,39881L,39882L,39883L,39884L,39885L,39886L,39887L,
93787 39888L,39889L,39890L,39891L,39892L,39893L,39894L,39895L,39896L,39897L,
93788 39898L,39899L,39900L,39901L,39902L,39903L,39904L,39905L,39906L,39907L,
93789 39908L,39909L,39910L,39911L,39912L,39913L,39914L,39915L,39916L,39917L,
93790 39918L,39919L,39920L,39921L,39922L,39923L,39924L,39925L,39926L,39927L,
93791 39928L,39929L,39930L,39931L,39932L,39933L,39934L,39935L,39936L,39937L,
93792 39938L,39939L,39940L,39941L,39942L,39943L,39944L,39945L,39946L,39947L,
93793 39948L,39949L,39950L,39951L,39952L,39953L,39954L,39955L,39956L,39957L,
93794 39958L,39959L,39960L,39961L,39962L,39963L,39964L,39965L,39966L,39967L,
93795 39968L,39969L,39970L,39971L,39972L,39973L,39974L,39975L,39976L,39977L,
93796 39978L,39979L,39980L,39981L,39982L,39983L,39984L,39985L,39986L,39987L,
93797 39988L,39989L,39990L,39991L,39992L,39993L,39994L,39995L,39996L,39997L,
93798 39998L,39999L,40000L,40001L,40002L,40003L,40004L,40005L,40006L,40007L,
93799 40008L,40009L,40010L,40011L,40012L,40013L,40014L,40015L,40016L,40017L,
93800 40018L,40019L,40020L,40021L,40022L,40023L,40024L,40025L,40026L,40027L,
93801 40028L,40029L,40030L,40031L,40032L,40033L,40034L,40035L,40036L,40037L,
93802 40038L,40039L,40040L,40041L,40042L,40043L,40044L,40045L,40046L,40047L,
93803 40048L,40049L,40050L,40051L,40052L,40053L,40054L,40055L,40056L,40057L,
93804 40058L,40059L,40060L,40061L,40062L,40063L,40064L,40065L,40066L,40067L,
93805 40068L,40069L,40070L,40071L,40072L,40073L,40074L,40075L,40076L,40077L,
93806 40078L,40079L,40080L,40081L,40082L,40083L,40084L,40085L,40086L,40087L,
93807 40088L,40089L,40090L,40091L,40092L,40093L,40094L,40095L,40096L,40097L,
93808 40098L,40099L,40100L,40101L,40102L,40103L,40104L,40105L,40106L,40107L,
93809 40108L,40109L,40110L,40111L,40112L,40113L,40114L,40115L,40116L,40117L,
93810 40118L,40119L,40120L,40121L,40122L,40123L,40124L,40125L,40126L,40127L,
93811 40128L,40129L,40130L,40131L,40132L,40133L,40134L,40135L,40136L,40137L,
93812 40138L,40139L,40140L,40141L,40142L,40143L,40144L,40145L,40146L,40147L,
93813 40148L,40149L,40150L,40151L,40152L,40153L,40154L,40155L,40156L,40157L,
93814 40158L,40159L,40160L,40161L,40162L,40163L,40164L,40165L,40166L,40167L,
93815 40168L,40169L,40170L,40171L,40172L,40173L,40174L,40175L,40176L,40177L,
93816 40178L,40179L,40180L,40181L,40182L,40183L,40184L,40185L,40186L,40187L,
93817 40188L,40189L,40190L,40191L,40192L,40193L,40194L,40195L,40196L,40197L,
93818 40198L,40199L,40200L,40201L,40202L,40203L,40204L,40205L,40206L,40207L,
93819 40208L,40209L,40210L,40211L,40212L,40213L,40214L,40215L,40216L,40217L,
93820 40218L,40219L,40220L,40221L,40222L,40223L,40224L,40225L,40226L,40227L,
93821 40228L,40229L,40230L,40231L,40232L,40233L,40234L,40235L,40236L,40237L,
93822 40238L,40239L,40240L,40241L,40242L,40243L,40244L,40245L,40246L,40247L,
93823 40248L,40249L,40250L,40251L,40252L,40253L,40254L,40255L,40256L,40257L,
93824 40258L,40259L,40260L,40261L,40262L,40263L,40264L,40265L,40266L,40267L,
93825 40268L,40269L,40270L,40271L,40272L,40273L,40274L,40275L,40276L,40277L,
93826 40278L,40279L,40280L,40281L,40282L,40283L,40284L,40285L,40286L,40287L,
93827 40288L,40289L,40290L,40291L,40292L,40293L,40294L,40295L,40296L,40297L,
93828 40298L,40299L,40300L,40301L,40302L,40303L,40304L,40305L,40306L,40307L,
93829 40308L,40309L,40310L,40311L,40312L,40313L,40314L,40315L,40316L,40317L,
93830 40318L,40319L,40320L,40321L,40322L,40323L,40324L,40325L,40326L,40327L,
93831 40328L,40329L,40330L,40331L,40332L,40333L,40334L,40335L,40336L,40337L,
93832 40338L,40339L,40340L,40341L,40342L,40343L,40344L,40345L,40346L,40347L,
93833 40348L,40349L,40350L,40351L,40352L,40353L,40354L,40355L,40356L,40357L,
93834 40358L,40359L,40360L,40361L,40362L,40363L,40364L,40365L,40366L,40367L,
93835 40368L,40369L,40370L,40371L,40372L,40373L,40374L,40375L,40376L,40377L,
93836 40378L,40379L,40380L,40381L,40382L,40383L,40384L,40385L,40386L,40387L,
93837 40388L,40389L,40390L,40391L,40392L,40393L,40394L,40395L,40396L,40397L,
93838 40398L,40399L,40400L,40401L,40402L,40403L,40404L,40405L,40406L,40407L,
93839 40408L,40409L,40410L,40411L,40412L,40413L,40414L,40415L,40416L,40417L,
93840 40418L,40419L,40420L,40421L,40422L,40423L,40424L,40425L,40426L,40427L,
93841 40428L,40429L,40430L,40431L,40432L,40433L,40434L,40435L,40436L,40437L,
93842 40438L,40439L,40440L,40441L,40442L,40443L,40444L,40445L,40446L,40447L,
93843 40448L,40449L,40450L,40451L,40452L,40453L,40454L,40455L,40456L,40457L,
93844 40458L,40459L,40460L,40461L,40462L,40463L,40464L,40465L,40466L,40467L,
93845 40468L,40469L,40470L,40471L,40472L,40473L,40474L,40475L,40476L,40477L,
93846 40478L,40479L,40480L,40481L,40482L,40483L,40484L,40485L,40486L,40487L,
93847 40488L,40489L,40490L,40491L,40492L,40493L,40494L,40495L,40496L,40497L,
93848 40498L,40499L,40500L,40501L,40502L,40503L,40504L,40505L,40506L,40507L,
93849 40508L,40509L,40510L,40511L,40512L,40513L,40514L,40515L,40516L,40517L,
93850 40518L,40519L,40520L,40521L,40522L,40523L,40524L,40525L,40526L,40527L,
93851 40528L,40529L,40530L,40531L,40532L,40533L,40534L,40535L,40536L,40537L,
93852 40538L,40539L,40540L,40541L,40542L,40543L,40544L,40545L,40546L,40547L,
93853 40548L,40549L,40550L,40551L,40552L,40553L,40554L,40555L,40556L,40557L,
93854 40558L,40559L,40560L,40561L,40562L,40563L,40564L,40565L,40566L,40567L,
93855 40568L,40569L,40570L,40571L,40572L,40573L,40574L,40575L,40576L,40577L,
93856 40578L,40579L,40580L,40581L,40582L,40583L,40584L,40585L,40586L,40587L,
93857 40588L,40589L,40590L,40591L,40592L,40593L,40594L,40595L,40596L,40597L,
93858 40598L,40599L,40600L,40601L,40602L,40603L,40604L,40605L,40606L,40607L,
93859 40608L,40609L,40610L,40611L,40612L,40613L,40614L,40615L,40616L,40617L,
93860 40618L,40619L,40620L,40621L,40622L,40623L,40624L,40625L,40626L,40627L,
93861 40628L,40629L,40630L,40631L,40632L,40633L,40634L,40635L,40636L,40637L,
93862 40638L,40639L,40640L,40641L,40642L,40643L,40644L,40645L,40646L,40647L,
93863 40648L,40649L,40650L,40651L,40652L,40653L,40654L,40655L,40656L,40657L,
93864 40658L,40659L,40660L,40661L,40662L,40663L,40664L,40665L,40666L,40667L,
93865 40668L,40669L,40670L,40671L,40672L,40673L,40674L,40675L,40676L,40677L,
93866 40678L,40679L,40680L,40681L,40682L,40683L,40684L,40685L,40686L,40687L,
93867 40688L,40689L,40690L,40691L,40692L,40693L,40694L,40695L,40696L,40697L,
93868 40698L,40699L,40700L,40701L,40702L,40703L,40704L,40705L,40706L,40707L,
93869 40708L,40709L,40710L,40711L,40712L,40713L,40714L,40715L,40716L,40717L,
93870 40718L,40719L,40720L,40721L,40722L,40723L,40724L,40725L,40726L,40727L,
93871 40728L,40729L,40730L,40731L,40732L,40733L,40734L,40735L,40736L,40737L,
93872 40738L,40739L,40740L,40741L,40742L,40743L,40744L,40745L,40746L,40747L,
93873 40748L,40749L,40750L,40751L,40752L,40753L,40754L,40755L,40756L,40757L,
93874 40758L,40759L,40760L,40761L,40762L,40763L,40764L,40765L,40766L,40767L,
93875 40768L,40769L,40770L,40771L,40772L,40773L,40774L,40775L,40776L,40777L,
93876 40778L,40779L,40780L,40781L,40782L,40783L,40784L,40785L,40786L,40787L,
93877 40788L,40789L,40790L,40791L,40792L,40793L,40794L,40795L,40796L,40797L,
93878 40798L,40799L,40800L,40801L,40802L,40803L,40804L,40805L,40806L,40807L,
93879 40808L,40809L,40810L,40811L,40812L,40813L,40814L,40815L,40816L,40817L,
93880 40818L,40819L,40820L,40821L,40822L,40823L,40824L,40825L,40826L,40827L,
93881 40828L,40829L,40830L,40831L,40832L,40833L,40834L,40835L,40836L,40837L,
93882 40838L,40839L,40840L,40841L,40842L,40843L,40844L,40845L,40846L,40847L,
93883 40848L,40849L,40850L,40851L,40852L,40853L,40854L,40855L,40856L,40857L,
93884 40858L,40859L,40860L,40861L,40862L,40863L,40864L,40865L,40866L,40867L,
93885 40868L,40869L,40870L,40871L,40872L,40873L,40874L,40875L,40876L,40877L,
93886 40878L,40879L,40880L,40881L,40882L,40883L,40884L,40885L,40886L,40887L,
93887 40888L,40889L,40890L,40891L,40892L,40893L,40894L,40895L,40896L,40897L,
93888 40898L,40899L,40900L,40901L,40902L,40903L,40904L,40905L,40906L,40907L,
93889 40908L,40909L,40910L,40911L,40912L,40913L,40914L,40915L,40916L,40917L,
93890 40918L,40919L,40920L,40921L,40922L,40923L,40924L,40925L,40926L,40927L,
93891 40928L,40929L,40930L,40931L,40932L,40933L,40934L,40935L,40936L,40937L,
93892 40938L,40939L,40940L,40941L,40942L,40943L,40944L,40945L,40946L,40947L,
93893 40948L,40949L,40950L,40951L,40952L,40953L,40954L,40955L,40956L,40957L,
93894 40958L,40959L,40960L,40961L,40962L,40963L,40964L,40965L,40966L,40967L,
93895 40968L,40969L,40970L,40971L,40972L,40973L,40974L,40975L,40976L,40977L,
93896 40978L,40979L,40980L,40981L,40982L,40983L,40984L,40985L,40986L,40987L,
93897 40988L,40989L,40990L,40991L,40992L,40993L,40994L,40995L,40996L,40997L,
93898 40998L,40999L,41000L,41001L,41002L,41003L,41004L,41005L,41006L,41007L,
93899 41008L,41009L,41010L,41011L,41012L,41013L,41014L,41015L,41016L,41017L,
93900 41018L,41019L,41020L,41021L,41022L,41023L,41024L,41025L,41026L,41027L,
93901 41028L,41029L,41030L,41031L,41032L,41033L,41034L,41035L,41036L,41037L,
93902 41038L,41039L,41040L,41041L,41042L,41043L,41044L,41045L,41046L,41047L,
93903 41048L,41049L,41050L,41051L,41052L,41053L,41054L,41055L,41056L,41057L,
93904 41058L,41059L,41060L,41061L,41062L,41063L,41064L,41065L,41066L,41067L,
93905 41068L,41069L,41070L,41071L,41072L,41073L,41074L,41075L,41076L,41077L,
93906 41078L,41079L,41080L,41081L,41082L,41083L,41084L,41085L,41086L,41087L,
93907 41088L,41089L,41090L,41091L,41092L,41093L,41094L,41095L,41096L,41097L,
93908 41098L,41099L,41100L,41101L,41102L,41103L,41104L,41105L,41106L,41107L,
93909 41108L,41109L,41110L,41111L,41112L,41113L,41114L,41115L,41116L,41117L,
93910 41118L,41119L,41120L,41121L,41122L,41123L,41124L,41125L,41126L,41127L,
93911 41128L,41129L,41130L,41131L,41132L,41133L,41134L,41135L,41136L,41137L,
93912 41138L,41139L,41140L,41141L,41142L,41143L,41144L,41145L,41146L,41147L,
93913 41148L,41149L,41150L,41151L,41152L,41153L,41154L,41155L,41156L,41157L,
93914 41158L,41159L,41160L,41161L,41162L,41163L,41164L,41165L,41166L,41167L,
93915 41168L,41169L,41170L,41171L,41172L,41173L,41174L,41175L,41176L,41177L,
93916 41178L,41179L,41180L,41181L,41182L,41183L,41184L,41185L,41186L,41187L,
93917 41188L,41189L,41190L,41191L,41192L,41193L,41194L,41195L,41196L,41197L,
93918 41198L,41199L,41200L,41201L,41202L,41203L,41204L,41205L,41206L,41207L,
93919 41208L,41209L,41210L,41211L,41212L,41213L,41214L,41215L,41216L,41217L,
93920 41218L,41219L,41220L,41221L,41222L,41223L,41224L,41225L,41226L,41227L,
93921 41228L,41229L,41230L,41231L,41232L,41233L,41234L,41235L,41236L,41237L,
93922 41238L,41239L,41240L,41241L,41242L,41243L,41244L,41245L,41246L,41247L,
93923 41248L,41249L,41250L,41251L,41252L,41253L,41254L,41255L,41256L,41257L,
93924 41258L,41259L,41260L,41261L,41262L,41263L,41264L,41265L,41266L,41267L,
93925 41268L,41269L,41270L,41271L,41272L,41273L,41274L,41275L,41276L,41277L,
93926 41278L,41279L,41280L,41281L,41282L,41283L,41284L,41285L,41286L,41287L,
93927 41288L,41289L,41290L,41291L,41292L,41293L,41294L,41295L,41296L,41297L,
93928 41298L,41299L,41300L,41301L,41302L,41303L,41304L,41305L,41306L,41307L,
93929 41308L,41309L,41310L,41311L,41312L,41313L,41314L,41315L,41316L,41317L,
93930 41318L,41319L,41320L,41321L,41322L,41323L,41324L,41325L,41326L,41327L,
93931 41328L,41329L,41330L,41331L,41332L,41333L,41334L,41335L,41336L,41337L,
93932 41338L,41339L,41340L,41341L,41342L,41343L,41344L,41345L,41346L,41347L,
93933 41348L,41349L,41350L,41351L,41352L,41353L,41354L,41355L,41356L,41357L,
93934 41358L,41359L,41360L,41361L,41362L,41363L,41364L,41365L,41366L,41367L,
93935 41368L,41369L,41370L,41371L,41372L,41373L,41374L,41375L,41376L,41377L,
93936 41378L,41379L,41380L,41381L,41382L,41383L,41384L,41385L,41386L,41387L,
93937 41388L,41389L,41390L,41391L,41392L,41393L,41394L,41395L,41396L,41397L,
93938 41398L,41399L,41400L,41401L,41402L,41403L,41404L,41405L,41406L,41407L,
93939 41408L,41409L,41410L,41411L,41412L,41413L,41414L,41415L,41416L,41417L,
93940 41418L,41419L,41420L,41421L,41422L,41423L,41424L,41425L,41426L,41427L,
93941 41428L,41429L,41430L,41431L,41432L,41433L,41434L,41435L,41436L,41437L,
93942 41438L,41439L,41440L,41441L,41442L,41443L,41444L,41445L,41446L,41447L,
93943 41448L,41449L,41450L,41451L,41452L,41453L,41454L,41455L,41456L,41457L,
93944 41458L,41459L,41460L,41461L,41462L,41463L,41464L,41465L,41466L,41467L,
93945 41468L,41469L,41470L,41471L,41472L,41473L,41474L,41475L,41476L,41477L,
93946 41478L,41479L,41480L,41481L,41482L,41483L,41484L,41485L,41486L,41487L,
93947 41488L,41489L,41490L,41491L,41492L,41493L,41494L,41495L,41496L,41497L,
93948 41498L,41499L,41500L,41501L,41502L,41503L,41504L,41505L,41506L,41507L,
93949 41508L,41509L,41510L,41511L,41512L,41513L,41514L,41515L,41516L,41517L,
93950 41518L,41519L,41520L,41521L,41522L,41523L,41524L,41525L,41526L,41527L,
93951 41528L,41529L,41530L,41531L,41532L,41533L,41534L,41535L,41536L,41537L,
93952 41538L,41539L,41540L,41541L,41542L,41543L,41544L,41545L,41546L,41547L,
93953 41548L,41549L,41550L,41551L,41552L,41553L,41554L,41555L,41556L,41557L,
93954 41558L,41559L,41560L,41561L,41562L,41563L,41564L,41565L,41566L,41567L,
93955 41568L,41569L,41570L,41571L,41572L,41573L,41574L,41575L,41576L,41577L,
93956 41578L,41579L,41580L,41581L,41582L,41583L,41584L,41585L,41586L,41587L,
93957 41588L,41589L,41590L,41591L,41592L,41593L,41594L,41595L,41596L,41597L,
93958 41598L,41599L,41600L,41601L,41602L,41603L,41604L,41605L,41606L,41607L,
93959 41608L,41609L,41610L,41611L,41612L,41613L,41614L,41615L,41616L,41617L,
93960 41618L,41619L,41620L,41621L,41622L,41623L,41624L,41625L,41626L,41627L,
93961 41628L,41629L,41630L,41631L,41632L,41633L,41634L,41635L,41636L,41637L,
93962 41638L,41639L,41640L,41641L,41642L,41643L,41644L,41645L,41646L,41647L,
93963 41648L,41649L,41650L,41651L,41652L,41653L,41654L,41655L,41656L,41657L,
93964 41658L,41659L,41660L,41661L,41662L,41663L,41664L,41665L,41666L,41667L,
93965 41668L,41669L,41670L,41671L,41672L,41673L,41674L,41675L,41676L,41677L,
93966 41678L,41679L,41680L,41681L,41682L,41683L,41684L,41685L,41686L,41687L,
93967 41688L,41689L,41690L,41691L,41692L,41693L,41694L,41695L,41696L,41697L,
93968 41698L,41699L,41700L,41701L,41702L,41703L,41704L,41705L,41706L,41707L,
93969 41708L,41709L,41710L,41711L,41712L,41713L,41714L,41715L,41716L,41717L,
93970 41718L,41719L,41720L,41721L,41722L,41723L,41724L,41725L,41726L,41727L,
93971 41728L,41729L,41730L,41731L,41732L,41733L,41734L,41735L,41736L,41737L,
93972 41738L,41739L,41740L,41741L,41742L,41743L,41744L,41745L,41746L,41747L,
93973 41748L,41749L,41750L,41751L,41752L,41753L,41754L,41755L,41756L,41757L,
93974 41758L,41759L,41760L,41761L,41762L,41763L,41764L,41765L,41766L,41767L,
93975 41768L,41769L,41770L,41771L,41772L,41773L,41774L,41775L,41776L,41777L,
93976 41778L,41779L,41780L,41781L,41782L,41783L,41784L,41785L,41786L,41787L,
93977 41788L,41789L,41790L,41791L,41792L,41793L,41794L,41795L,41796L,41797L,
93978 41798L,41799L,41800L,41801L,41802L,41803L,41804L,41805L,41806L,41807L,
93979 41808L,41809L,41810L,41811L,41812L,41813L,41814L,41815L,41816L,41817L,
93980 41818L,41819L,41820L,41821L,41822L,41823L,41824L,41825L,41826L,41827L,
93981 41828L,41829L,41830L,41831L,41832L,41833L,41834L,41835L,41836L,41837L,
93982 41838L,41839L,41840L,41841L,41842L,41843L,41844L,41845L,41846L,41847L,
93983 41848L,41849L,41850L,41851L,41852L,41853L,41854L,41855L,41856L,41857L,
93984 41858L,41859L,41860L,41861L,41862L,41863L,41864L,41865L,41866L,41867L,
93985 41868L,41869L,41870L,41871L,41872L,41873L,41874L,41875L,41876L,41877L,
93986 41878L,41879L,41880L,41881L,41882L,41883L,41884L,41885L,41886L,41887L,
93987 41888L,41889L,41890L,41891L,41892L,41893L,41894L,41895L,41896L,41897L,
93988 41898L,41899L,41900L,41901L,41902L,41903L,41904L,41905L,41906L,41907L,
93989 41908L,41909L,41910L,41911L,41912L,41913L,41914L,41915L,41916L,41917L,
93990 41918L,41919L,41920L,41921L,41922L,41923L,41924L,41925L,41926L,41927L,
93991 41928L,41929L,41930L,41931L,41932L,41933L,41934L,41935L,41936L,41937L,
93992 41938L,41939L,41940L,41941L,41942L,41943L,41944L,41945L,41946L,41947L,
93993 41948L,41949L,41950L,41951L,41952L,41953L,41954L,41955L,41956L,41957L,
93994 41958L,41959L,41960L,41961L,41962L,41963L,41964L,41965L,41966L,41967L,
93995 41968L,41969L,41970L,41971L,41972L,41973L,41974L,41975L,41976L,41977L,
93996 41978L,41979L,41980L,41981L,41982L,41983L,41984L,41985L,41986L,41987L,
93997 41988L,41989L,41990L,41991L,41992L,41993L,41994L,41995L,41996L,41997L,
93998 41998L,41999L,42000L,42001L,42002L,42003L,42004L,42005L,42006L,42007L,
93999 42008L,42009L,42010L,42011L,42012L,42013L,42014L,42015L,42016L,42017L,
94000 42018L,42019L,42020L,42021L,42022L,42023L,42024L,42025L,42026L,42027L,
94001 42028L,42029L,42030L,42031L,42032L,42033L,42034L,42035L,42036L,42037L,
94002 42038L,42039L,42040L,42041L,42042L,42043L,42044L,42045L,42046L,42047L,
94003 42048L,42049L,42050L,42051L,42052L,42053L,42054L,42055L,42056L,42057L,
94004 42058L,42059L,42060L,42061L,42062L,42063L,42064L,42065L,42066L,42067L,
94005 42068L,42069L,42070L,42071L,42072L,42073L,42074L,42075L,42076L,42077L,
94006 42078L,42079L,42080L,42081L,42082L,42083L,42084L,42085L,42086L,42087L,
94007 42088L,42089L,42090L,42091L,42092L,42093L,42094L,42095L,42096L,42097L,
94008 42098L,42099L,42100L,42101L,42102L,42103L,42104L,42105L,42106L,42107L,
94009 42108L,42109L,42110L,42111L,42112L,42113L,42114L,42115L,42116L,42117L,
94010 42118L,42119L,42120L,42121L,42122L,42123L,42124L,42125L,42126L,42127L,
94011 42128L,42129L,42130L,42131L,42132L,42133L,42134L,42135L,42136L,42137L,
94012 42138L,42139L,42140L,42141L,42142L,42143L,42144L,42145L,42146L,42147L,
94013 42148L,42149L,42150L,42151L,42152L,42153L,42154L,42155L,42156L,42157L,
94014 42158L,42159L,42160L,42161L,42162L,42163L,42164L,42165L,42166L,42167L,
94015 42168L,42169L,42170L,42171L,42172L,42173L,42174L,42175L,42176L,42177L,
94016 42178L,42179L,42180L,42181L,42182L,42183L,42184L,42185L,42186L,42187L,
94017 42188L,42189L,42190L,42191L,42192L,42193L,42194L,42195L,42196L,42197L,
94018 42198L,42199L,42200L,42201L,42202L,42203L,42204L,42205L,42206L,42207L,
94019 42208L,42209L,42210L,42211L,42212L,42213L,42214L,42215L,42216L,42217L,
94020 42218L,42219L,42220L,42221L,42222L,42223L,42224L,42225L,42226L,42227L,
94021 42228L,42229L,42230L,42231L,42232L,42233L,42234L,42235L,42236L,42237L,
94022 42238L,42239L,42240L,42241L,42242L,42243L,42244L,42245L,42246L,42247L,
94023 42248L,42249L,42250L,42251L,42252L,42253L,42254L,42255L,42256L,42257L,
94024 42258L,42259L,42260L,42261L,42262L,42263L,42264L,42265L,42266L,42267L,
94025 42268L,42269L,42270L,42271L,42272L,42273L,42274L,42275L,42276L,42277L,
94026 42278L,42279L,42280L,42281L,42282L,42283L,42284L,42285L,42286L,42287L,
94027 42288L,42289L,42290L,42291L,42292L,42293L,42294L,42295L,42296L,42297L,
94028 42298L,42299L,42300L,42301L,42302L,42303L,42304L,42305L,42306L,42307L,
94029 42308L,42309L,42310L,42311L,42312L,42313L,42314L,42315L,42316L,42317L,
94030 42318L,42319L,42320L,42321L,42322L,42323L,42324L,42325L,42326L,42327L,
94031 42328L,42329L,42330L,42331L,42332L,42333L,42334L,42335L,42336L,42337L,
94032 42338L,42339L,42340L,42341L,42342L,42343L,42344L,42345L,42346L,42347L,
94033 42348L,42349L,42350L,42351L,42352L,42353L,42354L,42355L,42356L,42357L,
94034 42358L,42359L,42360L,42361L,42362L,42363L,42364L,42365L,42366L,42367L,
94035 42368L,42369L,42370L,42371L,42372L,42373L,42374L,42375L,42376L,42377L,
94036 42378L,42379L,42380L,42381L,42382L,42383L,42384L,42385L,42386L,42387L,
94037 42388L,42389L,42390L,42391L,42392L,42393L,42394L,42395L,42396L,42397L,
94038 42398L,42399L,42400L,42401L,42402L,42403L,42404L,42405L,42406L,42407L,
94039 42408L,42409L,42410L,42411L,42412L,42413L,42414L,42415L,42416L,42417L,
94040 42418L,42419L,42420L,42421L,42422L,42423L,42424L,42425L,42426L,42427L,
94041 42428L,42429L,42430L,42431L,42432L,42433L,42434L,42435L,42436L,42437L,
94042 42438L,42439L,42440L,42441L,42442L,42443L,42444L,42445L,42446L,42447L,
94043 42448L,42449L,42450L,42451L,42452L,42453L,42454L,42455L,42456L,42457L,
94044 42458L,42459L,42460L,42461L,42462L,42463L,42464L,42465L,42466L,42467L,
94045 42468L,42469L,42470L,42471L,42472L,42473L,42474L,42475L,42476L,42477L,
94046 42478L,42479L,42480L,42481L,42482L,42483L,42484L,42485L,42486L,42487L,
94047 42488L,42489L,42490L,42491L,42492L,42493L,42494L,42495L,42496L,42497L,
94048 42498L,42499L,42500L,42501L,42502L,42503L,42504L,42505L,42506L,42507L,
94049 42508L,42509L,42510L,42511L,42512L,42513L,42514L,42515L,42516L,42517L,
94050 42518L,42519L,42520L,42521L,42522L,42523L,42524L,42525L,42526L,42527L,
94051 42528L,42529L,42530L,42531L,42532L,42533L,42534L,42535L,42536L,42537L,
94052 42538L,42539L,42540L,42541L,42542L,42543L,42544L,42545L,42546L,42547L,
94053 42548L,42549L,42550L,42551L,42552L,42553L,42554L,42555L,42556L,42557L,
94054 42558L,42559L,42560L,42560L,42562L,42562L,42564L,42564L,42566L,42566L,
94055 42568L,42568L,42570L,42570L,42572L,42572L,42574L,42574L,42576L,42576L,
94056 42578L,42578L,42580L,42580L,42582L,42582L,42584L,42584L,42586L,42586L,
94057 42588L,42588L,42590L,42590L,42592L,42592L,42594L,42594L,42596L,42596L,
94058 42598L,42598L,42600L,42600L,42602L,42602L,42604L,42604L,42606L,42607L,
94059 42608L,42609L,42610L,42611L,42612L,42613L,42614L,42615L,42616L,42617L,
94060 42618L,42619L,42620L,42621L,42622L,42623L,42624L,42624L,42626L,42626L,
94061 42628L,42628L,42630L,42630L,42632L,42632L,42634L,42634L,42636L,42636L,
94062 42638L,42638L,42640L,42640L,42642L,42642L,42644L,42644L,42646L,42646L,
94063 42648L,42648L,42650L,42650L,42652L,42653L,42654L,42655L,42656L,42657L,
94064 42658L,42659L,42660L,42661L,42662L,42663L,42664L,42665L,42666L,42667L,
94065 42668L,42669L,42670L,42671L,42672L,42673L,42674L,42675L,42676L,42677L,
94066 42678L,42679L,42680L,42681L,42682L,42683L,42684L,42685L,42686L,42687L,
94067 42688L,42689L,42690L,42691L,42692L,42693L,42694L,42695L,42696L,42697L,
94068 42698L,42699L,42700L,42701L,42702L,42703L,42704L,42705L,42706L,42707L,
94069 42708L,42709L,42710L,42711L,42712L,42713L,42714L,42715L,42716L,42717L,
94070 42718L,42719L,42720L,42721L,42722L,42723L,42724L,42725L,42726L,42727L,
94071 42728L,42729L,42730L,42731L,42732L,42733L,42734L,42735L,42736L,42737L,
94072 42738L,42739L,42740L,42741L,42742L,42743L,42744L,42745L,42746L,42747L,
94073 42748L,42749L,42750L,42751L,42752L,42753L,42754L,42755L,42756L,42757L,
94074 42758L,42759L,42760L,42761L,42762L,42763L,42764L,42765L,42766L,42767L,
94075 42768L,42769L,42770L,42771L,42772L,42773L,42774L,42775L,42776L,42777L,
94076 42778L,42779L,42780L,42781L,42782L,42783L,42784L,42785L,42786L,42786L,
94077 42788L,42788L,42790L,42790L,42792L,42792L,42794L,42794L,42796L,42796L,
94078 42798L,42798L,42800L,42801L,42802L,42802L,42804L,42804L,42806L,42806L,
94079 42808L,42808L,42810L,42810L,42812L,42812L,42814L,42814L,42816L,42816L,
94080 42818L,42818L,42820L,42820L,42822L,42822L,42824L,42824L,42826L,42826L,
94081 42828L,42828L,42830L,42830L,42832L,42832L,42834L,42834L,42836L,42836L,
94082 42838L,42838L,42840L,42840L,42842L,42842L,42844L,42844L,42846L,42846L,
94083 42848L,42848L,42850L,42850L,42852L,42852L,42854L,42854L,42856L,42856L,
94084 42858L,42858L,42860L,42860L,42862L,42862L,42864L,42865L,42866L,42867L,
94085 42868L,42869L,42870L,42871L,42872L,42873L,42873L,42875L,42875L,42877L,
94086 42878L,42878L,42880L,42880L,42882L,42882L,42884L,42884L,42886L,42886L,
94087 42888L,42889L,42890L,42891L,42891L,42893L,42894L,42895L,42896L,42896L,
94088 42898L,42898L,42948L,42901L,42902L,42902L,42904L,42904L,42906L,42906L,
94089 42908L,42908L,42910L,42910L,42912L,42912L,42914L,42914L,42916L,42916L,
94090 42918L,42918L,42920L,42920L,42922L,42923L,42924L,42925L,42926L,42927L,
94091 42928L,42929L,42930L,42931L,42932L,42932L,42934L,42934L,42936L,42936L,
94092 42938L,42938L,42940L,42940L,42942L,42942L,42944L,42945L,42946L,42946L,
94093 42948L,42949L,42950L,42951L,42952L,42953L,42954L,42955L,42956L,42957L,
94094 42958L,42959L,42960L,42961L,42962L,42963L,42964L,42965L,42966L,42967L,
94095 42968L,42969L,42970L,42971L,42972L,42973L,42974L,42975L,42976L,42977L,
94096 42978L,42979L,42980L,42981L,42982L,42983L,42984L,42985L,42986L,42987L,
94097 42988L,42989L,42990L,42991L,42992L,42993L,42994L,42995L,42996L,42997L,
94098 42998L,42999L,43000L,43001L,43002L,43003L,43004L,43005L,43006L,43007L,
94099 43008L,43009L,43010L,43011L,43012L,43013L,43014L,43015L,43016L,43017L,
94100 43018L,43019L,43020L,43021L,43022L,43023L,43024L,43025L,43026L,43027L,
94101 43028L,43029L,43030L,43031L,43032L,43033L,43034L,43035L,43036L,43037L,
94102 43038L,43039L,43040L,43041L,43042L,43043L,43044L,43045L,43046L,43047L,
94103 43048L,43049L,43050L,43051L,43052L,43053L,43054L,43055L,43056L,43057L,
94104 43058L,43059L,43060L,43061L,43062L,43063L,43064L,43065L,43066L,43067L,
94105 43068L,43069L,43070L,43071L,43072L,43073L,43074L,43075L,43076L,43077L,
94106 43078L,43079L,43080L,43081L,43082L,43083L,43084L,43085L,43086L,43087L,
94107 43088L,43089L,43090L,43091L,43092L,43093L,43094L,43095L,43096L,43097L,
94108 43098L,43099L,43100L,43101L,43102L,43103L,43104L,43105L,43106L,43107L,
94109 43108L,43109L,43110L,43111L,43112L,43113L,43114L,43115L,43116L,43117L,
94110 43118L,43119L,43120L,43121L,43122L,43123L,43124L,43125L,43126L,43127L,
94111 43128L,43129L,43130L,43131L,43132L,43133L,43134L,43135L,43136L,43137L,
94112 43138L,43139L,43140L,43141L,43142L,43143L,43144L,43145L,43146L,43147L,
94113 43148L,43149L,43150L,43151L,43152L,43153L,43154L,43155L,43156L,43157L,
94114 43158L,43159L,43160L,43161L,43162L,43163L,43164L,43165L,43166L,43167L,
94115 43168L,43169L,43170L,43171L,43172L,43173L,43174L,43175L,43176L,43177L,
94116 43178L,43179L,43180L,43181L,43182L,43183L,43184L,43185L,43186L,43187L,
94117 43188L,43189L,43190L,43191L,43192L,43193L,43194L,43195L,43196L,43197L,
94118 43198L,43199L,43200L,43201L,43202L,43203L,43204L,43205L,43206L,43207L,
94119 43208L,43209L,43210L,43211L,43212L,43213L,43214L,43215L,43216L,43217L,
94120 43218L,43219L,43220L,43221L,43222L,43223L,43224L,43225L,43226L,43227L,
94121 43228L,43229L,43230L,43231L,43232L,43233L,43234L,43235L,43236L,43237L,
94122 43238L,43239L,43240L,43241L,43242L,43243L,43244L,43245L,43246L,43247L,
94123 43248L,43249L,43250L,43251L,43252L,43253L,43254L,43255L,43256L,43257L,
94124 43258L,43259L,43260L,43261L,43262L,43263L,43264L,43265L,43266L,43267L,
94125 43268L,43269L,43270L,43271L,43272L,43273L,43274L,43275L,43276L,43277L,
94126 43278L,43279L,43280L,43281L,43282L,43283L,43284L,43285L,43286L,43287L,
94127 43288L,43289L,43290L,43291L,43292L,43293L,43294L,43295L,43296L,43297L,
94128 43298L,43299L,43300L,43301L,43302L,43303L,43304L,43305L,43306L,43307L,
94129 43308L,43309L,43310L,43311L,43312L,43313L,43314L,43315L,43316L,43317L,
94130 43318L,43319L,43320L,43321L,43322L,43323L,43324L,43325L,43326L,43327L,
94131 43328L,43329L,43330L,43331L,43332L,43333L,43334L,43335L,43336L,43337L,
94132 43338L,43339L,43340L,43341L,43342L,43343L,43344L,43345L,43346L,43347L,
94133 43348L,43349L,43350L,43351L,43352L,43353L,43354L,43355L,43356L,43357L,
94134 43358L,43359L,43360L,43361L,43362L,43363L,43364L,43365L,43366L,43367L,
94135 43368L,43369L,43370L,43371L,43372L,43373L,43374L,43375L,43376L,43377L,
94136 43378L,43379L,43380L,43381L,43382L,43383L,43384L,43385L,43386L,43387L,
94137 43388L,43389L,43390L,43391L,43392L,43393L,43394L,43395L,43396L,43397L,
94138 43398L,43399L,43400L,43401L,43402L,43403L,43404L,43405L,43406L,43407L,
94139 43408L,43409L,43410L,43411L,43412L,43413L,43414L,43415L,43416L,43417L,
94140 43418L,43419L,43420L,43421L,43422L,43423L,43424L,43425L,43426L,43427L,
94141 43428L,43429L,43430L,43431L,43432L,43433L,43434L,43435L,43436L,43437L,
94142 43438L,43439L,43440L,43441L,43442L,43443L,43444L,43445L,43446L,43447L,
94143 43448L,43449L,43450L,43451L,43452L,43453L,43454L,43455L,43456L,43457L,
94144 43458L,43459L,43460L,43461L,43462L,43463L,43464L,43465L,43466L,43467L,
94145 43468L,43469L,43470L,43471L,43472L,43473L,43474L,43475L,43476L,43477L,
94146 43478L,43479L,43480L,43481L,43482L,43483L,43484L,43485L,43486L,43487L,
94147 43488L,43489L,43490L,43491L,43492L,43493L,43494L,43495L,43496L,43497L,
94148 43498L,43499L,43500L,43501L,43502L,43503L,43504L,43505L,43506L,43507L,
94149 43508L,43509L,43510L,43511L,43512L,43513L,43514L,43515L,43516L,43517L,
94150 43518L,43519L,43520L,43521L,43522L,43523L,43524L,43525L,43526L,43527L,
94151 43528L,43529L,43530L,43531L,43532L,43533L,43534L,43535L,43536L,43537L,
94152 43538L,43539L,43540L,43541L,43542L,43543L,43544L,43545L,43546L,43547L,
94153 43548L,43549L,43550L,43551L,43552L,43553L,43554L,43555L,43556L,43557L,
94154 43558L,43559L,43560L,43561L,43562L,43563L,43564L,43565L,43566L,43567L,
94155 43568L,43569L,43570L,43571L,43572L,43573L,43574L,43575L,43576L,43577L,
94156 43578L,43579L,43580L,43581L,43582L,43583L,43584L,43585L,43586L,43587L,
94157 43588L,43589L,43590L,43591L,43592L,43593L,43594L,43595L,43596L,43597L,
94158 43598L,43599L,43600L,43601L,43602L,43603L,43604L,43605L,43606L,43607L,
94159 43608L,43609L,43610L,43611L,43612L,43613L,43614L,43615L,43616L,43617L,
94160 43618L,43619L,43620L,43621L,43622L,43623L,43624L,43625L,43626L,43627L,
94161 43628L,43629L,43630L,43631L,43632L,43633L,43634L,43635L,43636L,43637L,
94162 43638L,43639L,43640L,43641L,43642L,43643L,43644L,43645L,43646L,43647L,
94163 43648L,43649L,43650L,43651L,43652L,43653L,43654L,43655L,43656L,43657L,
94164 43658L,43659L,43660L,43661L,43662L,43663L,43664L,43665L,43666L,43667L,
94165 43668L,43669L,43670L,43671L,43672L,43673L,43674L,43675L,43676L,43677L,
94166 43678L,43679L,43680L,43681L,43682L,43683L,43684L,43685L,43686L,43687L,
94167 43688L,43689L,43690L,43691L,43692L,43693L,43694L,43695L,43696L,43697L,
94168 43698L,43699L,43700L,43701L,43702L,43703L,43704L,43705L,43706L,43707L,
94169 43708L,43709L,43710L,43711L,43712L,43713L,43714L,43715L,43716L,43717L,
94170 43718L,43719L,43720L,43721L,43722L,43723L,43724L,43725L,43726L,43727L,
94171 43728L,43729L,43730L,43731L,43732L,43733L,43734L,43735L,43736L,43737L,
94172 43738L,43739L,43740L,43741L,43742L,43743L,43744L,43745L,43746L,43747L,
94173 43748L,43749L,43750L,43751L,43752L,43753L,43754L,43755L,43756L,43757L,
94174 43758L,43759L,43760L,43761L,43762L,43763L,43764L,43765L,43766L,43767L,
94175 43768L,43769L,43770L,43771L,43772L,43773L,43774L,43775L,43776L,43777L,
94176 43778L,43779L,43780L,43781L,43782L,43783L,43784L,43785L,43786L,43787L,
94177 43788L,43789L,43790L,43791L,43792L,43793L,43794L,43795L,43796L,43797L,
94178 43798L,43799L,43800L,43801L,43802L,43803L,43804L,43805L,43806L,43807L,
94179 43808L,43809L,43810L,43811L,43812L,43813L,43814L,43815L,43816L,43817L,
94180 43818L,43819L,43820L,43821L,43822L,43823L,43824L,43825L,43826L,43827L,
94181 43828L,43829L,43830L,43831L,43832L,43833L,43834L,43835L,43836L,43837L,
94182 43838L,43839L,43840L,43841L,43842L,43843L,43844L,43845L,43846L,43847L,
94183 43848L,43849L,43850L,43851L,43852L,43853L,43854L,43855L,43856L,43857L,
94184 43858L,42931L,43860L,43861L,43862L,43863L,43864L,43865L,43866L,43867L,
94185 43868L,43869L,43870L,43871L,43872L,43873L,43874L,43875L,43876L,43877L,
94186 43878L,43879L,43880L,43881L,43882L,43883L,43884L,43885L,43886L,43887L,5024,
94187 5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,
94188 5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,
94189 5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,
94190 5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,
94191 5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,
94192 5100,5101,5102,5103,43968L,43969L,43970L,43971L,43972L,43973L,43974L,
94193 43975L,43976L,43977L,43978L,43979L,43980L,43981L,43982L,43983L,43984L,
94194 43985L,43986L,43987L,43988L,43989L,43990L,43991L,43992L,43993L,43994L,
94195 43995L,43996L,43997L,43998L,43999L,44000L,44001L,44002L,44003L,44004L,
94196 44005L,44006L,44007L,44008L,44009L,44010L,44011L,44012L,44013L,44014L,
94197 44015L,44016L,44017L,44018L,44019L,44020L,44021L,44022L,44023L,44024L,
94198 44025L,44026L,44027L,44028L,44029L,44030L,44031L,44032L,44033L,44034L,
94199 44035L,44036L,44037L,44038L,44039L,44040L,44041L,44042L,44043L,44044L,
94200 44045L,44046L,44047L,44048L,44049L,44050L,44051L,44052L,44053L,44054L,
94201 44055L,44056L,44057L,44058L,44059L,44060L,44061L,44062L,44063L,44064L,
94202 44065L,44066L,44067L,44068L,44069L,44070L,44071L,44072L,44073L,44074L,
94203 44075L,44076L,44077L,44078L,44079L,44080L,44081L,44082L,44083L,44084L,
94204 44085L,44086L,44087L,44088L,44089L,44090L,44091L,44092L,44093L,44094L,
94205 44095L,44096L,44097L,44098L,44099L,44100L,44101L,44102L,44103L,44104L,
94206 44105L,44106L,44107L,44108L,44109L,44110L,44111L,44112L,44113L,44114L,
94207 44115L,44116L,44117L,44118L,44119L,44120L,44121L,44122L,44123L,44124L,
94208 44125L,44126L,44127L,44128L,44129L,44130L,44131L,44132L,44133L,44134L,
94209 44135L,44136L,44137L,44138L,44139L,44140L,44141L,44142L,44143L,44144L,
94210 44145L,44146L,44147L,44148L,44149L,44150L,44151L,44152L,44153L,44154L,
94211 44155L,44156L,44157L,44158L,44159L,44160L,44161L,44162L,44163L,44164L,
94212 44165L,44166L,44167L,44168L,44169L,44170L,44171L,44172L,44173L,44174L,
94213 44175L,44176L,44177L,44178L,44179L,44180L,44181L,44182L,44183L,44184L,
94214 44185L,44186L,44187L,44188L,44189L,44190L,44191L,44192L,44193L,44194L,
94215 44195L,44196L,44197L,44198L,44199L,44200L,44201L,44202L,44203L,44204L,
94216 44205L,44206L,44207L,44208L,44209L,44210L,44211L,44212L,44213L,44214L,
94217 44215L,44216L,44217L,44218L,44219L,44220L,44221L,44222L,44223L,44224L,
94218 44225L,44226L,44227L,44228L,44229L,44230L,44231L,44232L,44233L,44234L,
94219 44235L,44236L,44237L,44238L,44239L,44240L,44241L,44242L,44243L,44244L,
94220 44245L,44246L,44247L,44248L,44249L,44250L,44251L,44252L,44253L,44254L,
94221 44255L,44256L,44257L,44258L,44259L,44260L,44261L,44262L,44263L,44264L,
94222 44265L,44266L,44267L,44268L,44269L,44270L,44271L,44272L,44273L,44274L,
94223 44275L,44276L,44277L,44278L,44279L,44280L,44281L,44282L,44283L,44284L,
94224 44285L,44286L,44287L,44288L,44289L,44290L,44291L,44292L,44293L,44294L,
94225 44295L,44296L,44297L,44298L,44299L,44300L,44301L,44302L,44303L,44304L,
94226 44305L,44306L,44307L,44308L,44309L,44310L,44311L,44312L,44313L,44314L,
94227 44315L,44316L,44317L,44318L,44319L,44320L,44321L,44322L,44323L,44324L,
94228 44325L,44326L,44327L,44328L,44329L,44330L,44331L,44332L,44333L,44334L,
94229 44335L,44336L,44337L,44338L,44339L,44340L,44341L,44342L,44343L,44344L,
94230 44345L,44346L,44347L,44348L,44349L,44350L,44351L,44352L,44353L,44354L,
94231 44355L,44356L,44357L,44358L,44359L,44360L,44361L,44362L,44363L,44364L,
94232 44365L,44366L,44367L,44368L,44369L,44370L,44371L,44372L,44373L,44374L,
94233 44375L,44376L,44377L,44378L,44379L,44380L,44381L,44382L,44383L,44384L,
94234 44385L,44386L,44387L,44388L,44389L,44390L,44391L,44392L,44393L,44394L,
94235 44395L,44396L,44397L,44398L,44399L,44400L,44401L,44402L,44403L,44404L,
94236 44405L,44406L,44407L,44408L,44409L,44410L,44411L,44412L,44413L,44414L,
94237 44415L,44416L,44417L,44418L,44419L,44420L,44421L,44422L,44423L,44424L,
94238 44425L,44426L,44427L,44428L,44429L,44430L,44431L,44432L,44433L,44434L,
94239 44435L,44436L,44437L,44438L,44439L,44440L,44441L,44442L,44443L,44444L,
94240 44445L,44446L,44447L,44448L,44449L,44450L,44451L,44452L,44453L,44454L,
94241 44455L,44456L,44457L,44458L,44459L,44460L,44461L,44462L,44463L,44464L,
94242 44465L,44466L,44467L,44468L,44469L,44470L,44471L,44472L,44473L,44474L,
94243 44475L,44476L,44477L,44478L,44479L,44480L,44481L,44482L,44483L,44484L,
94244 44485L,44486L,44487L,44488L,44489L,44490L,44491L,44492L,44493L,44494L,
94245 44495L,44496L,44497L,44498L,44499L,44500L,44501L,44502L,44503L,44504L,
94246 44505L,44506L,44507L,44508L,44509L,44510L,44511L,44512L,44513L,44514L,
94247 44515L,44516L,44517L,44518L,44519L,44520L,44521L,44522L,44523L,44524L,
94248 44525L,44526L,44527L,44528L,44529L,44530L,44531L,44532L,44533L,44534L,
94249 44535L,44536L,44537L,44538L,44539L,44540L,44541L,44542L,44543L,44544L,
94250 44545L,44546L,44547L,44548L,44549L,44550L,44551L,44552L,44553L,44554L,
94251 44555L,44556L,44557L,44558L,44559L,44560L,44561L,44562L,44563L,44564L,
94252 44565L,44566L,44567L,44568L,44569L,44570L,44571L,44572L,44573L,44574L,
94253 44575L,44576L,44577L,44578L,44579L,44580L,44581L,44582L,44583L,44584L,
94254 44585L,44586L,44587L,44588L,44589L,44590L,44591L,44592L,44593L,44594L,
94255 44595L,44596L,44597L,44598L,44599L,44600L,44601L,44602L,44603L,44604L,
94256 44605L,44606L,44607L,44608L,44609L,44610L,44611L,44612L,44613L,44614L,
94257 44615L,44616L,44617L,44618L,44619L,44620L,44621L,44622L,44623L,44624L,
94258 44625L,44626L,44627L,44628L,44629L,44630L,44631L,44632L,44633L,44634L,
94259 44635L,44636L,44637L,44638L,44639L,44640L,44641L,44642L,44643L,44644L,
94260 44645L,44646L,44647L,44648L,44649L,44650L,44651L,44652L,44653L,44654L,
94261 44655L,44656L,44657L,44658L,44659L,44660L,44661L,44662L,44663L,44664L,
94262 44665L,44666L,44667L,44668L,44669L,44670L,44671L,44672L,44673L,44674L,
94263 44675L,44676L,44677L,44678L,44679L,44680L,44681L,44682L,44683L,44684L,
94264 44685L,44686L,44687L,44688L,44689L,44690L,44691L,44692L,44693L,44694L,
94265 44695L,44696L,44697L,44698L,44699L,44700L,44701L,44702L,44703L,44704L,
94266 44705L,44706L,44707L,44708L,44709L,44710L,44711L,44712L,44713L,44714L,
94267 44715L,44716L,44717L,44718L,44719L,44720L,44721L,44722L,44723L,44724L,
94268 44725L,44726L,44727L,44728L,44729L,44730L,44731L,44732L,44733L,44734L,
94269 44735L,44736L,44737L,44738L,44739L,44740L,44741L,44742L,44743L,44744L,
94270 44745L,44746L,44747L,44748L,44749L,44750L,44751L,44752L,44753L,44754L,
94271 44755L,44756L,44757L,44758L,44759L,44760L,44761L,44762L,44763L,44764L,
94272 44765L,44766L,44767L,44768L,44769L,44770L,44771L,44772L,44773L,44774L,
94273 44775L,44776L,44777L,44778L,44779L,44780L,44781L,44782L,44783L,44784L,
94274 44785L,44786L,44787L,44788L,44789L,44790L,44791L,44792L,44793L,44794L,
94275 44795L,44796L,44797L,44798L,44799L,44800L,44801L,44802L,44803L,44804L,
94276 44805L,44806L,44807L,44808L,44809L,44810L,44811L,44812L,44813L,44814L,
94277 44815L,44816L,44817L,44818L,44819L,44820L,44821L,44822L,44823L,44824L,
94278 44825L,44826L,44827L,44828L,44829L,44830L,44831L,44832L,44833L,44834L,
94279 44835L,44836L,44837L,44838L,44839L,44840L,44841L,44842L,44843L,44844L,
94280 44845L,44846L,44847L,44848L,44849L,44850L,44851L,44852L,44853L,44854L,
94281 44855L,44856L,44857L,44858L,44859L,44860L,44861L,44862L,44863L,44864L,
94282 44865L,44866L,44867L,44868L,44869L,44870L,44871L,44872L,44873L,44874L,
94283 44875L,44876L,44877L,44878L,44879L,44880L,44881L,44882L,44883L,44884L,
94284 44885L,44886L,44887L,44888L,44889L,44890L,44891L,44892L,44893L,44894L,
94285 44895L,44896L,44897L,44898L,44899L,44900L,44901L,44902L,44903L,44904L,
94286 44905L,44906L,44907L,44908L,44909L,44910L,44911L,44912L,44913L,44914L,
94287 44915L,44916L,44917L,44918L,44919L,44920L,44921L,44922L,44923L,44924L,
94288 44925L,44926L,44927L,44928L,44929L,44930L,44931L,44932L,44933L,44934L,
94289 44935L,44936L,44937L,44938L,44939L,44940L,44941L,44942L,44943L,44944L,
94290 44945L,44946L,44947L,44948L,44949L,44950L,44951L,44952L,44953L,44954L,
94291 44955L,44956L,44957L,44958L,44959L,44960L,44961L,44962L,44963L,44964L,
94292 44965L,44966L,44967L,44968L,44969L,44970L,44971L,44972L,44973L,44974L,
94293 44975L,44976L,44977L,44978L,44979L,44980L,44981L,44982L,44983L,44984L,
94294 44985L,44986L,44987L,44988L,44989L,44990L,44991L,44992L,44993L,44994L,
94295 44995L,44996L,44997L,44998L,44999L,45000L,45001L,45002L,45003L,45004L,
94296 45005L,45006L,45007L,45008L,45009L,45010L,45011L,45012L,45013L,45014L,
94297 45015L,45016L,45017L,45018L,45019L,45020L,45021L,45022L,45023L,45024L,
94298 45025L,45026L,45027L,45028L,45029L,45030L,45031L,45032L,45033L,45034L,
94299 45035L,45036L,45037L,45038L,45039L,45040L,45041L,45042L,45043L,45044L,
94300 45045L,45046L,45047L,45048L,45049L,45050L,45051L,45052L,45053L,45054L,
94301 45055L,45056L,45057L,45058L,45059L,45060L,45061L,45062L,45063L,45064L,
94302 45065L,45066L,45067L,45068L,45069L,45070L,45071L,45072L,45073L,45074L,
94303 45075L,45076L,45077L,45078L,45079L,45080L,45081L,45082L,45083L,45084L,
94304 45085L,45086L,45087L,45088L,45089L,45090L,45091L,45092L,45093L,45094L,
94305 45095L,45096L,45097L,45098L,45099L,45100L,45101L,45102L,45103L,45104L,
94306 45105L,45106L,45107L,45108L,45109L,45110L,45111L,45112L,45113L,45114L,
94307 45115L,45116L,45117L,45118L,45119L,45120L,45121L,45122L,45123L,45124L,
94308 45125L,45126L,45127L,45128L,45129L,45130L,45131L,45132L,45133L,45134L,
94309 45135L,45136L,45137L,45138L,45139L,45140L,45141L,45142L,45143L,45144L,
94310 45145L,45146L,45147L,45148L,45149L,45150L,45151L,45152L,45153L,45154L,
94311 45155L,45156L,45157L,45158L,45159L,45160L,45161L,45162L,45163L,45164L,
94312 45165L,45166L,45167L,45168L,45169L,45170L,45171L,45172L,45173L,45174L,
94313 45175L,45176L,45177L,45178L,45179L,45180L,45181L,45182L,45183L,45184L,
94314 45185L,45186L,45187L,45188L,45189L,45190L,45191L,45192L,45193L,45194L,
94315 45195L,45196L,45197L,45198L,45199L,45200L,45201L,45202L,45203L,45204L,
94316 45205L,45206L,45207L,45208L,45209L,45210L,45211L,45212L,45213L,45214L,
94317 45215L,45216L,45217L,45218L,45219L,45220L,45221L,45222L,45223L,45224L,
94318 45225L,45226L,45227L,45228L,45229L,45230L,45231L,45232L,45233L,45234L,
94319 45235L,45236L,45237L,45238L,45239L,45240L,45241L,45242L,45243L,45244L,
94320 45245L,45246L,45247L,45248L,45249L,45250L,45251L,45252L,45253L,45254L,
94321 45255L,45256L,45257L,45258L,45259L,45260L,45261L,45262L,45263L,45264L,
94322 45265L,45266L,45267L,45268L,45269L,45270L,45271L,45272L,45273L,45274L,
94323 45275L,45276L,45277L,45278L,45279L,45280L,45281L,45282L,45283L,45284L,
94324 45285L,45286L,45287L,45288L,45289L,45290L,45291L,45292L,45293L,45294L,
94325 45295L,45296L,45297L,45298L,45299L,45300L,45301L,45302L,45303L,45304L,
94326 45305L,45306L,45307L,45308L,45309L,45310L,45311L,45312L,45313L,45314L,
94327 45315L,45316L,45317L,45318L,45319L,45320L,45321L,45322L,45323L,45324L,
94328 45325L,45326L,45327L,45328L,45329L,45330L,45331L,45332L,45333L,45334L,
94329 45335L,45336L,45337L,45338L,45339L,45340L,45341L,45342L,45343L,45344L,
94330 45345L,45346L,45347L,45348L,45349L,45350L,45351L,45352L,45353L,45354L,
94331 45355L,45356L,45357L,45358L,45359L,45360L,45361L,45362L,45363L,45364L,
94332 45365L,45366L,45367L,45368L,45369L,45370L,45371L,45372L,45373L,45374L,
94333 45375L,45376L,45377L,45378L,45379L,45380L,45381L,45382L,45383L,45384L,
94334 45385L,45386L,45387L,45388L,45389L,45390L,45391L,45392L,45393L,45394L,
94335 45395L,45396L,45397L,45398L,45399L,45400L,45401L,45402L,45403L,45404L,
94336 45405L,45406L,45407L,45408L,45409L,45410L,45411L,45412L,45413L,45414L,
94337 45415L,45416L,45417L,45418L,45419L,45420L,45421L,45422L,45423L,45424L,
94338 45425L,45426L,45427L,45428L,45429L,45430L,45431L,45432L,45433L,45434L,
94339 45435L,45436L,45437L,45438L,45439L,45440L,45441L,45442L,45443L,45444L,
94340 45445L,45446L,45447L,45448L,45449L,45450L,45451L,45452L,45453L,45454L,
94341 45455L,45456L,45457L,45458L,45459L,45460L,45461L,45462L,45463L,45464L,
94342 45465L,45466L,45467L,45468L,45469L,45470L,45471L,45472L,45473L,45474L,
94343 45475L,45476L,45477L,45478L,45479L,45480L,45481L,45482L,45483L,45484L,
94344 45485L,45486L,45487L,45488L,45489L,45490L,45491L,45492L,45493L,45494L,
94345 45495L,45496L,45497L,45498L,45499L,45500L,45501L,45502L,45503L,45504L,
94346 45505L,45506L,45507L,45508L,45509L,45510L,45511L,45512L,45513L,45514L,
94347 45515L,45516L,45517L,45518L,45519L,45520L,45521L,45522L,45523L,45524L,
94348 45525L,45526L,45527L,45528L,45529L,45530L,45531L,45532L,45533L,45534L,
94349 45535L,45536L,45537L,45538L,45539L,45540L,45541L,45542L,45543L,45544L,
94350 45545L,45546L,45547L,45548L,45549L,45550L,45551L,45552L,45553L,45554L,
94351 45555L,45556L,45557L,45558L,45559L,45560L,45561L,45562L,45563L,45564L,
94352 45565L,45566L,45567L,45568L,45569L,45570L,45571L,45572L,45573L,45574L,
94353 45575L,45576L,45577L,45578L,45579L,45580L,45581L,45582L,45583L,45584L,
94354 45585L,45586L,45587L,45588L,45589L,45590L,45591L,45592L,45593L,45594L,
94355 45595L,45596L,45597L,45598L,45599L,45600L,45601L,45602L,45603L,45604L,
94356 45605L,45606L,45607L,45608L,45609L,45610L,45611L,45612L,45613L,45614L,
94357 45615L,45616L,45617L,45618L,45619L,45620L,45621L,45622L,45623L,45624L,
94358 45625L,45626L,45627L,45628L,45629L,45630L,45631L,45632L,45633L,45634L,
94359 45635L,45636L,45637L,45638L,45639L,45640L,45641L,45642L,45643L,45644L,
94360 45645L,45646L,45647L,45648L,45649L,45650L,45651L,45652L,45653L,45654L,
94361 45655L,45656L,45657L,45658L,45659L,45660L,45661L,45662L,45663L,45664L,
94362 45665L,45666L,45667L,45668L,45669L,45670L,45671L,45672L,45673L,45674L,
94363 45675L,45676L,45677L,45678L,45679L,45680L,45681L,45682L,45683L,45684L,
94364 45685L,45686L,45687L,45688L,45689L,45690L,45691L,45692L,45693L,45694L,
94365 45695L,45696L,45697L,45698L,45699L,45700L,45701L,45702L,45703L,45704L,
94366 45705L,45706L,45707L,45708L,45709L,45710L,45711L,45712L,45713L,45714L,
94367 45715L,45716L,45717L,45718L,45719L,45720L,45721L,45722L,45723L,45724L,
94368 45725L,45726L,45727L,45728L,45729L,45730L,45731L,45732L,45733L,45734L,
94369 45735L,45736L,45737L,45738L,45739L,45740L,45741L,45742L,45743L,45744L,
94370 45745L,45746L,45747L,45748L,45749L,45750L,45751L,45752L,45753L,45754L,
94371 45755L,45756L,45757L,45758L,45759L,45760L,45761L,45762L,45763L,45764L,
94372 45765L,45766L,45767L,45768L,45769L,45770L,45771L,45772L,45773L,45774L,
94373 45775L,45776L,45777L,45778L,45779L,45780L,45781L,45782L,45783L,45784L,
94374 45785L,45786L,45787L,45788L,45789L,45790L,45791L,45792L,45793L,45794L,
94375 45795L,45796L,45797L,45798L,45799L,45800L,45801L,45802L,45803L,45804L,
94376 45805L,45806L,45807L,45808L,45809L,45810L,45811L,45812L,45813L,45814L,
94377 45815L,45816L,45817L,45818L,45819L,45820L,45821L,45822L,45823L,45824L,
94378 45825L,45826L,45827L,45828L,45829L,45830L,45831L,45832L,45833L,45834L,
94379 45835L,45836L,45837L,45838L,45839L,45840L,45841L,45842L,45843L,45844L,
94380 45845L,45846L,45847L,45848L,45849L,45850L,45851L,45852L,45853L,45854L,
94381 45855L,45856L,45857L,45858L,45859L,45860L,45861L,45862L,45863L,45864L,
94382 45865L,45866L,45867L,45868L,45869L,45870L,45871L,45872L,45873L,45874L,
94383 45875L,45876L,45877L,45878L,45879L,45880L,45881L,45882L,45883L,45884L,
94384 45885L,45886L,45887L,45888L,45889L,45890L,45891L,45892L,45893L,45894L,
94385 45895L,45896L,45897L,45898L,45899L,45900L,45901L,45902L,45903L,45904L,
94386 45905L,45906L,45907L,45908L,45909L,45910L,45911L,45912L,45913L,45914L,
94387 45915L,45916L,45917L,45918L,45919L,45920L,45921L,45922L,45923L,45924L,
94388 45925L,45926L,45927L,45928L,45929L,45930L,45931L,45932L,45933L,45934L,
94389 45935L,45936L,45937L,45938L,45939L,45940L,45941L,45942L,45943L,45944L,
94390 45945L,45946L,45947L,45948L,45949L,45950L,45951L,45952L,45953L,45954L,
94391 45955L,45956L,45957L,45958L,45959L,45960L,45961L,45962L,45963L,45964L,
94392 45965L,45966L,45967L,45968L,45969L,45970L,45971L,45972L,45973L,45974L,
94393 45975L,45976L,45977L,45978L,45979L,45980L,45981L,45982L,45983L,45984L,
94394 45985L,45986L,45987L,45988L,45989L,45990L,45991L,45992L,45993L,45994L,
94395 45995L,45996L,45997L,45998L,45999L,46000L,46001L,46002L,46003L,46004L,
94396 46005L,46006L,46007L,46008L,46009L,46010L,46011L,46012L,46013L,46014L,
94397 46015L,46016L,46017L,46018L,46019L,46020L,46021L,46022L,46023L,46024L,
94398 46025L,46026L,46027L,46028L,46029L,46030L,46031L,46032L,46033L,46034L,
94399 46035L,46036L,46037L,46038L,46039L,46040L,46041L,46042L,46043L,46044L,
94400 46045L,46046L,46047L,46048L,46049L,46050L,46051L,46052L,46053L,46054L,
94401 46055L,46056L,46057L,46058L,46059L,46060L,46061L,46062L,46063L,46064L,
94402 46065L,46066L,46067L,46068L,46069L,46070L,46071L,46072L,46073L,46074L,
94403 46075L,46076L,46077L,46078L,46079L,46080L,46081L,46082L,46083L,46084L,
94404 46085L,46086L,46087L,46088L,46089L,46090L,46091L,46092L,46093L,46094L,
94405 46095L,46096L,46097L,46098L,46099L,46100L,46101L,46102L,46103L,46104L,
94406 46105L,46106L,46107L,46108L,46109L,46110L,46111L,46112L,46113L,46114L,
94407 46115L,46116L,46117L,46118L,46119L,46120L,46121L,46122L,46123L,46124L,
94408 46125L,46126L,46127L,46128L,46129L,46130L,46131L,46132L,46133L,46134L,
94409 46135L,46136L,46137L,46138L,46139L,46140L,46141L,46142L,46143L,46144L,
94410 46145L,46146L,46147L,46148L,46149L,46150L,46151L,46152L,46153L,46154L,
94411 46155L,46156L,46157L,46158L,46159L,46160L,46161L,46162L,46163L,46164L,
94412 46165L,46166L,46167L,46168L,46169L,46170L,46171L,46172L,46173L,46174L,
94413 46175L,46176L,46177L,46178L,46179L,46180L,46181L,46182L,46183L,46184L,
94414 46185L,46186L,46187L,46188L,46189L,46190L,46191L,46192L,46193L,46194L,
94415 46195L,46196L,46197L,46198L,46199L,46200L,46201L,46202L,46203L,46204L,
94416 46205L,46206L,46207L,46208L,46209L,46210L,46211L,46212L,46213L,46214L,
94417 46215L,46216L,46217L,46218L,46219L,46220L,46221L,46222L,46223L,46224L,
94418 46225L,46226L,46227L,46228L,46229L,46230L,46231L,46232L,46233L,46234L,
94419 46235L,46236L,46237L,46238L,46239L,46240L,46241L,46242L,46243L,46244L,
94420 46245L,46246L,46247L,46248L,46249L,46250L,46251L,46252L,46253L,46254L,
94421 46255L,46256L,46257L,46258L,46259L,46260L,46261L,46262L,46263L,46264L,
94422 46265L,46266L,46267L,46268L,46269L,46270L,46271L,46272L,46273L,46274L,
94423 46275L,46276L,46277L,46278L,46279L,46280L,46281L,46282L,46283L,46284L,
94424 46285L,46286L,46287L,46288L,46289L,46290L,46291L,46292L,46293L,46294L,
94425 46295L,46296L,46297L,46298L,46299L,46300L,46301L,46302L,46303L,46304L,
94426 46305L,46306L,46307L,46308L,46309L,46310L,46311L,46312L,46313L,46314L,
94427 46315L,46316L,46317L,46318L,46319L,46320L,46321L,46322L,46323L,46324L,
94428 46325L,46326L,46327L,46328L,46329L,46330L,46331L,46332L,46333L,46334L,
94429 46335L,46336L,46337L,46338L,46339L,46340L,46341L,46342L,46343L,46344L,
94430 46345L,46346L,46347L,46348L,46349L,46350L,46351L,46352L,46353L,46354L,
94431 46355L,46356L,46357L,46358L,46359L,46360L,46361L,46362L,46363L,46364L,
94432 46365L,46366L,46367L,46368L,46369L,46370L,46371L,46372L,46373L,46374L,
94433 46375L,46376L,46377L,46378L,46379L,46380L,46381L,46382L,46383L,46384L,
94434 46385L,46386L,46387L,46388L,46389L,46390L,46391L,46392L,46393L,46394L,
94435 46395L,46396L,46397L,46398L,46399L,46400L,46401L,46402L,46403L,46404L,
94436 46405L,46406L,46407L,46408L,46409L,46410L,46411L,46412L,46413L,46414L,
94437 46415L,46416L,46417L,46418L,46419L,46420L,46421L,46422L,46423L,46424L,
94438 46425L,46426L,46427L,46428L,46429L,46430L,46431L,46432L,46433L,46434L,
94439 46435L,46436L,46437L,46438L,46439L,46440L,46441L,46442L,46443L,46444L,
94440 46445L,46446L,46447L,46448L,46449L,46450L,46451L,46452L,46453L,46454L,
94441 46455L,46456L,46457L,46458L,46459L,46460L,46461L,46462L,46463L,46464L,
94442 46465L,46466L,46467L,46468L,46469L,46470L,46471L,46472L,46473L,46474L,
94443 46475L,46476L,46477L,46478L,46479L,46480L,46481L,46482L,46483L,46484L,
94444 46485L,46486L,46487L,46488L,46489L,46490L,46491L,46492L,46493L,46494L,
94445 46495L,46496L,46497L,46498L,46499L,46500L,46501L,46502L,46503L,46504L,
94446 46505L,46506L,46507L,46508L,46509L,46510L,46511L,46512L,46513L,46514L,
94447 46515L,46516L,46517L,46518L,46519L,46520L,46521L,46522L,46523L,46524L,
94448 46525L,46526L,46527L,46528L,46529L,46530L,46531L,46532L,46533L,46534L,
94449 46535L,46536L,46537L,46538L,46539L,46540L,46541L,46542L,46543L,46544L,
94450 46545L,46546L,46547L,46548L,46549L,46550L,46551L,46552L,46553L,46554L,
94451 46555L,46556L,46557L,46558L,46559L,46560L,46561L,46562L,46563L,46564L,
94452 46565L,46566L,46567L,46568L,46569L,46570L,46571L,46572L,46573L,46574L,
94453 46575L,46576L,46577L,46578L,46579L,46580L,46581L,46582L,46583L,46584L,
94454 46585L,46586L,46587L,46588L,46589L,46590L,46591L,46592L,46593L,46594L,
94455 46595L,46596L,46597L,46598L,46599L,46600L,46601L,46602L,46603L,46604L,
94456 46605L,46606L,46607L,46608L,46609L,46610L,46611L,46612L,46613L,46614L,
94457 46615L,46616L,46617L,46618L,46619L,46620L,46621L,46622L,46623L,46624L,
94458 46625L,46626L,46627L,46628L,46629L,46630L,46631L,46632L,46633L,46634L,
94459 46635L,46636L,46637L,46638L,46639L,46640L,46641L,46642L,46643L,46644L,
94460 46645L,46646L,46647L,46648L,46649L,46650L,46651L,46652L,46653L,46654L,
94461 46655L,46656L,46657L,46658L,46659L,46660L,46661L,46662L,46663L,46664L,
94462 46665L,46666L,46667L,46668L,46669L,46670L,46671L,46672L,46673L,46674L,
94463 46675L,46676L,46677L,46678L,46679L,46680L,46681L,46682L,46683L,46684L,
94464 46685L,46686L,46687L,46688L,46689L,46690L,46691L,46692L,46693L,46694L,
94465 46695L,46696L,46697L,46698L,46699L,46700L,46701L,46702L,46703L,46704L,
94466 46705L,46706L,46707L,46708L,46709L,46710L,46711L,46712L,46713L,46714L,
94467 46715L,46716L,46717L,46718L,46719L,46720L,46721L,46722L,46723L,46724L,
94468 46725L,46726L,46727L,46728L,46729L,46730L,46731L,46732L,46733L,46734L,
94469 46735L,46736L,46737L,46738L,46739L,46740L,46741L,46742L,46743L,46744L,
94470 46745L,46746L,46747L,46748L,46749L,46750L,46751L,46752L,46753L,46754L,
94471 46755L,46756L,46757L,46758L,46759L,46760L,46761L,46762L,46763L,46764L,
94472 46765L,46766L,46767L,46768L,46769L,46770L,46771L,46772L,46773L,46774L,
94473 46775L,46776L,46777L,46778L,46779L,46780L,46781L,46782L,46783L,46784L,
94474 46785L,46786L,46787L,46788L,46789L,46790L,46791L,46792L,46793L,46794L,
94475 46795L,46796L,46797L,46798L,46799L,46800L,46801L,46802L,46803L,46804L,
94476 46805L,46806L,46807L,46808L,46809L,46810L,46811L,46812L,46813L,46814L,
94477 46815L,46816L,46817L,46818L,46819L,46820L,46821L,46822L,46823L,46824L,
94478 46825L,46826L,46827L,46828L,46829L,46830L,46831L,46832L,46833L,46834L,
94479 46835L,46836L,46837L,46838L,46839L,46840L,46841L,46842L,46843L,46844L,
94480 46845L,46846L,46847L,46848L,46849L,46850L,46851L,46852L,46853L,46854L,
94481 46855L,46856L,46857L,46858L,46859L,46860L,46861L,46862L,46863L,46864L,
94482 46865L,46866L,46867L,46868L,46869L,46870L,46871L,46872L,46873L,46874L,
94483 46875L,46876L,46877L,46878L,46879L,46880L,46881L,46882L,46883L,46884L,
94484 46885L,46886L,46887L,46888L,46889L,46890L,46891L,46892L,46893L,46894L,
94485 46895L,46896L,46897L,46898L,46899L,46900L,46901L,46902L,46903L,46904L,
94486 46905L,46906L,46907L,46908L,46909L,46910L,46911L,46912L,46913L,46914L,
94487 46915L,46916L,46917L,46918L,46919L,46920L,46921L,46922L,46923L,46924L,
94488 46925L,46926L,46927L,46928L,46929L,46930L,46931L,46932L,46933L,46934L,
94489 46935L,46936L,46937L,46938L,46939L,46940L,46941L,46942L,46943L,46944L,
94490 46945L,46946L,46947L,46948L,46949L,46950L,46951L,46952L,46953L,46954L,
94491 46955L,46956L,46957L,46958L,46959L,46960L,46961L,46962L,46963L,46964L,
94492 46965L,46966L,46967L,46968L,46969L,46970L,46971L,46972L,46973L,46974L,
94493 46975L,46976L,46977L,46978L,46979L,46980L,46981L,46982L,46983L,46984L,
94494 46985L,46986L,46987L,46988L,46989L,46990L,46991L,46992L,46993L,46994L,
94495 46995L,46996L,46997L,46998L,46999L,47000L,47001L,47002L,47003L,47004L,
94496 47005L,47006L,47007L,47008L,47009L,47010L,47011L,47012L,47013L,47014L,
94497 47015L,47016L,47017L,47018L,47019L,47020L,47021L,47022L,47023L,47024L,
94498 47025L,47026L,47027L,47028L,47029L,47030L,47031L,47032L,47033L,47034L,
94499 47035L,47036L,47037L,47038L,47039L,47040L,47041L,47042L,47043L,47044L,
94500 47045L,47046L,47047L,47048L,47049L,47050L,47051L,47052L,47053L,47054L,
94501 47055L,47056L,47057L,47058L,47059L,47060L,47061L,47062L,47063L,47064L,
94502 47065L,47066L,47067L,47068L,47069L,47070L,47071L,47072L,47073L,47074L,
94503 47075L,47076L,47077L,47078L,47079L,47080L,47081L,47082L,47083L,47084L,
94504 47085L,47086L,47087L,47088L,47089L,47090L,47091L,47092L,47093L,47094L,
94505 47095L,47096L,47097L,47098L,47099L,47100L,47101L,47102L,47103L,47104L,
94506 47105L,47106L,47107L,47108L,47109L,47110L,47111L,47112L,47113L,47114L,
94507 47115L,47116L,47117L,47118L,47119L,47120L,47121L,47122L,47123L,47124L,
94508 47125L,47126L,47127L,47128L,47129L,47130L,47131L,47132L,47133L,47134L,
94509 47135L,47136L,47137L,47138L,47139L,47140L,47141L,47142L,47143L,47144L,
94510 47145L,47146L,47147L,47148L,47149L,47150L,47151L,47152L,47153L,47154L,
94511 47155L,47156L,47157L,47158L,47159L,47160L,47161L,47162L,47163L,47164L,
94512 47165L,47166L,47167L,47168L,47169L,47170L,47171L,47172L,47173L,47174L,
94513 47175L,47176L,47177L,47178L,47179L,47180L,47181L,47182L,47183L,47184L,
94514 47185L,47186L,47187L,47188L,47189L,47190L,47191L,47192L,47193L,47194L,
94515 47195L,47196L,47197L,47198L,47199L,47200L,47201L,47202L,47203L,47204L,
94516 47205L,47206L,47207L,47208L,47209L,47210L,47211L,47212L,47213L,47214L,
94517 47215L,47216L,47217L,47218L,47219L,47220L,47221L,47222L,47223L,47224L,
94518 47225L,47226L,47227L,47228L,47229L,47230L,47231L,47232L,47233L,47234L,
94519 47235L,47236L,47237L,47238L,47239L,47240L,47241L,47242L,47243L,47244L,
94520 47245L,47246L,47247L,47248L,47249L,47250L,47251L,47252L,47253L,47254L,
94521 47255L,47256L,47257L,47258L,47259L,47260L,47261L,47262L,47263L,47264L,
94522 47265L,47266L,47267L,47268L,47269L,47270L,47271L,47272L,47273L,47274L,
94523 47275L,47276L,47277L,47278L,47279L,47280L,47281L,47282L,47283L,47284L,
94524 47285L,47286L,47287L,47288L,47289L,47290L,47291L,47292L,47293L,47294L,
94525 47295L,47296L,47297L,47298L,47299L,47300L,47301L,47302L,47303L,47304L,
94526 47305L,47306L,47307L,47308L,47309L,47310L,47311L,47312L,47313L,47314L,
94527 47315L,47316L,47317L,47318L,47319L,47320L,47321L,47322L,47323L,47324L,
94528 47325L,47326L,47327L,47328L,47329L,47330L,47331L,47332L,47333L,47334L,
94529 47335L,47336L,47337L,47338L,47339L,47340L,47341L,47342L,47343L,47344L,
94530 47345L,47346L,47347L,47348L,47349L,47350L,47351L,47352L,47353L,47354L,
94531 47355L,47356L,47357L,47358L,47359L,47360L,47361L,47362L,47363L,47364L,
94532 47365L,47366L,47367L,47368L,47369L,47370L,47371L,47372L,47373L,47374L,
94533 47375L,47376L,47377L,47378L,47379L,47380L,47381L,47382L,47383L,47384L,
94534 47385L,47386L,47387L,47388L,47389L,47390L,47391L,47392L,47393L,47394L,
94535 47395L,47396L,47397L,47398L,47399L,47400L,47401L,47402L,47403L,47404L,
94536 47405L,47406L,47407L,47408L,47409L,47410L,47411L,47412L,47413L,47414L,
94537 47415L,47416L,47417L,47418L,47419L,47420L,47421L,47422L,47423L,47424L,
94538 47425L,47426L,47427L,47428L,47429L,47430L,47431L,47432L,47433L,47434L,
94539 47435L,47436L,47437L,47438L,47439L,47440L,47441L,47442L,47443L,47444L,
94540 47445L,47446L,47447L,47448L,47449L,47450L,47451L,47452L,47453L,47454L,
94541 47455L,47456L,47457L,47458L,47459L,47460L,47461L,47462L,47463L,47464L,
94542 47465L,47466L,47467L,47468L,47469L,47470L,47471L,47472L,47473L,47474L,
94543 47475L,47476L,47477L,47478L,47479L,47480L,47481L,47482L,47483L,47484L,
94544 47485L,47486L,47487L,47488L,47489L,47490L,47491L,47492L,47493L,47494L,
94545 47495L,47496L,47497L,47498L,47499L,47500L,47501L,47502L,47503L,47504L,
94546 47505L,47506L,47507L,47508L,47509L,47510L,47511L,47512L,47513L,47514L,
94547 47515L,47516L,47517L,47518L,47519L,47520L,47521L,47522L,47523L,47524L,
94548 47525L,47526L,47527L,47528L,47529L,47530L,47531L,47532L,47533L,47534L,
94549 47535L,47536L,47537L,47538L,47539L,47540L,47541L,47542L,47543L,47544L,
94550 47545L,47546L,47547L,47548L,47549L,47550L,47551L,47552L,47553L,47554L,
94551 47555L,47556L,47557L,47558L,47559L,47560L,47561L,47562L,47563L,47564L,
94552 47565L,47566L,47567L,47568L,47569L,47570L,47571L,47572L,47573L,47574L,
94553 47575L,47576L,47577L,47578L,47579L,47580L,47581L,47582L,47583L,47584L,
94554 47585L,47586L,47587L,47588L,47589L,47590L,47591L,47592L,47593L,47594L,
94555 47595L,47596L,47597L,47598L,47599L,47600L,47601L,47602L,47603L,47604L,
94556 47605L,47606L,47607L,47608L,47609L,47610L,47611L,47612L,47613L,47614L,
94557 47615L,47616L,47617L,47618L,47619L,47620L,47621L,47622L,47623L,47624L,
94558 47625L,47626L,47627L,47628L,47629L,47630L,47631L,47632L,47633L,47634L,
94559 47635L,47636L,47637L,47638L,47639L,47640L,47641L,47642L,47643L,47644L,
94560 47645L,47646L,47647L,47648L,47649L,47650L,47651L,47652L,47653L,47654L,
94561 47655L,47656L,47657L,47658L,47659L,47660L,47661L,47662L,47663L,47664L,
94562 47665L,47666L,47667L,47668L,47669L,47670L,47671L,47672L,47673L,47674L,
94563 47675L,47676L,47677L,47678L,47679L,47680L,47681L,47682L,47683L,47684L,
94564 47685L,47686L,47687L,47688L,47689L,47690L,47691L,47692L,47693L,47694L,
94565 47695L,47696L,47697L,47698L,47699L,47700L,47701L,47702L,47703L,47704L,
94566 47705L,47706L,47707L,47708L,47709L,47710L,47711L,47712L,47713L,47714L,
94567 47715L,47716L,47717L,47718L,47719L,47720L,47721L,47722L,47723L,47724L,
94568 47725L,47726L,47727L,47728L,47729L,47730L,47731L,47732L,47733L,47734L,
94569 47735L,47736L,47737L,47738L,47739L,47740L,47741L,47742L,47743L,47744L,
94570 47745L,47746L,47747L,47748L,47749L,47750L,47751L,47752L,47753L,47754L,
94571 47755L,47756L,47757L,47758L,47759L,47760L,47761L,47762L,47763L,47764L,
94572 47765L,47766L,47767L,47768L,47769L,47770L,47771L,47772L,47773L,47774L,
94573 47775L,47776L,47777L,47778L,47779L,47780L,47781L,47782L,47783L,47784L,
94574 47785L,47786L,47787L,47788L,47789L,47790L,47791L,47792L,47793L,47794L,
94575 47795L,47796L,47797L,47798L,47799L,47800L,47801L,47802L,47803L,47804L,
94576 47805L,47806L,47807L,47808L,47809L,47810L,47811L,47812L,47813L,47814L,
94577 47815L,47816L,47817L,47818L,47819L,47820L,47821L,47822L,47823L,47824L,
94578 47825L,47826L,47827L,47828L,47829L,47830L,47831L,47832L,47833L,47834L,
94579 47835L,47836L,47837L,47838L,47839L,47840L,47841L,47842L,47843L,47844L,
94580 47845L,47846L,47847L,47848L,47849L,47850L,47851L,47852L,47853L,47854L,
94581 47855L,47856L,47857L,47858L,47859L,47860L,47861L,47862L,47863L,47864L,
94582 47865L,47866L,47867L,47868L,47869L,47870L,47871L,47872L,47873L,47874L,
94583 47875L,47876L,47877L,47878L,47879L,47880L,47881L,47882L,47883L,47884L,
94584 47885L,47886L,47887L,47888L,47889L,47890L,47891L,47892L,47893L,47894L,
94585 47895L,47896L,47897L,47898L,47899L,47900L,47901L,47902L,47903L,47904L,
94586 47905L,47906L,47907L,47908L,47909L,47910L,47911L,47912L,47913L,47914L,
94587 47915L,47916L,47917L,47918L,47919L,47920L,47921L,47922L,47923L,47924L,
94588 47925L,47926L,47927L,47928L,47929L,47930L,47931L,47932L,47933L,47934L,
94589 47935L,47936L,47937L,47938L,47939L,47940L,47941L,47942L,47943L,47944L,
94590 47945L,47946L,47947L,47948L,47949L,47950L,47951L,47952L,47953L,47954L,
94591 47955L,47956L,47957L,47958L,47959L,47960L,47961L,47962L,47963L,47964L,
94592 47965L,47966L,47967L,47968L,47969L,47970L,47971L,47972L,47973L,47974L,
94593 47975L,47976L,47977L,47978L,47979L,47980L,47981L,47982L,47983L,47984L,
94594 47985L,47986L,47987L,47988L,47989L,47990L,47991L,47992L,47993L,47994L,
94595 47995L,47996L,47997L,47998L,47999L,48000L,48001L,48002L,48003L,48004L,
94596 48005L,48006L,48007L,48008L,48009L,48010L,48011L,48012L,48013L,48014L,
94597 48015L,48016L,48017L,48018L,48019L,48020L,48021L,48022L,48023L,48024L,
94598 48025L,48026L,48027L,48028L,48029L,48030L,48031L,48032L,48033L,48034L,
94599 48035L,48036L,48037L,48038L,48039L,48040L,48041L,48042L,48043L,48044L,
94600 48045L,48046L,48047L,48048L,48049L,48050L,48051L,48052L,48053L,48054L,
94601 48055L,48056L,48057L,48058L,48059L,48060L,48061L,48062L,48063L,48064L,
94602 48065L,48066L,48067L,48068L,48069L,48070L,48071L,48072L,48073L,48074L,
94603 48075L,48076L,48077L,48078L,48079L,48080L,48081L,48082L,48083L,48084L,
94604 48085L,48086L,48087L,48088L,48089L,48090L,48091L,48092L,48093L,48094L,
94605 48095L,48096L,48097L,48098L,48099L,48100L,48101L,48102L,48103L,48104L,
94606 48105L,48106L,48107L,48108L,48109L,48110L,48111L,48112L,48113L,48114L,
94607 48115L,48116L,48117L,48118L,48119L,48120L,48121L,48122L,48123L,48124L,
94608 48125L,48126L,48127L,48128L,48129L,48130L,48131L,48132L,48133L,48134L,
94609 48135L,48136L,48137L,48138L,48139L,48140L,48141L,48142L,48143L,48144L,
94610 48145L,48146L,48147L,48148L,48149L,48150L,48151L,48152L,48153L,48154L,
94611 48155L,48156L,48157L,48158L,48159L,48160L,48161L,48162L,48163L,48164L,
94612 48165L,48166L,48167L,48168L,48169L,48170L,48171L,48172L,48173L,48174L,
94613 48175L,48176L,48177L,48178L,48179L,48180L,48181L,48182L,48183L,48184L,
94614 48185L,48186L,48187L,48188L,48189L,48190L,48191L,48192L,48193L,48194L,
94615 48195L,48196L,48197L,48198L,48199L,48200L,48201L,48202L,48203L,48204L,
94616 48205L,48206L,48207L,48208L,48209L,48210L,48211L,48212L,48213L,48214L,
94617 48215L,48216L,48217L,48218L,48219L,48220L,48221L,48222L,48223L,48224L,
94618 48225L,48226L,48227L,48228L,48229L,48230L,48231L,48232L,48233L,48234L,
94619 48235L,48236L,48237L,48238L,48239L,48240L,48241L,48242L,48243L,48244L,
94620 48245L,48246L,48247L,48248L,48249L,48250L,48251L,48252L,48253L,48254L,
94621 48255L,48256L,48257L,48258L,48259L,48260L,48261L,48262L,48263L,48264L,
94622 48265L,48266L,48267L,48268L,48269L,48270L,48271L,48272L,48273L,48274L,
94623 48275L,48276L,48277L,48278L,48279L,48280L,48281L,48282L,48283L,48284L,
94624 48285L,48286L,48287L,48288L,48289L,48290L,48291L,48292L,48293L,48294L,
94625 48295L,48296L,48297L,48298L,48299L,48300L,48301L,48302L,48303L,48304L,
94626 48305L,48306L,48307L,48308L,48309L,48310L,48311L,48312L,48313L,48314L,
94627 48315L,48316L,48317L,48318L,48319L,48320L,48321L,48322L,48323L,48324L,
94628 48325L,48326L,48327L,48328L,48329L,48330L,48331L,48332L,48333L,48334L,
94629 48335L,48336L,48337L,48338L,48339L,48340L,48341L,48342L,48343L,48344L,
94630 48345L,48346L,48347L,48348L,48349L,48350L,48351L,48352L,48353L,48354L,
94631 48355L,48356L,48357L,48358L,48359L,48360L,48361L,48362L,48363L,48364L,
94632 48365L,48366L,48367L,48368L,48369L,48370L,48371L,48372L,48373L,48374L,
94633 48375L,48376L,48377L,48378L,48379L,48380L,48381L,48382L,48383L,48384L,
94634 48385L,48386L,48387L,48388L,48389L,48390L,48391L,48392L,48393L,48394L,
94635 48395L,48396L,48397L,48398L,48399L,48400L,48401L,48402L,48403L,48404L,
94636 48405L,48406L,48407L,48408L,48409L,48410L,48411L,48412L,48413L,48414L,
94637 48415L,48416L,48417L,48418L,48419L,48420L,48421L,48422L,48423L,48424L,
94638 48425L,48426L,48427L,48428L,48429L,48430L,48431L,48432L,48433L,48434L,
94639 48435L,48436L,48437L,48438L,48439L,48440L,48441L,48442L,48443L,48444L,
94640 48445L,48446L,48447L,48448L,48449L,48450L,48451L,48452L,48453L,48454L,
94641 48455L,48456L,48457L,48458L,48459L,48460L,48461L,48462L,48463L,48464L,
94642 48465L,48466L,48467L,48468L,48469L,48470L,48471L,48472L,48473L,48474L,
94643 48475L,48476L,48477L,48478L,48479L,48480L,48481L,48482L,48483L,48484L,
94644 48485L,48486L,48487L,48488L,48489L,48490L,48491L,48492L,48493L,48494L,
94645 48495L,48496L,48497L,48498L,48499L,48500L,48501L,48502L,48503L,48504L,
94646 48505L,48506L,48507L,48508L,48509L,48510L,48511L,48512L,48513L,48514L,
94647 48515L,48516L,48517L,48518L,48519L,48520L,48521L,48522L,48523L,48524L,
94648 48525L,48526L,48527L,48528L,48529L,48530L,48531L,48532L,48533L,48534L,
94649 48535L,48536L,48537L,48538L,48539L,48540L,48541L,48542L,48543L,48544L,
94650 48545L,48546L,48547L,48548L,48549L,48550L,48551L,48552L,48553L,48554L,
94651 48555L,48556L,48557L,48558L,48559L,48560L,48561L,48562L,48563L,48564L,
94652 48565L,48566L,48567L,48568L,48569L,48570L,48571L,48572L,48573L,48574L,
94653 48575L,48576L,48577L,48578L,48579L,48580L,48581L,48582L,48583L,48584L,
94654 48585L,48586L,48587L,48588L,48589L,48590L,48591L,48592L,48593L,48594L,
94655 48595L,48596L,48597L,48598L,48599L,48600L,48601L,48602L,48603L,48604L,
94656 48605L,48606L,48607L,48608L,48609L,48610L,48611L,48612L,48613L,48614L,
94657 48615L,48616L,48617L,48618L,48619L,48620L,48621L,48622L,48623L,48624L,
94658 48625L,48626L,48627L,48628L,48629L,48630L,48631L,48632L,48633L,48634L,
94659 48635L,48636L,48637L,48638L,48639L,48640L,48641L,48642L,48643L,48644L,
94660 48645L,48646L,48647L,48648L,48649L,48650L,48651L,48652L,48653L,48654L,
94661 48655L,48656L,48657L,48658L,48659L,48660L,48661L,48662L,48663L,48664L,
94662 48665L,48666L,48667L,48668L,48669L,48670L,48671L,48672L,48673L,48674L,
94663 48675L,48676L,48677L,48678L,48679L,48680L,48681L,48682L,48683L,48684L,
94664 48685L,48686L,48687L,48688L,48689L,48690L,48691L,48692L,48693L,48694L,
94665 48695L,48696L,48697L,48698L,48699L,48700L,48701L,48702L,48703L,48704L,
94666 48705L,48706L,48707L,48708L,48709L,48710L,48711L,48712L,48713L,48714L,
94667 48715L,48716L,48717L,48718L,48719L,48720L,48721L,48722L,48723L,48724L,
94668 48725L,48726L,48727L,48728L,48729L,48730L,48731L,48732L,48733L,48734L,
94669 48735L,48736L,48737L,48738L,48739L,48740L,48741L,48742L,48743L,48744L,
94670 48745L,48746L,48747L,48748L,48749L,48750L,48751L,48752L,48753L,48754L,
94671 48755L,48756L,48757L,48758L,48759L,48760L,48761L,48762L,48763L,48764L,
94672 48765L,48766L,48767L,48768L,48769L,48770L,48771L,48772L,48773L,48774L,
94673 48775L,48776L,48777L,48778L,48779L,48780L,48781L,48782L,48783L,48784L,
94674 48785L,48786L,48787L,48788L,48789L,48790L,48791L,48792L,48793L,48794L,
94675 48795L,48796L,48797L,48798L,48799L,48800L,48801L,48802L,48803L,48804L,
94676 48805L,48806L,48807L,48808L,48809L,48810L,48811L,48812L,48813L,48814L,
94677 48815L,48816L,48817L,48818L,48819L,48820L,48821L,48822L,48823L,48824L,
94678 48825L,48826L,48827L,48828L,48829L,48830L,48831L,48832L,48833L,48834L,
94679 48835L,48836L,48837L,48838L,48839L,48840L,48841L,48842L,48843L,48844L,
94680 48845L,48846L,48847L,48848L,48849L,48850L,48851L,48852L,48853L,48854L,
94681 48855L,48856L,48857L,48858L,48859L,48860L,48861L,48862L,48863L,48864L,
94682 48865L,48866L,48867L,48868L,48869L,48870L,48871L,48872L,48873L,48874L,
94683 48875L,48876L,48877L,48878L,48879L,48880L,48881L,48882L,48883L,48884L,
94684 48885L,48886L,48887L,48888L,48889L,48890L,48891L,48892L,48893L,48894L,
94685 48895L,48896L,48897L,48898L,48899L,48900L,48901L,48902L,48903L,48904L,
94686 48905L,48906L,48907L,48908L,48909L,48910L,48911L,48912L,48913L,48914L,
94687 48915L,48916L,48917L,48918L,48919L,48920L,48921L,48922L,48923L,48924L,
94688 48925L,48926L,48927L,48928L,48929L,48930L,48931L,48932L,48933L,48934L,
94689 48935L,48936L,48937L,48938L,48939L,48940L,48941L,48942L,48943L,48944L,
94690 48945L,48946L,48947L,48948L,48949L,48950L,48951L,48952L,48953L,48954L,
94691 48955L,48956L,48957L,48958L,48959L,48960L,48961L,48962L,48963L,48964L,
94692 48965L,48966L,48967L,48968L,48969L,48970L,48971L,48972L,48973L,48974L,
94693 48975L,48976L,48977L,48978L,48979L,48980L,48981L,48982L,48983L,48984L,
94694 48985L,48986L,48987L,48988L,48989L,48990L,48991L,48992L,48993L,48994L,
94695 48995L,48996L,48997L,48998L,48999L,49000L,49001L,49002L,49003L,49004L,
94696 49005L,49006L,49007L,49008L,49009L,49010L,49011L,49012L,49013L,49014L,
94697 49015L,49016L,49017L,49018L,49019L,49020L,49021L,49022L,49023L,49024L,
94698 49025L,49026L,49027L,49028L,49029L,49030L,49031L,49032L,49033L,49034L,
94699 49035L,49036L,49037L,49038L,49039L,49040L,49041L,49042L,49043L,49044L,
94700 49045L,49046L,49047L,49048L,49049L,49050L,49051L,49052L,49053L,49054L,
94701 49055L,49056L,49057L,49058L,49059L,49060L,49061L,49062L,49063L,49064L,
94702 49065L,49066L,49067L,49068L,49069L,49070L,49071L,49072L,49073L,49074L,
94703 49075L,49076L,49077L,49078L,49079L,49080L,49081L,49082L,49083L,49084L,
94704 49085L,49086L,49087L,49088L,49089L,49090L,49091L,49092L,49093L,49094L,
94705 49095L,49096L,49097L,49098L,49099L,49100L,49101L,49102L,49103L,49104L,
94706 49105L,49106L,49107L,49108L,49109L,49110L,49111L,49112L,49113L,49114L,
94707 49115L,49116L,49117L,49118L,49119L,49120L,49121L,49122L,49123L,49124L,
94708 49125L,49126L,49127L,49128L,49129L,49130L,49131L,49132L,49133L,49134L,
94709 49135L,49136L,49137L,49138L,49139L,49140L,49141L,49142L,49143L,49144L,
94710 49145L,49146L,49147L,49148L,49149L,49150L,49151L,49152L,49153L,49154L,
94711 49155L,49156L,49157L,49158L,49159L,49160L,49161L,49162L,49163L,49164L,
94712 49165L,49166L,49167L,49168L,49169L,49170L,49171L,49172L,49173L,49174L,
94713 49175L,49176L,49177L,49178L,49179L,49180L,49181L,49182L,49183L,49184L,
94714 49185L,49186L,49187L,49188L,49189L,49190L,49191L,49192L,49193L,49194L,
94715 49195L,49196L,49197L,49198L,49199L,49200L,49201L,49202L,49203L,49204L,
94716 49205L,49206L,49207L,49208L,49209L,49210L,49211L,49212L,49213L,49214L,
94717 49215L,49216L,49217L,49218L,49219L,49220L,49221L,49222L,49223L,49224L,
94718 49225L,49226L,49227L,49228L,49229L,49230L,49231L,49232L,49233L,49234L,
94719 49235L,49236L,49237L,49238L,49239L,49240L,49241L,49242L,49243L,49244L,
94720 49245L,49246L,49247L,49248L,49249L,49250L,49251L,49252L,49253L,49254L,
94721 49255L,49256L,49257L,49258L,49259L,49260L,49261L,49262L,49263L,49264L,
94722 49265L,49266L,49267L,49268L,49269L,49270L,49271L,49272L,49273L,49274L,
94723 49275L,49276L,49277L,49278L,49279L,49280L,49281L,49282L,49283L,49284L,
94724 49285L,49286L,49287L,49288L,49289L,49290L,49291L,49292L,49293L,49294L,
94725 49295L,49296L,49297L,49298L,49299L,49300L,49301L,49302L,49303L,49304L,
94726 49305L,49306L,49307L,49308L,49309L,49310L,49311L,49312L,49313L,49314L,
94727 49315L,49316L,49317L,49318L,49319L,49320L,49321L,49322L,49323L,49324L,
94728 49325L,49326L,49327L,49328L,49329L,49330L,49331L,49332L,49333L,49334L,
94729 49335L,49336L,49337L,49338L,49339L,49340L,49341L,49342L,49343L,49344L,
94730 49345L,49346L,49347L,49348L,49349L,49350L,49351L,49352L,49353L,49354L,
94731 49355L,49356L,49357L,49358L,49359L,49360L,49361L,49362L,49363L,49364L,
94732 49365L,49366L,49367L,49368L,49369L,49370L,49371L,49372L,49373L,49374L,
94733 49375L,49376L,49377L,49378L,49379L,49380L,49381L,49382L,49383L,49384L,
94734 49385L,49386L,49387L,49388L,49389L,49390L,49391L,49392L,49393L,49394L,
94735 49395L,49396L,49397L,49398L,49399L,49400L,49401L,49402L,49403L,49404L,
94736 49405L,49406L,49407L,49408L,49409L,49410L,49411L,49412L,49413L,49414L,
94737 49415L,49416L,49417L,49418L,49419L,49420L,49421L,49422L,49423L,49424L,
94738 49425L,49426L,49427L,49428L,49429L,49430L,49431L,49432L,49433L,49434L,
94739 49435L,49436L,49437L,49438L,49439L,49440L,49441L,49442L,49443L,49444L,
94740 49445L,49446L,49447L,49448L,49449L,49450L,49451L,49452L,49453L,49454L,
94741 49455L,49456L,49457L,49458L,49459L,49460L,49461L,49462L,49463L,49464L,
94742 49465L,49466L,49467L,49468L,49469L,49470L,49471L,49472L,49473L,49474L,
94743 49475L,49476L,49477L,49478L,49479L,49480L,49481L,49482L,49483L,49484L,
94744 49485L,49486L,49487L,49488L,49489L,49490L,49491L,49492L,49493L,49494L,
94745 49495L,49496L,49497L,49498L,49499L,49500L,49501L,49502L,49503L,49504L,
94746 49505L,49506L,49507L,49508L,49509L,49510L,49511L,49512L,49513L,49514L,
94747 49515L,49516L,49517L,49518L,49519L,49520L,49521L,49522L,49523L,49524L,
94748 49525L,49526L,49527L,49528L,49529L,49530L,49531L,49532L,49533L,49534L,
94749 49535L,49536L,49537L,49538L,49539L,49540L,49541L,49542L,49543L,49544L,
94750 49545L,49546L,49547L,49548L,49549L,49550L,49551L,49552L,49553L,49554L,
94751 49555L,49556L,49557L,49558L,49559L,49560L,49561L,49562L,49563L,49564L,
94752 49565L,49566L,49567L,49568L,49569L,49570L,49571L,49572L,49573L,49574L,
94753 49575L,49576L,49577L,49578L,49579L,49580L,49581L,49582L,49583L,49584L,
94754 49585L,49586L,49587L,49588L,49589L,49590L,49591L,49592L,49593L,49594L,
94755 49595L,49596L,49597L,49598L,49599L,49600L,49601L,49602L,49603L,49604L,
94756 49605L,49606L,49607L,49608L,49609L,49610L,49611L,49612L,49613L,49614L,
94757 49615L,49616L,49617L,49618L,49619L,49620L,49621L,49622L,49623L,49624L,
94758 49625L,49626L,49627L,49628L,49629L,49630L,49631L,49632L,49633L,49634L,
94759 49635L,49636L,49637L,49638L,49639L,49640L,49641L,49642L,49643L,49644L,
94760 49645L,49646L,49647L,49648L,49649L,49650L,49651L,49652L,49653L,49654L,
94761 49655L,49656L,49657L,49658L,49659L,49660L,49661L,49662L,49663L,49664L,
94762 49665L,49666L,49667L,49668L,49669L,49670L,49671L,49672L,49673L,49674L,
94763 49675L,49676L,49677L,49678L,49679L,49680L,49681L,49682L,49683L,49684L,
94764 49685L,49686L,49687L,49688L,49689L,49690L,49691L,49692L,49693L,49694L,
94765 49695L,49696L,49697L,49698L,49699L,49700L,49701L,49702L,49703L,49704L,
94766 49705L,49706L,49707L,49708L,49709L,49710L,49711L,49712L,49713L,49714L,
94767 49715L,49716L,49717L,49718L,49719L,49720L,49721L,49722L,49723L,49724L,
94768 49725L,49726L,49727L,49728L,49729L,49730L,49731L,49732L,49733L,49734L,
94769 49735L,49736L,49737L,49738L,49739L,49740L,49741L,49742L,49743L,49744L,
94770 49745L,49746L,49747L,49748L,49749L,49750L,49751L,49752L,49753L,49754L,
94771 49755L,49756L,49757L,49758L,49759L,49760L,49761L,49762L,49763L,49764L,
94772 49765L,49766L,49767L,49768L,49769L,49770L,49771L,49772L,49773L,49774L,
94773 49775L,49776L,49777L,49778L,49779L,49780L,49781L,49782L,49783L,49784L,
94774 49785L,49786L,49787L,49788L,49789L,49790L,49791L,49792L,49793L,49794L,
94775 49795L,49796L,49797L,49798L,49799L,49800L,49801L,49802L,49803L,49804L,
94776 49805L,49806L,49807L,49808L,49809L,49810L,49811L,49812L,49813L,49814L,
94777 49815L,49816L,49817L,49818L,49819L,49820L,49821L,49822L,49823L,49824L,
94778 49825L,49826L,49827L,49828L,49829L,49830L,49831L,49832L,49833L,49834L,
94779 49835L,49836L,49837L,49838L,49839L,49840L,49841L,49842L,49843L,49844L,
94780 49845L,49846L,49847L,49848L,49849L,49850L,49851L,49852L,49853L,49854L,
94781 49855L,49856L,49857L,49858L,49859L,49860L,49861L,49862L,49863L,49864L,
94782 49865L,49866L,49867L,49868L,49869L,49870L,49871L,49872L,49873L,49874L,
94783 49875L,49876L,49877L,49878L,49879L,49880L,49881L,49882L,49883L,49884L,
94784 49885L,49886L,49887L,49888L,49889L,49890L,49891L,49892L,49893L,49894L,
94785 49895L,49896L,49897L,49898L,49899L,49900L,49901L,49902L,49903L,49904L,
94786 49905L,49906L,49907L,49908L,49909L,49910L,49911L,49912L,49913L,49914L,
94787 49915L,49916L,49917L,49918L,49919L,49920L,49921L,49922L,49923L,49924L,
94788 49925L,49926L,49927L,49928L,49929L,49930L,49931L,49932L,49933L,49934L,
94789 49935L,49936L,49937L,49938L,49939L,49940L,49941L,49942L,49943L,49944L,
94790 49945L,49946L,49947L,49948L,49949L,49950L,49951L,49952L,49953L,49954L,
94791 49955L,49956L,49957L,49958L,49959L,49960L,49961L,49962L,49963L,49964L,
94792 49965L,49966L,49967L,49968L,49969L,49970L,49971L,49972L,49973L,49974L,
94793 49975L,49976L,49977L,49978L,49979L,49980L,49981L,49982L,49983L,49984L,
94794 49985L,49986L,49987L,49988L,49989L,49990L,49991L,49992L,49993L,49994L,
94795 49995L,49996L,49997L,49998L,49999L,50000L,50001L,50002L,50003L,50004L,
94796 50005L,50006L,50007L,50008L,50009L,50010L,50011L,50012L,50013L,50014L,
94797 50015L,50016L,50017L,50018L,50019L,50020L,50021L,50022L,50023L,50024L,
94798 50025L,50026L,50027L,50028L,50029L,50030L,50031L,50032L,50033L,50034L,
94799 50035L,50036L,50037L,50038L,50039L,50040L,50041L,50042L,50043L,50044L,
94800 50045L,50046L,50047L,50048L,50049L,50050L,50051L,50052L,50053L,50054L,
94801 50055L,50056L,50057L,50058L,50059L,50060L,50061L,50062L,50063L,50064L,
94802 50065L,50066L,50067L,50068L,50069L,50070L,50071L,50072L,50073L,50074L,
94803 50075L,50076L,50077L,50078L,50079L,50080L,50081L,50082L,50083L,50084L,
94804 50085L,50086L,50087L,50088L,50089L,50090L,50091L,50092L,50093L,50094L,
94805 50095L,50096L,50097L,50098L,50099L,50100L,50101L,50102L,50103L,50104L,
94806 50105L,50106L,50107L,50108L,50109L,50110L,50111L,50112L,50113L,50114L,
94807 50115L,50116L,50117L,50118L,50119L,50120L,50121L,50122L,50123L,50124L,
94808 50125L,50126L,50127L,50128L,50129L,50130L,50131L,50132L,50133L,50134L,
94809 50135L,50136L,50137L,50138L,50139L,50140L,50141L,50142L,50143L,50144L,
94810 50145L,50146L,50147L,50148L,50149L,50150L,50151L,50152L,50153L,50154L,
94811 50155L,50156L,50157L,50158L,50159L,50160L,50161L,50162L,50163L,50164L,
94812 50165L,50166L,50167L,50168L,50169L,50170L,50171L,50172L,50173L,50174L,
94813 50175L,50176L,50177L,50178L,50179L,50180L,50181L,50182L,50183L,50184L,
94814 50185L,50186L,50187L,50188L,50189L,50190L,50191L,50192L,50193L,50194L,
94815 50195L,50196L,50197L,50198L,50199L,50200L,50201L,50202L,50203L,50204L,
94816 50205L,50206L,50207L,50208L,50209L,50210L,50211L,50212L,50213L,50214L,
94817 50215L,50216L,50217L,50218L,50219L,50220L,50221L,50222L,50223L,50224L,
94818 50225L,50226L,50227L,50228L,50229L,50230L,50231L,50232L,50233L,50234L,
94819 50235L,50236L,50237L,50238L,50239L,50240L,50241L,50242L,50243L,50244L,
94820 50245L,50246L,50247L,50248L,50249L,50250L,50251L,50252L,50253L,50254L,
94821 50255L,50256L,50257L,50258L,50259L,50260L,50261L,50262L,50263L,50264L,
94822 50265L,50266L,50267L,50268L,50269L,50270L,50271L,50272L,50273L,50274L,
94823 50275L,50276L,50277L,50278L,50279L,50280L,50281L,50282L,50283L,50284L,
94824 50285L,50286L,50287L,50288L,50289L,50290L,50291L,50292L,50293L,50294L,
94825 50295L,50296L,50297L,50298L,50299L,50300L,50301L,50302L,50303L,50304L,
94826 50305L,50306L,50307L,50308L,50309L,50310L,50311L,50312L,50313L,50314L,
94827 50315L,50316L,50317L,50318L,50319L,50320L,50321L,50322L,50323L,50324L,
94828 50325L,50326L,50327L,50328L,50329L,50330L,50331L,50332L,50333L,50334L,
94829 50335L,50336L,50337L,50338L,50339L,50340L,50341L,50342L,50343L,50344L,
94830 50345L,50346L,50347L,50348L,50349L,50350L,50351L,50352L,50353L,50354L,
94831 50355L,50356L,50357L,50358L,50359L,50360L,50361L,50362L,50363L,50364L,
94832 50365L,50366L,50367L,50368L,50369L,50370L,50371L,50372L,50373L,50374L,
94833 50375L,50376L,50377L,50378L,50379L,50380L,50381L,50382L,50383L,50384L,
94834 50385L,50386L,50387L,50388L,50389L,50390L,50391L,50392L,50393L,50394L,
94835 50395L,50396L,50397L,50398L,50399L,50400L,50401L,50402L,50403L,50404L,
94836 50405L,50406L,50407L,50408L,50409L,50410L,50411L,50412L,50413L,50414L,
94837 50415L,50416L,50417L,50418L,50419L,50420L,50421L,50422L,50423L,50424L,
94838 50425L,50426L,50427L,50428L,50429L,50430L,50431L,50432L,50433L,50434L,
94839 50435L,50436L,50437L,50438L,50439L,50440L,50441L,50442L,50443L,50444L,
94840 50445L,50446L,50447L,50448L,50449L,50450L,50451L,50452L,50453L,50454L,
94841 50455L,50456L,50457L,50458L,50459L,50460L,50461L,50462L,50463L,50464L,
94842 50465L,50466L,50467L,50468L,50469L,50470L,50471L,50472L,50473L,50474L,
94843 50475L,50476L,50477L,50478L,50479L,50480L,50481L,50482L,50483L,50484L,
94844 50485L,50486L,50487L,50488L,50489L,50490L,50491L,50492L,50493L,50494L,
94845 50495L,50496L,50497L,50498L,50499L,50500L,50501L,50502L,50503L,50504L,
94846 50505L,50506L,50507L,50508L,50509L,50510L,50511L,50512L,50513L,50514L,
94847 50515L,50516L,50517L,50518L,50519L,50520L,50521L,50522L,50523L,50524L,
94848 50525L,50526L,50527L,50528L,50529L,50530L,50531L,50532L,50533L,50534L,
94849 50535L,50536L,50537L,50538L,50539L,50540L,50541L,50542L,50543L,50544L,
94850 50545L,50546L,50547L,50548L,50549L,50550L,50551L,50552L,50553L,50554L,
94851 50555L,50556L,50557L,50558L,50559L,50560L,50561L,50562L,50563L,50564L,
94852 50565L,50566L,50567L,50568L,50569L,50570L,50571L,50572L,50573L,50574L,
94853 50575L,50576L,50577L,50578L,50579L,50580L,50581L,50582L,50583L,50584L,
94854 50585L,50586L,50587L,50588L,50589L,50590L,50591L,50592L,50593L,50594L,
94855 50595L,50596L,50597L,50598L,50599L,50600L,50601L,50602L,50603L,50604L,
94856 50605L,50606L,50607L,50608L,50609L,50610L,50611L,50612L,50613L,50614L,
94857 50615L,50616L,50617L,50618L,50619L,50620L,50621L,50622L,50623L,50624L,
94858 50625L,50626L,50627L,50628L,50629L,50630L,50631L,50632L,50633L,50634L,
94859 50635L,50636L,50637L,50638L,50639L,50640L,50641L,50642L,50643L,50644L,
94860 50645L,50646L,50647L,50648L,50649L,50650L,50651L,50652L,50653L,50654L,
94861 50655L,50656L,50657L,50658L,50659L,50660L,50661L,50662L,50663L,50664L,
94862 50665L,50666L,50667L,50668L,50669L,50670L,50671L,50672L,50673L,50674L,
94863 50675L,50676L,50677L,50678L,50679L,50680L,50681L,50682L,50683L,50684L,
94864 50685L,50686L,50687L,50688L,50689L,50690L,50691L,50692L,50693L,50694L,
94865 50695L,50696L,50697L,50698L,50699L,50700L,50701L,50702L,50703L,50704L,
94866 50705L,50706L,50707L,50708L,50709L,50710L,50711L,50712L,50713L,50714L,
94867 50715L,50716L,50717L,50718L,50719L,50720L,50721L,50722L,50723L,50724L,
94868 50725L,50726L,50727L,50728L,50729L,50730L,50731L,50732L,50733L,50734L,
94869 50735L,50736L,50737L,50738L,50739L,50740L,50741L,50742L,50743L,50744L,
94870 50745L,50746L,50747L,50748L,50749L,50750L,50751L,50752L,50753L,50754L,
94871 50755L,50756L,50757L,50758L,50759L,50760L,50761L,50762L,50763L,50764L,
94872 50765L,50766L,50767L,50768L,50769L,50770L,50771L,50772L,50773L,50774L,
94873 50775L,50776L,50777L,50778L,50779L,50780L,50781L,50782L,50783L,50784L,
94874 50785L,50786L,50787L,50788L,50789L,50790L,50791L,50792L,50793L,50794L,
94875 50795L,50796L,50797L,50798L,50799L,50800L,50801L,50802L,50803L,50804L,
94876 50805L,50806L,50807L,50808L,50809L,50810L,50811L,50812L,50813L,50814L,
94877 50815L,50816L,50817L,50818L,50819L,50820L,50821L,50822L,50823L,50824L,
94878 50825L,50826L,50827L,50828L,50829L,50830L,50831L,50832L,50833L,50834L,
94879 50835L,50836L,50837L,50838L,50839L,50840L,50841L,50842L,50843L,50844L,
94880 50845L,50846L,50847L,50848L,50849L,50850L,50851L,50852L,50853L,50854L,
94881 50855L,50856L,50857L,50858L,50859L,50860L,50861L,50862L,50863L,50864L,
94882 50865L,50866L,50867L,50868L,50869L,50870L,50871L,50872L,50873L,50874L,
94883 50875L,50876L,50877L,50878L,50879L,50880L,50881L,50882L,50883L,50884L,
94884 50885L,50886L,50887L,50888L,50889L,50890L,50891L,50892L,50893L,50894L,
94885 50895L,50896L,50897L,50898L,50899L,50900L,50901L,50902L,50903L,50904L,
94886 50905L,50906L,50907L,50908L,50909L,50910L,50911L,50912L,50913L,50914L,
94887 50915L,50916L,50917L,50918L,50919L,50920L,50921L,50922L,50923L,50924L,
94888 50925L,50926L,50927L,50928L,50929L,50930L,50931L,50932L,50933L,50934L,
94889 50935L,50936L,50937L,50938L,50939L,50940L,50941L,50942L,50943L,50944L,
94890 50945L,50946L,50947L,50948L,50949L,50950L,50951L,50952L,50953L,50954L,
94891 50955L,50956L,50957L,50958L,50959L,50960L,50961L,50962L,50963L,50964L,
94892 50965L,50966L,50967L,50968L,50969L,50970L,50971L,50972L,50973L,50974L,
94893 50975L,50976L,50977L,50978L,50979L,50980L,50981L,50982L,50983L,50984L,
94894 50985L,50986L,50987L,50988L,50989L,50990L,50991L,50992L,50993L,50994L,
94895 50995L,50996L,50997L,50998L,50999L,51000L,51001L,51002L,51003L,51004L,
94896 51005L,51006L,51007L,51008L,51009L,51010L,51011L,51012L,51013L,51014L,
94897 51015L,51016L,51017L,51018L,51019L,51020L,51021L,51022L,51023L,51024L,
94898 51025L,51026L,51027L,51028L,51029L,51030L,51031L,51032L,51033L,51034L,
94899 51035L,51036L,51037L,51038L,51039L,51040L,51041L,51042L,51043L,51044L,
94900 51045L,51046L,51047L,51048L,51049L,51050L,51051L,51052L,51053L,51054L,
94901 51055L,51056L,51057L,51058L,51059L,51060L,51061L,51062L,51063L,51064L,
94902 51065L,51066L,51067L,51068L,51069L,51070L,51071L,51072L,51073L,51074L,
94903 51075L,51076L,51077L,51078L,51079L,51080L,51081L,51082L,51083L,51084L,
94904 51085L,51086L,51087L,51088L,51089L,51090L,51091L,51092L,51093L,51094L,
94905 51095L,51096L,51097L,51098L,51099L,51100L,51101L,51102L,51103L,51104L,
94906 51105L,51106L,51107L,51108L,51109L,51110L,51111L,51112L,51113L,51114L,
94907 51115L,51116L,51117L,51118L,51119L,51120L,51121L,51122L,51123L,51124L,
94908 51125L,51126L,51127L,51128L,51129L,51130L,51131L,51132L,51133L,51134L,
94909 51135L,51136L,51137L,51138L,51139L,51140L,51141L,51142L,51143L,51144L,
94910 51145L,51146L,51147L,51148L,51149L,51150L,51151L,51152L,51153L,51154L,
94911 51155L,51156L,51157L,51158L,51159L,51160L,51161L,51162L,51163L,51164L,
94912 51165L,51166L,51167L,51168L,51169L,51170L,51171L,51172L,51173L,51174L,
94913 51175L,51176L,51177L,51178L,51179L,51180L,51181L,51182L,51183L,51184L,
94914 51185L,51186L,51187L,51188L,51189L,51190L,51191L,51192L,51193L,51194L,
94915 51195L,51196L,51197L,51198L,51199L,51200L,51201L,51202L,51203L,51204L,
94916 51205L,51206L,51207L,51208L,51209L,51210L,51211L,51212L,51213L,51214L,
94917 51215L,51216L,51217L,51218L,51219L,51220L,51221L,51222L,51223L,51224L,
94918 51225L,51226L,51227L,51228L,51229L,51230L,51231L,51232L,51233L,51234L,
94919 51235L,51236L,51237L,51238L,51239L,51240L,51241L,51242L,51243L,51244L,
94920 51245L,51246L,51247L,51248L,51249L,51250L,51251L,51252L,51253L,51254L,
94921 51255L,51256L,51257L,51258L,51259L,51260L,51261L,51262L,51263L,51264L,
94922 51265L,51266L,51267L,51268L,51269L,51270L,51271L,51272L,51273L,51274L,
94923 51275L,51276L,51277L,51278L,51279L,51280L,51281L,51282L,51283L,51284L,
94924 51285L,51286L,51287L,51288L,51289L,51290L,51291L,51292L,51293L,51294L,
94925 51295L,51296L,51297L,51298L,51299L,51300L,51301L,51302L,51303L,51304L,
94926 51305L,51306L,51307L,51308L,51309L,51310L,51311L,51312L,51313L,51314L,
94927 51315L,51316L,51317L,51318L,51319L,51320L,51321L,51322L,51323L,51324L,
94928 51325L,51326L,51327L,51328L,51329L,51330L,51331L,51332L,51333L,51334L,
94929 51335L,51336L,51337L,51338L,51339L,51340L,51341L,51342L,51343L,51344L,
94930 51345L,51346L,51347L,51348L,51349L,51350L,51351L,51352L,51353L,51354L,
94931 51355L,51356L,51357L,51358L,51359L,51360L,51361L,51362L,51363L,51364L,
94932 51365L,51366L,51367L,51368L,51369L,51370L,51371L,51372L,51373L,51374L,
94933 51375L,51376L,51377L,51378L,51379L,51380L,51381L,51382L,51383L,51384L,
94934 51385L,51386L,51387L,51388L,51389L,51390L,51391L,51392L,51393L,51394L,
94935 51395L,51396L,51397L,51398L,51399L,51400L,51401L,51402L,51403L,51404L,
94936 51405L,51406L,51407L,51408L,51409L,51410L,51411L,51412L,51413L,51414L,
94937 51415L,51416L,51417L,51418L,51419L,51420L,51421L,51422L,51423L,51424L,
94938 51425L,51426L,51427L,51428L,51429L,51430L,51431L,51432L,51433L,51434L,
94939 51435L,51436L,51437L,51438L,51439L,51440L,51441L,51442L,51443L,51444L,
94940 51445L,51446L,51447L,51448L,51449L,51450L,51451L,51452L,51453L,51454L,
94941 51455L,51456L,51457L,51458L,51459L,51460L,51461L,51462L,51463L,51464L,
94942 51465L,51466L,51467L,51468L,51469L,51470L,51471L,51472L,51473L,51474L,
94943 51475L,51476L,51477L,51478L,51479L,51480L,51481L,51482L,51483L,51484L,
94944 51485L,51486L,51487L,51488L,51489L,51490L,51491L,51492L,51493L,51494L,
94945 51495L,51496L,51497L,51498L,51499L,51500L,51501L,51502L,51503L,51504L,
94946 51505L,51506L,51507L,51508L,51509L,51510L,51511L,51512L,51513L,51514L,
94947 51515L,51516L,51517L,51518L,51519L,51520L,51521L,51522L,51523L,51524L,
94948 51525L,51526L,51527L,51528L,51529L,51530L,51531L,51532L,51533L,51534L,
94949 51535L,51536L,51537L,51538L,51539L,51540L,51541L,51542L,51543L,51544L,
94950 51545L,51546L,51547L,51548L,51549L,51550L,51551L,51552L,51553L,51554L,
94951 51555L,51556L,51557L,51558L,51559L,51560L,51561L,51562L,51563L,51564L,
94952 51565L,51566L,51567L,51568L,51569L,51570L,51571L,51572L,51573L,51574L,
94953 51575L,51576L,51577L,51578L,51579L,51580L,51581L,51582L,51583L,51584L,
94954 51585L,51586L,51587L,51588L,51589L,51590L,51591L,51592L,51593L,51594L,
94955 51595L,51596L,51597L,51598L,51599L,51600L,51601L,51602L,51603L,51604L,
94956 51605L,51606L,51607L,51608L,51609L,51610L,51611L,51612L,51613L,51614L,
94957 51615L,51616L,51617L,51618L,51619L,51620L,51621L,51622L,51623L,51624L,
94958 51625L,51626L,51627L,51628L,51629L,51630L,51631L,51632L,51633L,51634L,
94959 51635L,51636L,51637L,51638L,51639L,51640L,51641L,51642L,51643L,51644L,
94960 51645L,51646L,51647L,51648L,51649L,51650L,51651L,51652L,51653L,51654L,
94961 51655L,51656L,51657L,51658L,51659L,51660L,51661L,51662L,51663L,51664L,
94962 51665L,51666L,51667L,51668L,51669L,51670L,51671L,51672L,51673L,51674L,
94963 51675L,51676L,51677L,51678L,51679L,51680L,51681L,51682L,51683L,51684L,
94964 51685L,51686L,51687L,51688L,51689L,51690L,51691L,51692L,51693L,51694L,
94965 51695L,51696L,51697L,51698L,51699L,51700L,51701L,51702L,51703L,51704L,
94966 51705L,51706L,51707L,51708L,51709L,51710L,51711L,51712L,51713L,51714L,
94967 51715L,51716L,51717L,51718L,51719L,51720L,51721L,51722L,51723L,51724L,
94968 51725L,51726L,51727L,51728L,51729L,51730L,51731L,51732L,51733L,51734L,
94969 51735L,51736L,51737L,51738L,51739L,51740L,51741L,51742L,51743L,51744L,
94970 51745L,51746L,51747L,51748L,51749L,51750L,51751L,51752L,51753L,51754L,
94971 51755L,51756L,51757L,51758L,51759L,51760L,51761L,51762L,51763L,51764L,
94972 51765L,51766L,51767L,51768L,51769L,51770L,51771L,51772L,51773L,51774L,
94973 51775L,51776L,51777L,51778L,51779L,51780L,51781L,51782L,51783L,51784L,
94974 51785L,51786L,51787L,51788L,51789L,51790L,51791L,51792L,51793L,51794L,
94975 51795L,51796L,51797L,51798L,51799L,51800L,51801L,51802L,51803L,51804L,
94976 51805L,51806L,51807L,51808L,51809L,51810L,51811L,51812L,51813L,51814L,
94977 51815L,51816L,51817L,51818L,51819L,51820L,51821L,51822L,51823L,51824L,
94978 51825L,51826L,51827L,51828L,51829L,51830L,51831L,51832L,51833L,51834L,
94979 51835L,51836L,51837L,51838L,51839L,51840L,51841L,51842L,51843L,51844L,
94980 51845L,51846L,51847L,51848L,51849L,51850L,51851L,51852L,51853L,51854L,
94981 51855L,51856L,51857L,51858L,51859L,51860L,51861L,51862L,51863L,51864L,
94982 51865L,51866L,51867L,51868L,51869L,51870L,51871L,51872L,51873L,51874L,
94983 51875L,51876L,51877L,51878L,51879L,51880L,51881L,51882L,51883L,51884L,
94984 51885L,51886L,51887L,51888L,51889L,51890L,51891L,51892L,51893L,51894L,
94985 51895L,51896L,51897L,51898L,51899L,51900L,51901L,51902L,51903L,51904L,
94986 51905L,51906L,51907L,51908L,51909L,51910L,51911L,51912L,51913L,51914L,
94987 51915L,51916L,51917L,51918L,51919L,51920L,51921L,51922L,51923L,51924L,
94988 51925L,51926L,51927L,51928L,51929L,51930L,51931L,51932L,51933L,51934L,
94989 51935L,51936L,51937L,51938L,51939L,51940L,51941L,51942L,51943L,51944L,
94990 51945L,51946L,51947L,51948L,51949L,51950L,51951L,51952L,51953L,51954L,
94991 51955L,51956L,51957L,51958L,51959L,51960L,51961L,51962L,51963L,51964L,
94992 51965L,51966L,51967L,51968L,51969L,51970L,51971L,51972L,51973L,51974L,
94993 51975L,51976L,51977L,51978L,51979L,51980L,51981L,51982L,51983L,51984L,
94994 51985L,51986L,51987L,51988L,51989L,51990L,51991L,51992L,51993L,51994L,
94995 51995L,51996L,51997L,51998L,51999L,52000L,52001L,52002L,52003L,52004L,
94996 52005L,52006L,52007L,52008L,52009L,52010L,52011L,52012L,52013L,52014L,
94997 52015L,52016L,52017L,52018L,52019L,52020L,52021L,52022L,52023L,52024L,
94998 52025L,52026L,52027L,52028L,52029L,52030L,52031L,52032L,52033L,52034L,
94999 52035L,52036L,52037L,52038L,52039L,52040L,52041L,52042L,52043L,52044L,
95000 52045L,52046L,52047L,52048L,52049L,52050L,52051L,52052L,52053L,52054L,
95001 52055L,52056L,52057L,52058L,52059L,52060L,52061L,52062L,52063L,52064L,
95002 52065L,52066L,52067L,52068L,52069L,52070L,52071L,52072L,52073L,52074L,
95003 52075L,52076L,52077L,52078L,52079L,52080L,52081L,52082L,52083L,52084L,
95004 52085L,52086L,52087L,52088L,52089L,52090L,52091L,52092L,52093L,52094L,
95005 52095L,52096L,52097L,52098L,52099L,52100L,52101L,52102L,52103L,52104L,
95006 52105L,52106L,52107L,52108L,52109L,52110L,52111L,52112L,52113L,52114L,
95007 52115L,52116L,52117L,52118L,52119L,52120L,52121L,52122L,52123L,52124L,
95008 52125L,52126L,52127L,52128L,52129L,52130L,52131L,52132L,52133L,52134L,
95009 52135L,52136L,52137L,52138L,52139L,52140L,52141L,52142L,52143L,52144L,
95010 52145L,52146L,52147L,52148L,52149L,52150L,52151L,52152L,52153L,52154L,
95011 52155L,52156L,52157L,52158L,52159L,52160L,52161L,52162L,52163L,52164L,
95012 52165L,52166L,52167L,52168L,52169L,52170L,52171L,52172L,52173L,52174L,
95013 52175L,52176L,52177L,52178L,52179L,52180L,52181L,52182L,52183L,52184L,
95014 52185L,52186L,52187L,52188L,52189L,52190L,52191L,52192L,52193L,52194L,
95015 52195L,52196L,52197L,52198L,52199L,52200L,52201L,52202L,52203L,52204L,
95016 52205L,52206L,52207L,52208L,52209L,52210L,52211L,52212L,52213L,52214L,
95017 52215L,52216L,52217L,52218L,52219L,52220L,52221L,52222L,52223L,52224L,
95018 52225L,52226L,52227L,52228L,52229L,52230L,52231L,52232L,52233L,52234L,
95019 52235L,52236L,52237L,52238L,52239L,52240L,52241L,52242L,52243L,52244L,
95020 52245L,52246L,52247L,52248L,52249L,52250L,52251L,52252L,52253L,52254L,
95021 52255L,52256L,52257L,52258L,52259L,52260L,52261L,52262L,52263L,52264L,
95022 52265L,52266L,52267L,52268L,52269L,52270L,52271L,52272L,52273L,52274L,
95023 52275L,52276L,52277L,52278L,52279L,52280L,52281L,52282L,52283L,52284L,
95024 52285L,52286L,52287L,52288L,52289L,52290L,52291L,52292L,52293L,52294L,
95025 52295L,52296L,52297L,52298L,52299L,52300L,52301L,52302L,52303L,52304L,
95026 52305L,52306L,52307L,52308L,52309L,52310L,52311L,52312L,52313L,52314L,
95027 52315L,52316L,52317L,52318L,52319L,52320L,52321L,52322L,52323L,52324L,
95028 52325L,52326L,52327L,52328L,52329L,52330L,52331L,52332L,52333L,52334L,
95029 52335L,52336L,52337L,52338L,52339L,52340L,52341L,52342L,52343L,52344L,
95030 52345L,52346L,52347L,52348L,52349L,52350L,52351L,52352L,52353L,52354L,
95031 52355L,52356L,52357L,52358L,52359L,52360L,52361L,52362L,52363L,52364L,
95032 52365L,52366L,52367L,52368L,52369L,52370L,52371L,52372L,52373L,52374L,
95033 52375L,52376L,52377L,52378L,52379L,52380L,52381L,52382L,52383L,52384L,
95034 52385L,52386L,52387L,52388L,52389L,52390L,52391L,52392L,52393L,52394L,
95035 52395L,52396L,52397L,52398L,52399L,52400L,52401L,52402L,52403L,52404L,
95036 52405L,52406L,52407L,52408L,52409L,52410L,52411L,52412L,52413L,52414L,
95037 52415L,52416L,52417L,52418L,52419L,52420L,52421L,52422L,52423L,52424L,
95038 52425L,52426L,52427L,52428L,52429L,52430L,52431L,52432L,52433L,52434L,
95039 52435L,52436L,52437L,52438L,52439L,52440L,52441L,52442L,52443L,52444L,
95040 52445L,52446L,52447L,52448L,52449L,52450L,52451L,52452L,52453L,52454L,
95041 52455L,52456L,52457L,52458L,52459L,52460L,52461L,52462L,52463L,52464L,
95042 52465L,52466L,52467L,52468L,52469L,52470L,52471L,52472L,52473L,52474L,
95043 52475L,52476L,52477L,52478L,52479L,52480L,52481L,52482L,52483L,52484L,
95044 52485L,52486L,52487L,52488L,52489L,52490L,52491L,52492L,52493L,52494L,
95045 52495L,52496L,52497L,52498L,52499L,52500L,52501L,52502L,52503L,52504L,
95046 52505L,52506L,52507L,52508L,52509L,52510L,52511L,52512L,52513L,52514L,
95047 52515L,52516L,52517L,52518L,52519L,52520L,52521L,52522L,52523L,52524L,
95048 52525L,52526L,52527L,52528L,52529L,52530L,52531L,52532L,52533L,52534L,
95049 52535L,52536L,52537L,52538L,52539L,52540L,52541L,52542L,52543L,52544L,
95050 52545L,52546L,52547L,52548L,52549L,52550L,52551L,52552L,52553L,52554L,
95051 52555L,52556L,52557L,52558L,52559L,52560L,52561L,52562L,52563L,52564L,
95052 52565L,52566L,52567L,52568L,52569L,52570L,52571L,52572L,52573L,52574L,
95053 52575L,52576L,52577L,52578L,52579L,52580L,52581L,52582L,52583L,52584L,
95054 52585L,52586L,52587L,52588L,52589L,52590L,52591L,52592L,52593L,52594L,
95055 52595L,52596L,52597L,52598L,52599L,52600L,52601L,52602L,52603L,52604L,
95056 52605L,52606L,52607L,52608L,52609L,52610L,52611L,52612L,52613L,52614L,
95057 52615L,52616L,52617L,52618L,52619L,52620L,52621L,52622L,52623L,52624L,
95058 52625L,52626L,52627L,52628L,52629L,52630L,52631L,52632L,52633L,52634L,
95059 52635L,52636L,52637L,52638L,52639L,52640L,52641L,52642L,52643L,52644L,
95060 52645L,52646L,52647L,52648L,52649L,52650L,52651L,52652L,52653L,52654L,
95061 52655L,52656L,52657L,52658L,52659L,52660L,52661L,52662L,52663L,52664L,
95062 52665L,52666L,52667L,52668L,52669L,52670L,52671L,52672L,52673L,52674L,
95063 52675L,52676L,52677L,52678L,52679L,52680L,52681L,52682L,52683L,52684L,
95064 52685L,52686L,52687L,52688L,52689L,52690L,52691L,52692L,52693L,52694L,
95065 52695L,52696L,52697L,52698L,52699L,52700L,52701L,52702L,52703L,52704L,
95066 52705L,52706L,52707L,52708L,52709L,52710L,52711L,52712L,52713L,52714L,
95067 52715L,52716L,52717L,52718L,52719L,52720L,52721L,52722L,52723L,52724L,
95068 52725L,52726L,52727L,52728L,52729L,52730L,52731L,52732L,52733L,52734L,
95069 52735L,52736L,52737L,52738L,52739L,52740L,52741L,52742L,52743L,52744L,
95070 52745L,52746L,52747L,52748L,52749L,52750L,52751L,52752L,52753L,52754L,
95071 52755L,52756L,52757L,52758L,52759L,52760L,52761L,52762L,52763L,52764L,
95072 52765L,52766L,52767L,52768L,52769L,52770L,52771L,52772L,52773L,52774L,
95073 52775L,52776L,52777L,52778L,52779L,52780L,52781L,52782L,52783L,52784L,
95074 52785L,52786L,52787L,52788L,52789L,52790L,52791L,52792L,52793L,52794L,
95075 52795L,52796L,52797L,52798L,52799L,52800L,52801L,52802L,52803L,52804L,
95076 52805L,52806L,52807L,52808L,52809L,52810L,52811L,52812L,52813L,52814L,
95077 52815L,52816L,52817L,52818L,52819L,52820L,52821L,52822L,52823L,52824L,
95078 52825L,52826L,52827L,52828L,52829L,52830L,52831L,52832L,52833L,52834L,
95079 52835L,52836L,52837L,52838L,52839L,52840L,52841L,52842L,52843L,52844L,
95080 52845L,52846L,52847L,52848L,52849L,52850L,52851L,52852L,52853L,52854L,
95081 52855L,52856L,52857L,52858L,52859L,52860L,52861L,52862L,52863L,52864L,
95082 52865L,52866L,52867L,52868L,52869L,52870L,52871L,52872L,52873L,52874L,
95083 52875L,52876L,52877L,52878L,52879L,52880L,52881L,52882L,52883L,52884L,
95084 52885L,52886L,52887L,52888L,52889L,52890L,52891L,52892L,52893L,52894L,
95085 52895L,52896L,52897L,52898L,52899L,52900L,52901L,52902L,52903L,52904L,
95086 52905L,52906L,52907L,52908L,52909L,52910L,52911L,52912L,52913L,52914L,
95087 52915L,52916L,52917L,52918L,52919L,52920L,52921L,52922L,52923L,52924L,
95088 52925L,52926L,52927L,52928L,52929L,52930L,52931L,52932L,52933L,52934L,
95089 52935L,52936L,52937L,52938L,52939L,52940L,52941L,52942L,52943L,52944L,
95090 52945L,52946L,52947L,52948L,52949L,52950L,52951L,52952L,52953L,52954L,
95091 52955L,52956L,52957L,52958L,52959L,52960L,52961L,52962L,52963L,52964L,
95092 52965L,52966L,52967L,52968L,52969L,52970L,52971L,52972L,52973L,52974L,
95093 52975L,52976L,52977L,52978L,52979L,52980L,52981L,52982L,52983L,52984L,
95094 52985L,52986L,52987L,52988L,52989L,52990L,52991L,52992L,52993L,52994L,
95095 52995L,52996L,52997L,52998L,52999L,53000L,53001L,53002L,53003L,53004L,
95096 53005L,53006L,53007L,53008L,53009L,53010L,53011L,53012L,53013L,53014L,
95097 53015L,53016L,53017L,53018L,53019L,53020L,53021L,53022L,53023L,53024L,
95098 53025L,53026L,53027L,53028L,53029L,53030L,53031L,53032L,53033L,53034L,
95099 53035L,53036L,53037L,53038L,53039L,53040L,53041L,53042L,53043L,53044L,
95100 53045L,53046L,53047L,53048L,53049L,53050L,53051L,53052L,53053L,53054L,
95101 53055L,53056L,53057L,53058L,53059L,53060L,53061L,53062L,53063L,53064L,
95102 53065L,53066L,53067L,53068L,53069L,53070L,53071L,53072L,53073L,53074L,
95103 53075L,53076L,53077L,53078L,53079L,53080L,53081L,53082L,53083L,53084L,
95104 53085L,53086L,53087L,53088L,53089L,53090L,53091L,53092L,53093L,53094L,
95105 53095L,53096L,53097L,53098L,53099L,53100L,53101L,53102L,53103L,53104L,
95106 53105L,53106L,53107L,53108L,53109L,53110L,53111L,53112L,53113L,53114L,
95107 53115L,53116L,53117L,53118L,53119L,53120L,53121L,53122L,53123L,53124L,
95108 53125L,53126L,53127L,53128L,53129L,53130L,53131L,53132L,53133L,53134L,
95109 53135L,53136L,53137L,53138L,53139L,53140L,53141L,53142L,53143L,53144L,
95110 53145L,53146L,53147L,53148L,53149L,53150L,53151L,53152L,53153L,53154L,
95111 53155L,53156L,53157L,53158L,53159L,53160L,53161L,53162L,53163L,53164L,
95112 53165L,53166L,53167L,53168L,53169L,53170L,53171L,53172L,53173L,53174L,
95113 53175L,53176L,53177L,53178L,53179L,53180L,53181L,53182L,53183L,53184L,
95114 53185L,53186L,53187L,53188L,53189L,53190L,53191L,53192L,53193L,53194L,
95115 53195L,53196L,53197L,53198L,53199L,53200L,53201L,53202L,53203L,53204L,
95116 53205L,53206L,53207L,53208L,53209L,53210L,53211L,53212L,53213L,53214L,
95117 53215L,53216L,53217L,53218L,53219L,53220L,53221L,53222L,53223L,53224L,
95118 53225L,53226L,53227L,53228L,53229L,53230L,53231L,53232L,53233L,53234L,
95119 53235L,53236L,53237L,53238L,53239L,53240L,53241L,53242L,53243L,53244L,
95120 53245L,53246L,53247L,53248L,53249L,53250L,53251L,53252L,53253L,53254L,
95121 53255L,53256L,53257L,53258L,53259L,53260L,53261L,53262L,53263L,53264L,
95122 53265L,53266L,53267L,53268L,53269L,53270L,53271L,53272L,53273L,53274L,
95123 53275L,53276L,53277L,53278L,53279L,53280L,53281L,53282L,53283L,53284L,
95124 53285L,53286L,53287L,53288L,53289L,53290L,53291L,53292L,53293L,53294L,
95125 53295L,53296L,53297L,53298L,53299L,53300L,53301L,53302L,53303L,53304L,
95126 53305L,53306L,53307L,53308L,53309L,53310L,53311L,53312L,53313L,53314L,
95127 53315L,53316L,53317L,53318L,53319L,53320L,53321L,53322L,53323L,53324L,
95128 53325L,53326L,53327L,53328L,53329L,53330L,53331L,53332L,53333L,53334L,
95129 53335L,53336L,53337L,53338L,53339L,53340L,53341L,53342L,53343L,53344L,
95130 53345L,53346L,53347L,53348L,53349L,53350L,53351L,53352L,53353L,53354L,
95131 53355L,53356L,53357L,53358L,53359L,53360L,53361L,53362L,53363L,53364L,
95132 53365L,53366L,53367L,53368L,53369L,53370L,53371L,53372L,53373L,53374L,
95133 53375L,53376L,53377L,53378L,53379L,53380L,53381L,53382L,53383L,53384L,
95134 53385L,53386L,53387L,53388L,53389L,53390L,53391L,53392L,53393L,53394L,
95135 53395L,53396L,53397L,53398L,53399L,53400L,53401L,53402L,53403L,53404L,
95136 53405L,53406L,53407L,53408L,53409L,53410L,53411L,53412L,53413L,53414L,
95137 53415L,53416L,53417L,53418L,53419L,53420L,53421L,53422L,53423L,53424L,
95138 53425L,53426L,53427L,53428L,53429L,53430L,53431L,53432L,53433L,53434L,
95139 53435L,53436L,53437L,53438L,53439L,53440L,53441L,53442L,53443L,53444L,
95140 53445L,53446L,53447L,53448L,53449L,53450L,53451L,53452L,53453L,53454L,
95141 53455L,53456L,53457L,53458L,53459L,53460L,53461L,53462L,53463L,53464L,
95142 53465L,53466L,53467L,53468L,53469L,53470L,53471L,53472L,53473L,53474L,
95143 53475L,53476L,53477L,53478L,53479L,53480L,53481L,53482L,53483L,53484L,
95144 53485L,53486L,53487L,53488L,53489L,53490L,53491L,53492L,53493L,53494L,
95145 53495L,53496L,53497L,53498L,53499L,53500L,53501L,53502L,53503L,53504L,
95146 53505L,53506L,53507L,53508L,53509L,53510L,53511L,53512L,53513L,53514L,
95147 53515L,53516L,53517L,53518L,53519L,53520L,53521L,53522L,53523L,53524L,
95148 53525L,53526L,53527L,53528L,53529L,53530L,53531L,53532L,53533L,53534L,
95149 53535L,53536L,53537L,53538L,53539L,53540L,53541L,53542L,53543L,53544L,
95150 53545L,53546L,53547L,53548L,53549L,53550L,53551L,53552L,53553L,53554L,
95151 53555L,53556L,53557L,53558L,53559L,53560L,53561L,53562L,53563L,53564L,
95152 53565L,53566L,53567L,53568L,53569L,53570L,53571L,53572L,53573L,53574L,
95153 53575L,53576L,53577L,53578L,53579L,53580L,53581L,53582L,53583L,53584L,
95154 53585L,53586L,53587L,53588L,53589L,53590L,53591L,53592L,53593L,53594L,
95155 53595L,53596L,53597L,53598L,53599L,53600L,53601L,53602L,53603L,53604L,
95156 53605L,53606L,53607L,53608L,53609L,53610L,53611L,53612L,53613L,53614L,
95157 53615L,53616L,53617L,53618L,53619L,53620L,53621L,53622L,53623L,53624L,
95158 53625L,53626L,53627L,53628L,53629L,53630L,53631L,53632L,53633L,53634L,
95159 53635L,53636L,53637L,53638L,53639L,53640L,53641L,53642L,53643L,53644L,
95160 53645L,53646L,53647L,53648L,53649L,53650L,53651L,53652L,53653L,53654L,
95161 53655L,53656L,53657L,53658L,53659L,53660L,53661L,53662L,53663L,53664L,
95162 53665L,53666L,53667L,53668L,53669L,53670L,53671L,53672L,53673L,53674L,
95163 53675L,53676L,53677L,53678L,53679L,53680L,53681L,53682L,53683L,53684L,
95164 53685L,53686L,53687L,53688L,53689L,53690L,53691L,53692L,53693L,53694L,
95165 53695L,53696L,53697L,53698L,53699L,53700L,53701L,53702L,53703L,53704L,
95166 53705L,53706L,53707L,53708L,53709L,53710L,53711L,53712L,53713L,53714L,
95167 53715L,53716L,53717L,53718L,53719L,53720L,53721L,53722L,53723L,53724L,
95168 53725L,53726L,53727L,53728L,53729L,53730L,53731L,53732L,53733L,53734L,
95169 53735L,53736L,53737L,53738L,53739L,53740L,53741L,53742L,53743L,53744L,
95170 53745L,53746L,53747L,53748L,53749L,53750L,53751L,53752L,53753L,53754L,
95171 53755L,53756L,53757L,53758L,53759L,53760L,53761L,53762L,53763L,53764L,
95172 53765L,53766L,53767L,53768L,53769L,53770L,53771L,53772L,53773L,53774L,
95173 53775L,53776L,53777L,53778L,53779L,53780L,53781L,53782L,53783L,53784L,
95174 53785L,53786L,53787L,53788L,53789L,53790L,53791L,53792L,53793L,53794L,
95175 53795L,53796L,53797L,53798L,53799L,53800L,53801L,53802L,53803L,53804L,
95176 53805L,53806L,53807L,53808L,53809L,53810L,53811L,53812L,53813L,53814L,
95177 53815L,53816L,53817L,53818L,53819L,53820L,53821L,53822L,53823L,53824L,
95178 53825L,53826L,53827L,53828L,53829L,53830L,53831L,53832L,53833L,53834L,
95179 53835L,53836L,53837L,53838L,53839L,53840L,53841L,53842L,53843L,53844L,
95180 53845L,53846L,53847L,53848L,53849L,53850L,53851L,53852L,53853L,53854L,
95181 53855L,53856L,53857L,53858L,53859L,53860L,53861L,53862L,53863L,53864L,
95182 53865L,53866L,53867L,53868L,53869L,53870L,53871L,53872L,53873L,53874L,
95183 53875L,53876L,53877L,53878L,53879L,53880L,53881L,53882L,53883L,53884L,
95184 53885L,53886L,53887L,53888L,53889L,53890L,53891L,53892L,53893L,53894L,
95185 53895L,53896L,53897L,53898L,53899L,53900L,53901L,53902L,53903L,53904L,
95186 53905L,53906L,53907L,53908L,53909L,53910L,53911L,53912L,53913L,53914L,
95187 53915L,53916L,53917L,53918L,53919L,53920L,53921L,53922L,53923L,53924L,
95188 53925L,53926L,53927L,53928L,53929L,53930L,53931L,53932L,53933L,53934L,
95189 53935L,53936L,53937L,53938L,53939L,53940L,53941L,53942L,53943L,53944L,
95190 53945L,53946L,53947L,53948L,53949L,53950L,53951L,53952L,53953L,53954L,
95191 53955L,53956L,53957L,53958L,53959L,53960L,53961L,53962L,53963L,53964L,
95192 53965L,53966L,53967L,53968L,53969L,53970L,53971L,53972L,53973L,53974L,
95193 53975L,53976L,53977L,53978L,53979L,53980L,53981L,53982L,53983L,53984L,
95194 53985L,53986L,53987L,53988L,53989L,53990L,53991L,53992L,53993L,53994L,
95195 53995L,53996L,53997L,53998L,53999L,54000L,54001L,54002L,54003L,54004L,
95196 54005L,54006L,54007L,54008L,54009L,54010L,54011L,54012L,54013L,54014L,
95197 54015L,54016L,54017L,54018L,54019L,54020L,54021L,54022L,54023L,54024L,
95198 54025L,54026L,54027L,54028L,54029L,54030L,54031L,54032L,54033L,54034L,
95199 54035L,54036L,54037L,54038L,54039L,54040L,54041L,54042L,54043L,54044L,
95200 54045L,54046L,54047L,54048L,54049L,54050L,54051L,54052L,54053L,54054L,
95201 54055L,54056L,54057L,54058L,54059L,54060L,54061L,54062L,54063L,54064L,
95202 54065L,54066L,54067L,54068L,54069L,54070L,54071L,54072L,54073L,54074L,
95203 54075L,54076L,54077L,54078L,54079L,54080L,54081L,54082L,54083L,54084L,
95204 54085L,54086L,54087L,54088L,54089L,54090L,54091L,54092L,54093L,54094L,
95205 54095L,54096L,54097L,54098L,54099L,54100L,54101L,54102L,54103L,54104L,
95206 54105L,54106L,54107L,54108L,54109L,54110L,54111L,54112L,54113L,54114L,
95207 54115L,54116L,54117L,54118L,54119L,54120L,54121L,54122L,54123L,54124L,
95208 54125L,54126L,54127L,54128L,54129L,54130L,54131L,54132L,54133L,54134L,
95209 54135L,54136L,54137L,54138L,54139L,54140L,54141L,54142L,54143L,54144L,
95210 54145L,54146L,54147L,54148L,54149L,54150L,54151L,54152L,54153L,54154L,
95211 54155L,54156L,54157L,54158L,54159L,54160L,54161L,54162L,54163L,54164L,
95212 54165L,54166L,54167L,54168L,54169L,54170L,54171L,54172L,54173L,54174L,
95213 54175L,54176L,54177L,54178L,54179L,54180L,54181L,54182L,54183L,54184L,
95214 54185L,54186L,54187L,54188L,54189L,54190L,54191L,54192L,54193L,54194L,
95215 54195L,54196L,54197L,54198L,54199L,54200L,54201L,54202L,54203L,54204L,
95216 54205L,54206L,54207L,54208L,54209L,54210L,54211L,54212L,54213L,54214L,
95217 54215L,54216L,54217L,54218L,54219L,54220L,54221L,54222L,54223L,54224L,
95218 54225L,54226L,54227L,54228L,54229L,54230L,54231L,54232L,54233L,54234L,
95219 54235L,54236L,54237L,54238L,54239L,54240L,54241L,54242L,54243L,54244L,
95220 54245L,54246L,54247L,54248L,54249L,54250L,54251L,54252L,54253L,54254L,
95221 54255L,54256L,54257L,54258L,54259L,54260L,54261L,54262L,54263L,54264L,
95222 54265L,54266L,54267L,54268L,54269L,54270L,54271L,54272L,54273L,54274L,
95223 54275L,54276L,54277L,54278L,54279L,54280L,54281L,54282L,54283L,54284L,
95224 54285L,54286L,54287L,54288L,54289L,54290L,54291L,54292L,54293L,54294L,
95225 54295L,54296L,54297L,54298L,54299L,54300L,54301L,54302L,54303L,54304L,
95226 54305L,54306L,54307L,54308L,54309L,54310L,54311L,54312L,54313L,54314L,
95227 54315L,54316L,54317L,54318L,54319L,54320L,54321L,54322L,54323L,54324L,
95228 54325L,54326L,54327L,54328L,54329L,54330L,54331L,54332L,54333L,54334L,
95229 54335L,54336L,54337L,54338L,54339L,54340L,54341L,54342L,54343L,54344L,
95230 54345L,54346L,54347L,54348L,54349L,54350L,54351L,54352L,54353L,54354L,
95231 54355L,54356L,54357L,54358L,54359L,54360L,54361L,54362L,54363L,54364L,
95232 54365L,54366L,54367L,54368L,54369L,54370L,54371L,54372L,54373L,54374L,
95233 54375L,54376L,54377L,54378L,54379L,54380L,54381L,54382L,54383L,54384L,
95234 54385L,54386L,54387L,54388L,54389L,54390L,54391L,54392L,54393L,54394L,
95235 54395L,54396L,54397L,54398L,54399L,54400L,54401L,54402L,54403L,54404L,
95236 54405L,54406L,54407L,54408L,54409L,54410L,54411L,54412L,54413L,54414L,
95237 54415L,54416L,54417L,54418L,54419L,54420L,54421L,54422L,54423L,54424L,
95238 54425L,54426L,54427L,54428L,54429L,54430L,54431L,54432L,54433L,54434L,
95239 54435L,54436L,54437L,54438L,54439L,54440L,54441L,54442L,54443L,54444L,
95240 54445L,54446L,54447L,54448L,54449L,54450L,54451L,54452L,54453L,54454L,
95241 54455L,54456L,54457L,54458L,54459L,54460L,54461L,54462L,54463L,54464L,
95242 54465L,54466L,54467L,54468L,54469L,54470L,54471L,54472L,54473L,54474L,
95243 54475L,54476L,54477L,54478L,54479L,54480L,54481L,54482L,54483L,54484L,
95244 54485L,54486L,54487L,54488L,54489L,54490L,54491L,54492L,54493L,54494L,
95245 54495L,54496L,54497L,54498L,54499L,54500L,54501L,54502L,54503L,54504L,
95246 54505L,54506L,54507L,54508L,54509L,54510L,54511L,54512L,54513L,54514L,
95247 54515L,54516L,54517L,54518L,54519L,54520L,54521L,54522L,54523L,54524L,
95248 54525L,54526L,54527L,54528L,54529L,54530L,54531L,54532L,54533L,54534L,
95249 54535L,54536L,54537L,54538L,54539L,54540L,54541L,54542L,54543L,54544L,
95250 54545L,54546L,54547L,54548L,54549L,54550L,54551L,54552L,54553L,54554L,
95251 54555L,54556L,54557L,54558L,54559L,54560L,54561L,54562L,54563L,54564L,
95252 54565L,54566L,54567L,54568L,54569L,54570L,54571L,54572L,54573L,54574L,
95253 54575L,54576L,54577L,54578L,54579L,54580L,54581L,54582L,54583L,54584L,
95254 54585L,54586L,54587L,54588L,54589L,54590L,54591L,54592L,54593L,54594L,
95255 54595L,54596L,54597L,54598L,54599L,54600L,54601L,54602L,54603L,54604L,
95256 54605L,54606L,54607L,54608L,54609L,54610L,54611L,54612L,54613L,54614L,
95257 54615L,54616L,54617L,54618L,54619L,54620L,54621L,54622L,54623L,54624L,
95258 54625L,54626L,54627L,54628L,54629L,54630L,54631L,54632L,54633L,54634L,
95259 54635L,54636L,54637L,54638L,54639L,54640L,54641L,54642L,54643L,54644L,
95260 54645L,54646L,54647L,54648L,54649L,54650L,54651L,54652L,54653L,54654L,
95261 54655L,54656L,54657L,54658L,54659L,54660L,54661L,54662L,54663L,54664L,
95262 54665L,54666L,54667L,54668L,54669L,54670L,54671L,54672L,54673L,54674L,
95263 54675L,54676L,54677L,54678L,54679L,54680L,54681L,54682L,54683L,54684L,
95264 54685L,54686L,54687L,54688L,54689L,54690L,54691L,54692L,54693L,54694L,
95265 54695L,54696L,54697L,54698L,54699L,54700L,54701L,54702L,54703L,54704L,
95266 54705L,54706L,54707L,54708L,54709L,54710L,54711L,54712L,54713L,54714L,
95267 54715L,54716L,54717L,54718L,54719L,54720L,54721L,54722L,54723L,54724L,
95268 54725L,54726L,54727L,54728L,54729L,54730L,54731L,54732L,54733L,54734L,
95269 54735L,54736L,54737L,54738L,54739L,54740L,54741L,54742L,54743L,54744L,
95270 54745L,54746L,54747L,54748L,54749L,54750L,54751L,54752L,54753L,54754L,
95271 54755L,54756L,54757L,54758L,54759L,54760L,54761L,54762L,54763L,54764L,
95272 54765L,54766L,54767L,54768L,54769L,54770L,54771L,54772L,54773L,54774L,
95273 54775L,54776L,54777L,54778L,54779L,54780L,54781L,54782L,54783L,54784L,
95274 54785L,54786L,54787L,54788L,54789L,54790L,54791L,54792L,54793L,54794L,
95275 54795L,54796L,54797L,54798L,54799L,54800L,54801L,54802L,54803L,54804L,
95276 54805L,54806L,54807L,54808L,54809L,54810L,54811L,54812L,54813L,54814L,
95277 54815L,54816L,54817L,54818L,54819L,54820L,54821L,54822L,54823L,54824L,
95278 54825L,54826L,54827L,54828L,54829L,54830L,54831L,54832L,54833L,54834L,
95279 54835L,54836L,54837L,54838L,54839L,54840L,54841L,54842L,54843L,54844L,
95280 54845L,54846L,54847L,54848L,54849L,54850L,54851L,54852L,54853L,54854L,
95281 54855L,54856L,54857L,54858L,54859L,54860L,54861L,54862L,54863L,54864L,
95282 54865L,54866L,54867L,54868L,54869L,54870L,54871L,54872L,54873L,54874L,
95283 54875L,54876L,54877L,54878L,54879L,54880L,54881L,54882L,54883L,54884L,
95284 54885L,54886L,54887L,54888L,54889L,54890L,54891L,54892L,54893L,54894L,
95285 54895L,54896L,54897L,54898L,54899L,54900L,54901L,54902L,54903L,54904L,
95286 54905L,54906L,54907L,54908L,54909L,54910L,54911L,54912L,54913L,54914L,
95287 54915L,54916L,54917L,54918L,54919L,54920L,54921L,54922L,54923L,54924L,
95288 54925L,54926L,54927L,54928L,54929L,54930L,54931L,54932L,54933L,54934L,
95289 54935L,54936L,54937L,54938L,54939L,54940L,54941L,54942L,54943L,54944L,
95290 54945L,54946L,54947L,54948L,54949L,54950L,54951L,54952L,54953L,54954L,
95291 54955L,54956L,54957L,54958L,54959L,54960L,54961L,54962L,54963L,54964L,
95292 54965L,54966L,54967L,54968L,54969L,54970L,54971L,54972L,54973L,54974L,
95293 54975L,54976L,54977L,54978L,54979L,54980L,54981L,54982L,54983L,54984L,
95294 54985L,54986L,54987L,54988L,54989L,54990L,54991L,54992L,54993L,54994L,
95295 54995L,54996L,54997L,54998L,54999L,55000L,55001L,55002L,55003L,55004L,
95296 55005L,55006L,55007L,55008L,55009L,55010L,55011L,55012L,55013L,55014L,
95297 55015L,55016L,55017L,55018L,55019L,55020L,55021L,55022L,55023L,55024L,
95298 55025L,55026L,55027L,55028L,55029L,55030L,55031L,55032L,55033L,55034L,
95299 55035L,55036L,55037L,55038L,55039L,55040L,55041L,55042L,55043L,55044L,
95300 55045L,55046L,55047L,55048L,55049L,55050L,55051L,55052L,55053L,55054L,
95301 55055L,55056L,55057L,55058L,55059L,55060L,55061L,55062L,55063L,55064L,
95302 55065L,55066L,55067L,55068L,55069L,55070L,55071L,55072L,55073L,55074L,
95303 55075L,55076L,55077L,55078L,55079L,55080L,55081L,55082L,55083L,55084L,
95304 55085L,55086L,55087L,55088L,55089L,55090L,55091L,55092L,55093L,55094L,
95305 55095L,55096L,55097L,55098L,55099L,55100L,55101L,55102L,55103L,55104L,
95306 55105L,55106L,55107L,55108L,55109L,55110L,55111L,55112L,55113L,55114L,
95307 55115L,55116L,55117L,55118L,55119L,55120L,55121L,55122L,55123L,55124L,
95308 55125L,55126L,55127L,55128L,55129L,55130L,55131L,55132L,55133L,55134L,
95309 55135L,55136L,55137L,55138L,55139L,55140L,55141L,55142L,55143L,55144L,
95310 55145L,55146L,55147L,55148L,55149L,55150L,55151L,55152L,55153L,55154L,
95311 55155L,55156L,55157L,55158L,55159L,55160L,55161L,55162L,55163L,55164L,
95312 55165L,55166L,55167L,55168L,55169L,55170L,55171L,55172L,55173L,55174L,
95313 55175L,55176L,55177L,55178L,55179L,55180L,55181L,55182L,55183L,55184L,
95314 55185L,55186L,55187L,55188L,55189L,55190L,55191L,55192L,55193L,55194L,
95315 55195L,55196L,55197L,55198L,55199L,55200L,55201L,55202L,55203L,55204L,
95316 55205L,55206L,55207L,55208L,55209L,55210L,55211L,55212L,55213L,55214L,
95317 55215L,55216L,55217L,55218L,55219L,55220L,55221L,55222L,55223L,55224L,
95318 55225L,55226L,55227L,55228L,55229L,55230L,55231L,55232L,55233L,55234L,
95319 55235L,55236L,55237L,55238L,55239L,55240L,55241L,55242L,55243L,55244L,
95320 55245L,55246L,55247L,55248L,55249L,55250L,55251L,55252L,55253L,55254L,
95321 55255L,55256L,55257L,55258L,55259L,55260L,55261L,55262L,55263L,55264L,
95322 55265L,55266L,55267L,55268L,55269L,55270L,55271L,55272L,55273L,55274L,
95323 55275L,55276L,55277L,55278L,55279L,55280L,55281L,55282L,55283L,55284L,
95324 55285L,55286L,55287L,55288L,55289L,55290L,55291L,55292L,55293L,55294L,
95325 55295L,55296L,55297L,55298L,55299L,55300L,55301L,55302L,55303L,55304L,
95326 55305L,55306L,55307L,55308L,55309L,55310L,55311L,55312L,55313L,55314L,
95327 55315L,55316L,55317L,55318L,55319L,55320L,55321L,55322L,55323L,55324L,
95328 55325L,55326L,55327L,55328L,55329L,55330L,55331L,55332L,55333L,55334L,
95329 55335L,55336L,55337L,55338L,55339L,55340L,55341L,55342L,55343L,55344L,
95330 55345L,55346L,55347L,55348L,55349L,55350L,55351L,55352L,55353L,55354L,
95331 55355L,55356L,55357L,55358L,55359L,55360L,55361L,55362L,55363L,55364L,
95332 55365L,55366L,55367L,55368L,55369L,55370L,55371L,55372L,55373L,55374L,
95333 55375L,55376L,55377L,55378L,55379L,55380L,55381L,55382L,55383L,55384L,
95334 55385L,55386L,55387L,55388L,55389L,55390L,55391L,55392L,55393L,55394L,
95335 55395L,55396L,55397L,55398L,55399L,55400L,55401L,55402L,55403L,55404L,
95336 55405L,55406L,55407L,55408L,55409L,55410L,55411L,55412L,55413L,55414L,
95337 55415L,55416L,55417L,55418L,55419L,55420L,55421L,55422L,55423L,55424L,
95338 55425L,55426L,55427L,55428L,55429L,55430L,55431L,55432L,55433L,55434L,
95339 55435L,55436L,55437L,55438L,55439L,55440L,55441L,55442L,55443L,55444L,
95340 55445L,55446L,55447L,55448L,55449L,55450L,55451L,55452L,55453L,55454L,
95341 55455L,55456L,55457L,55458L,55459L,55460L,55461L,55462L,55463L,55464L,
95342 55465L,55466L,55467L,55468L,55469L,55470L,55471L,55472L,55473L,55474L,
95343 55475L,55476L,55477L,55478L,55479L,55480L,55481L,55482L,55483L,55484L,
95344 55485L,55486L,55487L,55488L,55489L,55490L,55491L,55492L,55493L,55494L,
95345 55495L,55496L,55497L,55498L,55499L,55500L,55501L,55502L,55503L,55504L,
95346 55505L,55506L,55507L,55508L,55509L,55510L,55511L,55512L,55513L,55514L,
95347 55515L,55516L,55517L,55518L,55519L,55520L,55521L,55522L,55523L,55524L,
95348 55525L,55526L,55527L,55528L,55529L,55530L,55531L,55532L,55533L,55534L,
95349 55535L,55536L,55537L,55538L,55539L,55540L,55541L,55542L,55543L,55544L,
95350 55545L,55546L,55547L,55548L,55549L,55550L,55551L,55552L,55553L,55554L,
95351 55555L,55556L,55557L,55558L,55559L,55560L,55561L,55562L,55563L,55564L,
95352 55565L,55566L,55567L,55568L,55569L,55570L,55571L,55572L,55573L,55574L,
95353 55575L,55576L,55577L,55578L,55579L,55580L,55581L,55582L,55583L,55584L,
95354 55585L,55586L,55587L,55588L,55589L,55590L,55591L,55592L,55593L,55594L,
95355 55595L,55596L,55597L,55598L,55599L,55600L,55601L,55602L,55603L,55604L,
95356 55605L,55606L,55607L,55608L,55609L,55610L,55611L,55612L,55613L,55614L,
95357 55615L,55616L,55617L,55618L,55619L,55620L,55621L,55622L,55623L,55624L,
95358 55625L,55626L,55627L,55628L,55629L,55630L,55631L,55632L,55633L,55634L,
95359 55635L,55636L,55637L,55638L,55639L,55640L,55641L,55642L,55643L,55644L,
95360 55645L,55646L,55647L,55648L,55649L,55650L,55651L,55652L,55653L,55654L,
95361 55655L,55656L,55657L,55658L,55659L,55660L,55661L,55662L,55663L,55664L,
95362 55665L,55666L,55667L,55668L,55669L,55670L,55671L,55672L,55673L,55674L,
95363 55675L,55676L,55677L,55678L,55679L,55680L,55681L,55682L,55683L,55684L,
95364 55685L,55686L,55687L,55688L,55689L,55690L,55691L,55692L,55693L,55694L,
95365 55695L,55696L,55697L,55698L,55699L,55700L,55701L,55702L,55703L,55704L,
95366 55705L,55706L,55707L,55708L,55709L,55710L,55711L,55712L,55713L,55714L,
95367 55715L,55716L,55717L,55718L,55719L,55720L,55721L,55722L,55723L,55724L,
95368 55725L,55726L,55727L,55728L,55729L,55730L,55731L,55732L,55733L,55734L,
95369 55735L,55736L,55737L,55738L,55739L,55740L,55741L,55742L,55743L,55744L,
95370 55745L,55746L,55747L,55748L,55749L,55750L,55751L,55752L,55753L,55754L,
95371 55755L,55756L,55757L,55758L,55759L,55760L,55761L,55762L,55763L,55764L,
95372 55765L,55766L,55767L,55768L,55769L,55770L,55771L,55772L,55773L,55774L,
95373 55775L,55776L,55777L,55778L,55779L,55780L,55781L,55782L,55783L,55784L,
95374 55785L,55786L,55787L,55788L,55789L,55790L,55791L,55792L,55793L,55794L,
95375 55795L,55796L,55797L,55798L,55799L,55800L,55801L,55802L,55803L,55804L,
95376 55805L,55806L,55807L,55808L,55809L,55810L,55811L,55812L,55813L,55814L,
95377 55815L,55816L,55817L,55818L,55819L,55820L,55821L,55822L,55823L,55824L,
95378 55825L,55826L,55827L,55828L,55829L,55830L,55831L,55832L,55833L,55834L,
95379 55835L,55836L,55837L,55838L,55839L,55840L,55841L,55842L,55843L,55844L,
95380 55845L,55846L,55847L,55848L,55849L,55850L,55851L,55852L,55853L,55854L,
95381 55855L,55856L,55857L,55858L,55859L,55860L,55861L,55862L,55863L,55864L,
95382 55865L,55866L,55867L,55868L,55869L,55870L,55871L,55872L,55873L,55874L,
95383 55875L,55876L,55877L,55878L,55879L,55880L,55881L,55882L,55883L,55884L,
95384 55885L,55886L,55887L,55888L,55889L,55890L,55891L,55892L,55893L,55894L,
95385 55895L,55896L,55897L,55898L,55899L,55900L,55901L,55902L,55903L,55904L,
95386 55905L,55906L,55907L,55908L,55909L,55910L,55911L,55912L,55913L,55914L,
95387 55915L,55916L,55917L,55918L,55919L,55920L,55921L,55922L,55923L,55924L,
95388 55925L,55926L,55927L,55928L,55929L,55930L,55931L,55932L,55933L,55934L,
95389 55935L,55936L,55937L,55938L,55939L,55940L,55941L,55942L,55943L,55944L,
95390 55945L,55946L,55947L,55948L,55949L,55950L,55951L,55952L,55953L,55954L,
95391 55955L,55956L,55957L,55958L,55959L,55960L,55961L,55962L,55963L,55964L,
95392 55965L,55966L,55967L,55968L,55969L,55970L,55971L,55972L,55973L,55974L,
95393 55975L,55976L,55977L,55978L,55979L,55980L,55981L,55982L,55983L,55984L,
95394 55985L,55986L,55987L,55988L,55989L,55990L,55991L,55992L,55993L,55994L,
95395 55995L,55996L,55997L,55998L,55999L,56000L,56001L,56002L,56003L,56004L,
95396 56005L,56006L,56007L,56008L,56009L,56010L,56011L,56012L,56013L,56014L,
95397 56015L,56016L,56017L,56018L,56019L,56020L,56021L,56022L,56023L,56024L,
95398 56025L,56026L,56027L,56028L,56029L,56030L,56031L,56032L,56033L,56034L,
95399 56035L,56036L,56037L,56038L,56039L,56040L,56041L,56042L,56043L,56044L,
95400 56045L,56046L,56047L,56048L,56049L,56050L,56051L,56052L,56053L,56054L,
95401 56055L,56056L,56057L,56058L,56059L,56060L,56061L,56062L,56063L,56064L,
95402 56065L,56066L,56067L,56068L,56069L,56070L,56071L,56072L,56073L,56074L,
95403 56075L,56076L,56077L,56078L,56079L,56080L,56081L,56082L,56083L,56084L,
95404 56085L,56086L,56087L,56088L,56089L,56090L,56091L,56092L,56093L,56094L,
95405 56095L,56096L,56097L,56098L,56099L,56100L,56101L,56102L,56103L,56104L,
95406 56105L,56106L,56107L,56108L,56109L,56110L,56111L,56112L,56113L,56114L,
95407 56115L,56116L,56117L,56118L,56119L,56120L,56121L,56122L,56123L,56124L,
95408 56125L,56126L,56127L,56128L,56129L,56130L,56131L,56132L,56133L,56134L,
95409 56135L,56136L,56137L,56138L,56139L,56140L,56141L,56142L,56143L,56144L,
95410 56145L,56146L,56147L,56148L,56149L,56150L,56151L,56152L,56153L,56154L,
95411 56155L,56156L,56157L,56158L,56159L,56160L,56161L,56162L,56163L,56164L,
95412 56165L,56166L,56167L,56168L,56169L,56170L,56171L,56172L,56173L,56174L,
95413 56175L,56176L,56177L,56178L,56179L,56180L,56181L,56182L,56183L,56184L,
95414 56185L,56186L,56187L,56188L,56189L,56190L,56191L,56192L,56193L,56194L,
95415 56195L,56196L,56197L,56198L,56199L,56200L,56201L,56202L,56203L,56204L,
95416 56205L,56206L,56207L,56208L,56209L,56210L,56211L,56212L,56213L,56214L,
95417 56215L,56216L,56217L,56218L,56219L,56220L,56221L,56222L,56223L,56224L,
95418 56225L,56226L,56227L,56228L,56229L,56230L,56231L,56232L,56233L,56234L,
95419 56235L,56236L,56237L,56238L,56239L,56240L,56241L,56242L,56243L,56244L,
95420 56245L,56246L,56247L,56248L,56249L,56250L,56251L,56252L,56253L,56254L,
95421 56255L,56256L,56257L,56258L,56259L,56260L,56261L,56262L,56263L,56264L,
95422 56265L,56266L,56267L,56268L,56269L,56270L,56271L,56272L,56273L,56274L,
95423 56275L,56276L,56277L,56278L,56279L,56280L,56281L,56282L,56283L,56284L,
95424 56285L,56286L,56287L,56288L,56289L,56290L,56291L,56292L,56293L,56294L,
95425 56295L,56296L,56297L,56298L,56299L,56300L,56301L,56302L,56303L,56304L,
95426 56305L,56306L,56307L,56308L,56309L,56310L,56311L,56312L,56313L,56314L,
95427 56315L,56316L,56317L,56318L,56319L,56320L,56321L,56322L,56323L,56324L,
95428 56325L,56326L,56327L,56328L,56329L,56330L,56331L,56332L,56333L,56334L,
95429 56335L,56336L,56337L,56338L,56339L,56340L,56341L,56342L,56343L,56344L,
95430 56345L,56346L,56347L,56348L,56349L,56350L,56351L,56352L,56353L,56354L,
95431 56355L,56356L,56357L,56358L,56359L,56360L,56361L,56362L,56363L,56364L,
95432 56365L,56366L,56367L,56368L,56369L,56370L,56371L,56372L,56373L,56374L,
95433 56375L,56376L,56377L,56378L,56379L,56380L,56381L,56382L,56383L,56384L,
95434 56385L,56386L,56387L,56388L,56389L,56390L,56391L,56392L,56393L,56394L,
95435 56395L,56396L,56397L,56398L,56399L,56400L,56401L,56402L,56403L,56404L,
95436 56405L,56406L,56407L,56408L,56409L,56410L,56411L,56412L,56413L,56414L,
95437 56415L,56416L,56417L,56418L,56419L,56420L,56421L,56422L,56423L,56424L,
95438 56425L,56426L,56427L,56428L,56429L,56430L,56431L,56432L,56433L,56434L,
95439 56435L,56436L,56437L,56438L,56439L,56440L,56441L,56442L,56443L,56444L,
95440 56445L,56446L,56447L,56448L,56449L,56450L,56451L,56452L,56453L,56454L,
95441 56455L,56456L,56457L,56458L,56459L,56460L,56461L,56462L,56463L,56464L,
95442 56465L,56466L,56467L,56468L,56469L,56470L,56471L,56472L,56473L,56474L,
95443 56475L,56476L,56477L,56478L,56479L,56480L,56481L,56482L,56483L,56484L,
95444 56485L,56486L,56487L,56488L,56489L,56490L,56491L,56492L,56493L,56494L,
95445 56495L,56496L,56497L,56498L,56499L,56500L,56501L,56502L,56503L,56504L,
95446 56505L,56506L,56507L,56508L,56509L,56510L,56511L,56512L,56513L,56514L,
95447 56515L,56516L,56517L,56518L,56519L,56520L,56521L,56522L,56523L,56524L,
95448 56525L,56526L,56527L,56528L,56529L,56530L,56531L,56532L,56533L,56534L,
95449 56535L,56536L,56537L,56538L,56539L,56540L,56541L,56542L,56543L,56544L,
95450 56545L,56546L,56547L,56548L,56549L,56550L,56551L,56552L,56553L,56554L,
95451 56555L,56556L,56557L,56558L,56559L,56560L,56561L,56562L,56563L,56564L,
95452 56565L,56566L,56567L,56568L,56569L,56570L,56571L,56572L,56573L,56574L,
95453 56575L,56576L,56577L,56578L,56579L,56580L,56581L,56582L,56583L,56584L,
95454 56585L,56586L,56587L,56588L,56589L,56590L,56591L,56592L,56593L,56594L,
95455 56595L,56596L,56597L,56598L,56599L,56600L,56601L,56602L,56603L,56604L,
95456 56605L,56606L,56607L,56608L,56609L,56610L,56611L,56612L,56613L,56614L,
95457 56615L,56616L,56617L,56618L,56619L,56620L,56621L,56622L,56623L,56624L,
95458 56625L,56626L,56627L,56628L,56629L,56630L,56631L,56632L,56633L,56634L,
95459 56635L,56636L,56637L,56638L,56639L,56640L,56641L,56642L,56643L,56644L,
95460 56645L,56646L,56647L,56648L,56649L,56650L,56651L,56652L,56653L,56654L,
95461 56655L,56656L,56657L,56658L,56659L,56660L,56661L,56662L,56663L,56664L,
95462 56665L,56666L,56667L,56668L,56669L,56670L,56671L,56672L,56673L,56674L,
95463 56675L,56676L,56677L,56678L,56679L,56680L,56681L,56682L,56683L,56684L,
95464 56685L,56686L,56687L,56688L,56689L,56690L,56691L,56692L,56693L,56694L,
95465 56695L,56696L,56697L,56698L,56699L,56700L,56701L,56702L,56703L,56704L,
95466 56705L,56706L,56707L,56708L,56709L,56710L,56711L,56712L,56713L,56714L,
95467 56715L,56716L,56717L,56718L,56719L,56720L,56721L,56722L,56723L,56724L,
95468 56725L,56726L,56727L,56728L,56729L,56730L,56731L,56732L,56733L,56734L,
95469 56735L,56736L,56737L,56738L,56739L,56740L,56741L,56742L,56743L,56744L,
95470 56745L,56746L,56747L,56748L,56749L,56750L,56751L,56752L,56753L,56754L,
95471 56755L,56756L,56757L,56758L,56759L,56760L,56761L,56762L,56763L,56764L,
95472 56765L,56766L,56767L,56768L,56769L,56770L,56771L,56772L,56773L,56774L,
95473 56775L,56776L,56777L,56778L,56779L,56780L,56781L,56782L,56783L,56784L,
95474 56785L,56786L,56787L,56788L,56789L,56790L,56791L,56792L,56793L,56794L,
95475 56795L,56796L,56797L,56798L,56799L,56800L,56801L,56802L,56803L,56804L,
95476 56805L,56806L,56807L,56808L,56809L,56810L,56811L,56812L,56813L,56814L,
95477 56815L,56816L,56817L,56818L,56819L,56820L,56821L,56822L,56823L,56824L,
95478 56825L,56826L,56827L,56828L,56829L,56830L,56831L,56832L,56833L,56834L,
95479 56835L,56836L,56837L,56838L,56839L,56840L,56841L,56842L,56843L,56844L,
95480 56845L,56846L,56847L,56848L,56849L,56850L,56851L,56852L,56853L,56854L,
95481 56855L,56856L,56857L,56858L,56859L,56860L,56861L,56862L,56863L,56864L,
95482 56865L,56866L,56867L,56868L,56869L,56870L,56871L,56872L,56873L,56874L,
95483 56875L,56876L,56877L,56878L,56879L,56880L,56881L,56882L,56883L,56884L,
95484 56885L,56886L,56887L,56888L,56889L,56890L,56891L,56892L,56893L,56894L,
95485 56895L,56896L,56897L,56898L,56899L,56900L,56901L,56902L,56903L,56904L,
95486 56905L,56906L,56907L,56908L,56909L,56910L,56911L,56912L,56913L,56914L,
95487 56915L,56916L,56917L,56918L,56919L,56920L,56921L,56922L,56923L,56924L,
95488 56925L,56926L,56927L,56928L,56929L,56930L,56931L,56932L,56933L,56934L,
95489 56935L,56936L,56937L,56938L,56939L,56940L,56941L,56942L,56943L,56944L,
95490 56945L,56946L,56947L,56948L,56949L,56950L,56951L,56952L,56953L,56954L,
95491 56955L,56956L,56957L,56958L,56959L,56960L,56961L,56962L,56963L,56964L,
95492 56965L,56966L,56967L,56968L,56969L,56970L,56971L,56972L,56973L,56974L,
95493 56975L,56976L,56977L,56978L,56979L,56980L,56981L,56982L,56983L,56984L,
95494 56985L,56986L,56987L,56988L,56989L,56990L,56991L,56992L,56993L,56994L,
95495 56995L,56996L,56997L,56998L,56999L,57000L,57001L,57002L,57003L,57004L,
95496 57005L,57006L,57007L,57008L,57009L,57010L,57011L,57012L,57013L,57014L,
95497 57015L,57016L,57017L,57018L,57019L,57020L,57021L,57022L,57023L,57024L,
95498 57025L,57026L,57027L,57028L,57029L,57030L,57031L,57032L,57033L,57034L,
95499 57035L,57036L,57037L,57038L,57039L,57040L,57041L,57042L,57043L,57044L,
95500 57045L,57046L,57047L,57048L,57049L,57050L,57051L,57052L,57053L,57054L,
95501 57055L,57056L,57057L,57058L,57059L,57060L,57061L,57062L,57063L,57064L,
95502 57065L,57066L,57067L,57068L,57069L,57070L,57071L,57072L,57073L,57074L,
95503 57075L,57076L,57077L,57078L,57079L,57080L,57081L,57082L,57083L,57084L,
95504 57085L,57086L,57087L,57088L,57089L,57090L,57091L,57092L,57093L,57094L,
95505 57095L,57096L,57097L,57098L,57099L,57100L,57101L,57102L,57103L,57104L,
95506 57105L,57106L,57107L,57108L,57109L,57110L,57111L,57112L,57113L,57114L,
95507 57115L,57116L,57117L,57118L,57119L,57120L,57121L,57122L,57123L,57124L,
95508 57125L,57126L,57127L,57128L,57129L,57130L,57131L,57132L,57133L,57134L,
95509 57135L,57136L,57137L,57138L,57139L,57140L,57141L,57142L,57143L,57144L,
95510 57145L,57146L,57147L,57148L,57149L,57150L,57151L,57152L,57153L,57154L,
95511 57155L,57156L,57157L,57158L,57159L,57160L,57161L,57162L,57163L,57164L,
95512 57165L,57166L,57167L,57168L,57169L,57170L,57171L,57172L,57173L,57174L,
95513 57175L,57176L,57177L,57178L,57179L,57180L,57181L,57182L,57183L,57184L,
95514 57185L,57186L,57187L,57188L,57189L,57190L,57191L,57192L,57193L,57194L,
95515 57195L,57196L,57197L,57198L,57199L,57200L,57201L,57202L,57203L,57204L,
95516 57205L,57206L,57207L,57208L,57209L,57210L,57211L,57212L,57213L,57214L,
95517 57215L,57216L,57217L,57218L,57219L,57220L,57221L,57222L,57223L,57224L,
95518 57225L,57226L,57227L,57228L,57229L,57230L,57231L,57232L,57233L,57234L,
95519 57235L,57236L,57237L,57238L,57239L,57240L,57241L,57242L,57243L,57244L,
95520 57245L,57246L,57247L,57248L,57249L,57250L,57251L,57252L,57253L,57254L,
95521 57255L,57256L,57257L,57258L,57259L,57260L,57261L,57262L,57263L,57264L,
95522 57265L,57266L,57267L,57268L,57269L,57270L,57271L,57272L,57273L,57274L,
95523 57275L,57276L,57277L,57278L,57279L,57280L,57281L,57282L,57283L,57284L,
95524 57285L,57286L,57287L,57288L,57289L,57290L,57291L,57292L,57293L,57294L,
95525 57295L,57296L,57297L,57298L,57299L,57300L,57301L,57302L,57303L,57304L,
95526 57305L,57306L,57307L,57308L,57309L,57310L,57311L,57312L,57313L,57314L,
95527 57315L,57316L,57317L,57318L,57319L,57320L,57321L,57322L,57323L,57324L,
95528 57325L,57326L,57327L,57328L,57329L,57330L,57331L,57332L,57333L,57334L,
95529 57335L,57336L,57337L,57338L,57339L,57340L,57341L,57342L,57343L,57344L,
95530 57345L,57346L,57347L,57348L,57349L,57350L,57351L,57352L,57353L,57354L,
95531 57355L,57356L,57357L,57358L,57359L,57360L,57361L,57362L,57363L,57364L,
95532 57365L,57366L,57367L,57368L,57369L,57370L,57371L,57372L,57373L,57374L,
95533 57375L,57376L,57377L,57378L,57379L,57380L,57381L,57382L,57383L,57384L,
95534 57385L,57386L,57387L,57388L,57389L,57390L,57391L,57392L,57393L,57394L,
95535 57395L,57396L,57397L,57398L,57399L,57400L,57401L,57402L,57403L,57404L,
95536 57405L,57406L,57407L,57408L,57409L,57410L,57411L,57412L,57413L,57414L,
95537 57415L,57416L,57417L,57418L,57419L,57420L,57421L,57422L,57423L,57424L,
95538 57425L,57426L,57427L,57428L,57429L,57430L,57431L,57432L,57433L,57434L,
95539 57435L,57436L,57437L,57438L,57439L,57440L,57441L,57442L,57443L,57444L,
95540 57445L,57446L,57447L,57448L,57449L,57450L,57451L,57452L,57453L,57454L,
95541 57455L,57456L,57457L,57458L,57459L,57460L,57461L,57462L,57463L,57464L,
95542 57465L,57466L,57467L,57468L,57469L,57470L,57471L,57472L,57473L,57474L,
95543 57475L,57476L,57477L,57478L,57479L,57480L,57481L,57482L,57483L,57484L,
95544 57485L,57486L,57487L,57488L,57489L,57490L,57491L,57492L,57493L,57494L,
95545 57495L,57496L,57497L,57498L,57499L,57500L,57501L,57502L,57503L,57504L,
95546 57505L,57506L,57507L,57508L,57509L,57510L,57511L,57512L,57513L,57514L,
95547 57515L,57516L,57517L,57518L,57519L,57520L,57521L,57522L,57523L,57524L,
95548 57525L,57526L,57527L,57528L,57529L,57530L,57531L,57532L,57533L,57534L,
95549 57535L,57536L,57537L,57538L,57539L,57540L,57541L,57542L,57543L,57544L,
95550 57545L,57546L,57547L,57548L,57549L,57550L,57551L,57552L,57553L,57554L,
95551 57555L,57556L,57557L,57558L,57559L,57560L,57561L,57562L,57563L,57564L,
95552 57565L,57566L,57567L,57568L,57569L,57570L,57571L,57572L,57573L,57574L,
95553 57575L,57576L,57577L,57578L,57579L,57580L,57581L,57582L,57583L,57584L,
95554 57585L,57586L,57587L,57588L,57589L,57590L,57591L,57592L,57593L,57594L,
95555 57595L,57596L,57597L,57598L,57599L,57600L,57601L,57602L,57603L,57604L,
95556 57605L,57606L,57607L,57608L,57609L,57610L,57611L,57612L,57613L,57614L,
95557 57615L,57616L,57617L,57618L,57619L,57620L,57621L,57622L,57623L,57624L,
95558 57625L,57626L,57627L,57628L,57629L,57630L,57631L,57632L,57633L,57634L,
95559 57635L,57636L,57637L,57638L,57639L,57640L,57641L,57642L,57643L,57644L,
95560 57645L,57646L,57647L,57648L,57649L,57650L,57651L,57652L,57653L,57654L,
95561 57655L,57656L,57657L,57658L,57659L,57660L,57661L,57662L,57663L,57664L,
95562 57665L,57666L,57667L,57668L,57669L,57670L,57671L,57672L,57673L,57674L,
95563 57675L,57676L,57677L,57678L,57679L,57680L,57681L,57682L,57683L,57684L,
95564 57685L,57686L,57687L,57688L,57689L,57690L,57691L,57692L,57693L,57694L,
95565 57695L,57696L,57697L,57698L,57699L,57700L,57701L,57702L,57703L,57704L,
95566 57705L,57706L,57707L,57708L,57709L,57710L,57711L,57712L,57713L,57714L,
95567 57715L,57716L,57717L,57718L,57719L,57720L,57721L,57722L,57723L,57724L,
95568 57725L,57726L,57727L,57728L,57729L,57730L,57731L,57732L,57733L,57734L,
95569 57735L,57736L,57737L,57738L,57739L,57740L,57741L,57742L,57743L,57744L,
95570 57745L,57746L,57747L,57748L,57749L,57750L,57751L,57752L,57753L,57754L,
95571 57755L,57756L,57757L,57758L,57759L,57760L,57761L,57762L,57763L,57764L,
95572 57765L,57766L,57767L,57768L,57769L,57770L,57771L,57772L,57773L,57774L,
95573 57775L,57776L,57777L,57778L,57779L,57780L,57781L,57782L,57783L,57784L,
95574 57785L,57786L,57787L,57788L,57789L,57790L,57791L,57792L,57793L,57794L,
95575 57795L,57796L,57797L,57798L,57799L,57800L,57801L,57802L,57803L,57804L,
95576 57805L,57806L,57807L,57808L,57809L,57810L,57811L,57812L,57813L,57814L,
95577 57815L,57816L,57817L,57818L,57819L,57820L,57821L,57822L,57823L,57824L,
95578 57825L,57826L,57827L,57828L,57829L,57830L,57831L,57832L,57833L,57834L,
95579 57835L,57836L,57837L,57838L,57839L,57840L,57841L,57842L,57843L,57844L,
95580 57845L,57846L,57847L,57848L,57849L,57850L,57851L,57852L,57853L,57854L,
95581 57855L,57856L,57857L,57858L,57859L,57860L,57861L,57862L,57863L,57864L,
95582 57865L,57866L,57867L,57868L,57869L,57870L,57871L,57872L,57873L,57874L,
95583 57875L,57876L,57877L,57878L,57879L,57880L,57881L,57882L,57883L,57884L,
95584 57885L,57886L,57887L,57888L,57889L,57890L,57891L,57892L,57893L,57894L,
95585 57895L,57896L,57897L,57898L,57899L,57900L,57901L,57902L,57903L,57904L,
95586 57905L,57906L,57907L,57908L,57909L,57910L,57911L,57912L,57913L,57914L,
95587 57915L,57916L,57917L,57918L,57919L,57920L,57921L,57922L,57923L,57924L,
95588 57925L,57926L,57927L,57928L,57929L,57930L,57931L,57932L,57933L,57934L,
95589 57935L,57936L,57937L,57938L,57939L,57940L,57941L,57942L,57943L,57944L,
95590 57945L,57946L,57947L,57948L,57949L,57950L,57951L,57952L,57953L,57954L,
95591 57955L,57956L,57957L,57958L,57959L,57960L,57961L,57962L,57963L,57964L,
95592 57965L,57966L,57967L,57968L,57969L,57970L,57971L,57972L,57973L,57974L,
95593 57975L,57976L,57977L,57978L,57979L,57980L,57981L,57982L,57983L,57984L,
95594 57985L,57986L,57987L,57988L,57989L,57990L,57991L,57992L,57993L,57994L,
95595 57995L,57996L,57997L,57998L,57999L,58000L,58001L,58002L,58003L,58004L,
95596 58005L,58006L,58007L,58008L,58009L,58010L,58011L,58012L,58013L,58014L,
95597 58015L,58016L,58017L,58018L,58019L,58020L,58021L,58022L,58023L,58024L,
95598 58025L,58026L,58027L,58028L,58029L,58030L,58031L,58032L,58033L,58034L,
95599 58035L,58036L,58037L,58038L,58039L,58040L,58041L,58042L,58043L,58044L,
95600 58045L,58046L,58047L,58048L,58049L,58050L,58051L,58052L,58053L,58054L,
95601 58055L,58056L,58057L,58058L,58059L,58060L,58061L,58062L,58063L,58064L,
95602 58065L,58066L,58067L,58068L,58069L,58070L,58071L,58072L,58073L,58074L,
95603 58075L,58076L,58077L,58078L,58079L,58080L,58081L,58082L,58083L,58084L,
95604 58085L,58086L,58087L,58088L,58089L,58090L,58091L,58092L,58093L,58094L,
95605 58095L,58096L,58097L,58098L,58099L,58100L,58101L,58102L,58103L,58104L,
95606 58105L,58106L,58107L,58108L,58109L,58110L,58111L,58112L,58113L,58114L,
95607 58115L,58116L,58117L,58118L,58119L,58120L,58121L,58122L,58123L,58124L,
95608 58125L,58126L,58127L,58128L,58129L,58130L,58131L,58132L,58133L,58134L,
95609 58135L,58136L,58137L,58138L,58139L,58140L,58141L,58142L,58143L,58144L,
95610 58145L,58146L,58147L,58148L,58149L,58150L,58151L,58152L,58153L,58154L,
95611 58155L,58156L,58157L,58158L,58159L,58160L,58161L,58162L,58163L,58164L,
95612 58165L,58166L,58167L,58168L,58169L,58170L,58171L,58172L,58173L,58174L,
95613 58175L,58176L,58177L,58178L,58179L,58180L,58181L,58182L,58183L,58184L,
95614 58185L,58186L,58187L,58188L,58189L,58190L,58191L,58192L,58193L,58194L,
95615 58195L,58196L,58197L,58198L,58199L,58200L,58201L,58202L,58203L,58204L,
95616 58205L,58206L,58207L,58208L,58209L,58210L,58211L,58212L,58213L,58214L,
95617 58215L,58216L,58217L,58218L,58219L,58220L,58221L,58222L,58223L,58224L,
95618 58225L,58226L,58227L,58228L,58229L,58230L,58231L,58232L,58233L,58234L,
95619 58235L,58236L,58237L,58238L,58239L,58240L,58241L,58242L,58243L,58244L,
95620 58245L,58246L,58247L,58248L,58249L,58250L,58251L,58252L,58253L,58254L,
95621 58255L,58256L,58257L,58258L,58259L,58260L,58261L,58262L,58263L,58264L,
95622 58265L,58266L,58267L,58268L,58269L,58270L,58271L,58272L,58273L,58274L,
95623 58275L,58276L,58277L,58278L,58279L,58280L,58281L,58282L,58283L,58284L,
95624 58285L,58286L,58287L,58288L,58289L,58290L,58291L,58292L,58293L,58294L,
95625 58295L,58296L,58297L,58298L,58299L,58300L,58301L,58302L,58303L,58304L,
95626 58305L,58306L,58307L,58308L,58309L,58310L,58311L,58312L,58313L,58314L,
95627 58315L,58316L,58317L,58318L,58319L,58320L,58321L,58322L,58323L,58324L,
95628 58325L,58326L,58327L,58328L,58329L,58330L,58331L,58332L,58333L,58334L,
95629 58335L,58336L,58337L,58338L,58339L,58340L,58341L,58342L,58343L,58344L,
95630 58345L,58346L,58347L,58348L,58349L,58350L,58351L,58352L,58353L,58354L,
95631 58355L,58356L,58357L,58358L,58359L,58360L,58361L,58362L,58363L,58364L,
95632 58365L,58366L,58367L,58368L,58369L,58370L,58371L,58372L,58373L,58374L,
95633 58375L,58376L,58377L,58378L,58379L,58380L,58381L,58382L,58383L,58384L,
95634 58385L,58386L,58387L,58388L,58389L,58390L,58391L,58392L,58393L,58394L,
95635 58395L,58396L,58397L,58398L,58399L,58400L,58401L,58402L,58403L,58404L,
95636 58405L,58406L,58407L,58408L,58409L,58410L,58411L,58412L,58413L,58414L,
95637 58415L,58416L,58417L,58418L,58419L,58420L,58421L,58422L,58423L,58424L,
95638 58425L,58426L,58427L,58428L,58429L,58430L,58431L,58432L,58433L,58434L,
95639 58435L,58436L,58437L,58438L,58439L,58440L,58441L,58442L,58443L,58444L,
95640 58445L,58446L,58447L,58448L,58449L,58450L,58451L,58452L,58453L,58454L,
95641 58455L,58456L,58457L,58458L,58459L,58460L,58461L,58462L,58463L,58464L,
95642 58465L,58466L,58467L,58468L,58469L,58470L,58471L,58472L,58473L,58474L,
95643 58475L,58476L,58477L,58478L,58479L,58480L,58481L,58482L,58483L,58484L,
95644 58485L,58486L,58487L,58488L,58489L,58490L,58491L,58492L,58493L,58494L,
95645 58495L,58496L,58497L,58498L,58499L,58500L,58501L,58502L,58503L,58504L,
95646 58505L,58506L,58507L,58508L,58509L,58510L,58511L,58512L,58513L,58514L,
95647 58515L,58516L,58517L,58518L,58519L,58520L,58521L,58522L,58523L,58524L,
95648 58525L,58526L,58527L,58528L,58529L,58530L,58531L,58532L,58533L,58534L,
95649 58535L,58536L,58537L,58538L,58539L,58540L,58541L,58542L,58543L,58544L,
95650 58545L,58546L,58547L,58548L,58549L,58550L,58551L,58552L,58553L,58554L,
95651 58555L,58556L,58557L,58558L,58559L,58560L,58561L,58562L,58563L,58564L,
95652 58565L,58566L,58567L,58568L,58569L,58570L,58571L,58572L,58573L,58574L,
95653 58575L,58576L,58577L,58578L,58579L,58580L,58581L,58582L,58583L,58584L,
95654 58585L,58586L,58587L,58588L,58589L,58590L,58591L,58592L,58593L,58594L,
95655 58595L,58596L,58597L,58598L,58599L,58600L,58601L,58602L,58603L,58604L,
95656 58605L,58606L,58607L,58608L,58609L,58610L,58611L,58612L,58613L,58614L,
95657 58615L,58616L,58617L,58618L,58619L,58620L,58621L,58622L,58623L,58624L,
95658 58625L,58626L,58627L,58628L,58629L,58630L,58631L,58632L,58633L,58634L,
95659 58635L,58636L,58637L,58638L,58639L,58640L,58641L,58642L,58643L,58644L,
95660 58645L,58646L,58647L,58648L,58649L,58650L,58651L,58652L,58653L,58654L,
95661 58655L,58656L,58657L,58658L,58659L,58660L,58661L,58662L,58663L,58664L,
95662 58665L,58666L,58667L,58668L,58669L,58670L,58671L,58672L,58673L,58674L,
95663 58675L,58676L,58677L,58678L,58679L,58680L,58681L,58682L,58683L,58684L,
95664 58685L,58686L,58687L,58688L,58689L,58690L,58691L,58692L,58693L,58694L,
95665 58695L,58696L,58697L,58698L,58699L,58700L,58701L,58702L,58703L,58704L,
95666 58705L,58706L,58707L,58708L,58709L,58710L,58711L,58712L,58713L,58714L,
95667 58715L,58716L,58717L,58718L,58719L,58720L,58721L,58722L,58723L,58724L,
95668 58725L,58726L,58727L,58728L,58729L,58730L,58731L,58732L,58733L,58734L,
95669 58735L,58736L,58737L,58738L,58739L,58740L,58741L,58742L,58743L,58744L,
95670 58745L,58746L,58747L,58748L,58749L,58750L,58751L,58752L,58753L,58754L,
95671 58755L,58756L,58757L,58758L,58759L,58760L,58761L,58762L,58763L,58764L,
95672 58765L,58766L,58767L,58768L,58769L,58770L,58771L,58772L,58773L,58774L,
95673 58775L,58776L,58777L,58778L,58779L,58780L,58781L,58782L,58783L,58784L,
95674 58785L,58786L,58787L,58788L,58789L,58790L,58791L,58792L,58793L,58794L,
95675 58795L,58796L,58797L,58798L,58799L,58800L,58801L,58802L,58803L,58804L,
95676 58805L,58806L,58807L,58808L,58809L,58810L,58811L,58812L,58813L,58814L,
95677 58815L,58816L,58817L,58818L,58819L,58820L,58821L,58822L,58823L,58824L,
95678 58825L,58826L,58827L,58828L,58829L,58830L,58831L,58832L,58833L,58834L,
95679 58835L,58836L,58837L,58838L,58839L,58840L,58841L,58842L,58843L,58844L,
95680 58845L,58846L,58847L,58848L,58849L,58850L,58851L,58852L,58853L,58854L,
95681 58855L,58856L,58857L,58858L,58859L,58860L,58861L,58862L,58863L,58864L,
95682 58865L,58866L,58867L,58868L,58869L,58870L,58871L,58872L,58873L,58874L,
95683 58875L,58876L,58877L,58878L,58879L,58880L,58881L,58882L,58883L,58884L,
95684 58885L,58886L,58887L,58888L,58889L,58890L,58891L,58892L,58893L,58894L,
95685 58895L,58896L,58897L,58898L,58899L,58900L,58901L,58902L,58903L,58904L,
95686 58905L,58906L,58907L,58908L,58909L,58910L,58911L,58912L,58913L,58914L,
95687 58915L,58916L,58917L,58918L,58919L,58920L,58921L,58922L,58923L,58924L,
95688 58925L,58926L,58927L,58928L,58929L,58930L,58931L,58932L,58933L,58934L,
95689 58935L,58936L,58937L,58938L,58939L,58940L,58941L,58942L,58943L,58944L,
95690 58945L,58946L,58947L,58948L,58949L,58950L,58951L,58952L,58953L,58954L,
95691 58955L,58956L,58957L,58958L,58959L,58960L,58961L,58962L,58963L,58964L,
95692 58965L,58966L,58967L,58968L,58969L,58970L,58971L,58972L,58973L,58974L,
95693 58975L,58976L,58977L,58978L,58979L,58980L,58981L,58982L,58983L,58984L,
95694 58985L,58986L,58987L,58988L,58989L,58990L,58991L,58992L,58993L,58994L,
95695 58995L,58996L,58997L,58998L,58999L,59000L,59001L,59002L,59003L,59004L,
95696 59005L,59006L,59007L,59008L,59009L,59010L,59011L,59012L,59013L,59014L,
95697 59015L,59016L,59017L,59018L,59019L,59020L,59021L,59022L,59023L,59024L,
95698 59025L,59026L,59027L,59028L,59029L,59030L,59031L,59032L,59033L,59034L,
95699 59035L,59036L,59037L,59038L,59039L,59040L,59041L,59042L,59043L,59044L,
95700 59045L,59046L,59047L,59048L,59049L,59050L,59051L,59052L,59053L,59054L,
95701 59055L,59056L,59057L,59058L,59059L,59060L,59061L,59062L,59063L,59064L,
95702 59065L,59066L,59067L,59068L,59069L,59070L,59071L,59072L,59073L,59074L,
95703 59075L,59076L,59077L,59078L,59079L,59080L,59081L,59082L,59083L,59084L,
95704 59085L,59086L,59087L,59088L,59089L,59090L,59091L,59092L,59093L,59094L,
95705 59095L,59096L,59097L,59098L,59099L,59100L,59101L,59102L,59103L,59104L,
95706 59105L,59106L,59107L,59108L,59109L,59110L,59111L,59112L,59113L,59114L,
95707 59115L,59116L,59117L,59118L,59119L,59120L,59121L,59122L,59123L,59124L,
95708 59125L,59126L,59127L,59128L,59129L,59130L,59131L,59132L,59133L,59134L,
95709 59135L,59136L,59137L,59138L,59139L,59140L,59141L,59142L,59143L,59144L,
95710 59145L,59146L,59147L,59148L,59149L,59150L,59151L,59152L,59153L,59154L,
95711 59155L,59156L,59157L,59158L,59159L,59160L,59161L,59162L,59163L,59164L,
95712 59165L,59166L,59167L,59168L,59169L,59170L,59171L,59172L,59173L,59174L,
95713 59175L,59176L,59177L,59178L,59179L,59180L,59181L,59182L,59183L,59184L,
95714 59185L,59186L,59187L,59188L,59189L,59190L,59191L,59192L,59193L,59194L,
95715 59195L,59196L,59197L,59198L,59199L,59200L,59201L,59202L,59203L,59204L,
95716 59205L,59206L,59207L,59208L,59209L,59210L,59211L,59212L,59213L,59214L,
95717 59215L,59216L,59217L,59218L,59219L,59220L,59221L,59222L,59223L,59224L,
95718 59225L,59226L,59227L,59228L,59229L,59230L,59231L,59232L,59233L,59234L,
95719 59235L,59236L,59237L,59238L,59239L,59240L,59241L,59242L,59243L,59244L,
95720 59245L,59246L,59247L,59248L,59249L,59250L,59251L,59252L,59253L,59254L,
95721 59255L,59256L,59257L,59258L,59259L,59260L,59261L,59262L,59263L,59264L,
95722 59265L,59266L,59267L,59268L,59269L,59270L,59271L,59272L,59273L,59274L,
95723 59275L,59276L,59277L,59278L,59279L,59280L,59281L,59282L,59283L,59284L,
95724 59285L,59286L,59287L,59288L,59289L,59290L,59291L,59292L,59293L,59294L,
95725 59295L,59296L,59297L,59298L,59299L,59300L,59301L,59302L,59303L,59304L,
95726 59305L,59306L,59307L,59308L,59309L,59310L,59311L,59312L,59313L,59314L,
95727 59315L,59316L,59317L,59318L,59319L,59320L,59321L,59322L,59323L,59324L,
95728 59325L,59326L,59327L,59328L,59329L,59330L,59331L,59332L,59333L,59334L,
95729 59335L,59336L,59337L,59338L,59339L,59340L,59341L,59342L,59343L,59344L,
95730 59345L,59346L,59347L,59348L,59349L,59350L,59351L,59352L,59353L,59354L,
95731 59355L,59356L,59357L,59358L,59359L,59360L,59361L,59362L,59363L,59364L,
95732 59365L,59366L,59367L,59368L,59369L,59370L,59371L,59372L,59373L,59374L,
95733 59375L,59376L,59377L,59378L,59379L,59380L,59381L,59382L,59383L,59384L,
95734 59385L,59386L,59387L,59388L,59389L,59390L,59391L,59392L,59393L,59394L,
95735 59395L,59396L,59397L,59398L,59399L,59400L,59401L,59402L,59403L,59404L,
95736 59405L,59406L,59407L,59408L,59409L,59410L,59411L,59412L,59413L,59414L,
95737 59415L,59416L,59417L,59418L,59419L,59420L,59421L,59422L,59423L,59424L,
95738 59425L,59426L,59427L,59428L,59429L,59430L,59431L,59432L,59433L,59434L,
95739 59435L,59436L,59437L,59438L,59439L,59440L,59441L,59442L,59443L,59444L,
95740 59445L,59446L,59447L,59448L,59449L,59450L,59451L,59452L,59453L,59454L,
95741 59455L,59456L,59457L,59458L,59459L,59460L,59461L,59462L,59463L,59464L,
95742 59465L,59466L,59467L,59468L,59469L,59470L,59471L,59472L,59473L,59474L,
95743 59475L,59476L,59477L,59478L,59479L,59480L,59481L,59482L,59483L,59484L,
95744 59485L,59486L,59487L,59488L,59489L,59490L,59491L,59492L,59493L,59494L,
95745 59495L,59496L,59497L,59498L,59499L,59500L,59501L,59502L,59503L,59504L,
95746 59505L,59506L,59507L,59508L,59509L,59510L,59511L,59512L,59513L,59514L,
95747 59515L,59516L,59517L,59518L,59519L,59520L,59521L,59522L,59523L,59524L,
95748 59525L,59526L,59527L,59528L,59529L,59530L,59531L,59532L,59533L,59534L,
95749 59535L,59536L,59537L,59538L,59539L,59540L,59541L,59542L,59543L,59544L,
95750 59545L,59546L,59547L,59548L,59549L,59550L,59551L,59552L,59553L,59554L,
95751 59555L,59556L,59557L,59558L,59559L,59560L,59561L,59562L,59563L,59564L,
95752 59565L,59566L,59567L,59568L,59569L,59570L,59571L,59572L,59573L,59574L,
95753 59575L,59576L,59577L,59578L,59579L,59580L,59581L,59582L,59583L,59584L,
95754 59585L,59586L,59587L,59588L,59589L,59590L,59591L,59592L,59593L,59594L,
95755 59595L,59596L,59597L,59598L,59599L,59600L,59601L,59602L,59603L,59604L,
95756 59605L,59606L,59607L,59608L,59609L,59610L,59611L,59612L,59613L,59614L,
95757 59615L,59616L,59617L,59618L,59619L,59620L,59621L,59622L,59623L,59624L,
95758 59625L,59626L,59627L,59628L,59629L,59630L,59631L,59632L,59633L,59634L,
95759 59635L,59636L,59637L,59638L,59639L,59640L,59641L,59642L,59643L,59644L,
95760 59645L,59646L,59647L,59648L,59649L,59650L,59651L,59652L,59653L,59654L,
95761 59655L,59656L,59657L,59658L,59659L,59660L,59661L,59662L,59663L,59664L,
95762 59665L,59666L,59667L,59668L,59669L,59670L,59671L,59672L,59673L,59674L,
95763 59675L,59676L,59677L,59678L,59679L,59680L,59681L,59682L,59683L,59684L,
95764 59685L,59686L,59687L,59688L,59689L,59690L,59691L,59692L,59693L,59694L,
95765 59695L,59696L,59697L,59698L,59699L,59700L,59701L,59702L,59703L,59704L,
95766 59705L,59706L,59707L,59708L,59709L,59710L,59711L,59712L,59713L,59714L,
95767 59715L,59716L,59717L,59718L,59719L,59720L,59721L,59722L,59723L,59724L,
95768 59725L,59726L,59727L,59728L,59729L,59730L,59731L,59732L,59733L,59734L,
95769 59735L,59736L,59737L,59738L,59739L,59740L,59741L,59742L,59743L,59744L,
95770 59745L,59746L,59747L,59748L,59749L,59750L,59751L,59752L,59753L,59754L,
95771 59755L,59756L,59757L,59758L,59759L,59760L,59761L,59762L,59763L,59764L,
95772 59765L,59766L,59767L,59768L,59769L,59770L,59771L,59772L,59773L,59774L,
95773 59775L,59776L,59777L,59778L,59779L,59780L,59781L,59782L,59783L,59784L,
95774 59785L,59786L,59787L,59788L,59789L,59790L,59791L,59792L,59793L,59794L,
95775 59795L,59796L,59797L,59798L,59799L,59800L,59801L,59802L,59803L,59804L,
95776 59805L,59806L,59807L,59808L,59809L,59810L,59811L,59812L,59813L,59814L,
95777 59815L,59816L,59817L,59818L,59819L,59820L,59821L,59822L,59823L,59824L,
95778 59825L,59826L,59827L,59828L,59829L,59830L,59831L,59832L,59833L,59834L,
95779 59835L,59836L,59837L,59838L,59839L,59840L,59841L,59842L,59843L,59844L,
95780 59845L,59846L,59847L,59848L,59849L,59850L,59851L,59852L,59853L,59854L,
95781 59855L,59856L,59857L,59858L,59859L,59860L,59861L,59862L,59863L,59864L,
95782 59865L,59866L,59867L,59868L,59869L,59870L,59871L,59872L,59873L,59874L,
95783 59875L,59876L,59877L,59878L,59879L,59880L,59881L,59882L,59883L,59884L,
95784 59885L,59886L,59887L,59888L,59889L,59890L,59891L,59892L,59893L,59894L,
95785 59895L,59896L,59897L,59898L,59899L,59900L,59901L,59902L,59903L,59904L,
95786 59905L,59906L,59907L,59908L,59909L,59910L,59911L,59912L,59913L,59914L,
95787 59915L,59916L,59917L,59918L,59919L,59920L,59921L,59922L,59923L,59924L,
95788 59925L,59926L,59927L,59928L,59929L,59930L,59931L,59932L,59933L,59934L,
95789 59935L,59936L,59937L,59938L,59939L,59940L,59941L,59942L,59943L,59944L,
95790 59945L,59946L,59947L,59948L,59949L,59950L,59951L,59952L,59953L,59954L,
95791 59955L,59956L,59957L,59958L,59959L,59960L,59961L,59962L,59963L,59964L,
95792 59965L,59966L,59967L,59968L,59969L,59970L,59971L,59972L,59973L,59974L,
95793 59975L,59976L,59977L,59978L,59979L,59980L,59981L,59982L,59983L,59984L,
95794 59985L,59986L,59987L,59988L,59989L,59990L,59991L,59992L,59993L,59994L,
95795 59995L,59996L,59997L,59998L,59999L,60000L,60001L,60002L,60003L,60004L,
95796 60005L,60006L,60007L,60008L,60009L,60010L,60011L,60012L,60013L,60014L,
95797 60015L,60016L,60017L,60018L,60019L,60020L,60021L,60022L,60023L,60024L,
95798 60025L,60026L,60027L,60028L,60029L,60030L,60031L,60032L,60033L,60034L,
95799 60035L,60036L,60037L,60038L,60039L,60040L,60041L,60042L,60043L,60044L,
95800 60045L,60046L,60047L,60048L,60049L,60050L,60051L,60052L,60053L,60054L,
95801 60055L,60056L,60057L,60058L,60059L,60060L,60061L,60062L,60063L,60064L,
95802 60065L,60066L,60067L,60068L,60069L,60070L,60071L,60072L,60073L,60074L,
95803 60075L,60076L,60077L,60078L,60079L,60080L,60081L,60082L,60083L,60084L,
95804 60085L,60086L,60087L,60088L,60089L,60090L,60091L,60092L,60093L,60094L,
95805 60095L,60096L,60097L,60098L,60099L,60100L,60101L,60102L,60103L,60104L,
95806 60105L,60106L,60107L,60108L,60109L,60110L,60111L,60112L,60113L,60114L,
95807 60115L,60116L,60117L,60118L,60119L,60120L,60121L,60122L,60123L,60124L,
95808 60125L,60126L,60127L,60128L,60129L,60130L,60131L,60132L,60133L,60134L,
95809 60135L,60136L,60137L,60138L,60139L,60140L,60141L,60142L,60143L,60144L,
95810 60145L,60146L,60147L,60148L,60149L,60150L,60151L,60152L,60153L,60154L,
95811 60155L,60156L,60157L,60158L,60159L,60160L,60161L,60162L,60163L,60164L,
95812 60165L,60166L,60167L,60168L,60169L,60170L,60171L,60172L,60173L,60174L,
95813 60175L,60176L,60177L,60178L,60179L,60180L,60181L,60182L,60183L,60184L,
95814 60185L,60186L,60187L,60188L,60189L,60190L,60191L,60192L,60193L,60194L,
95815 60195L,60196L,60197L,60198L,60199L,60200L,60201L,60202L,60203L,60204L,
95816 60205L,60206L,60207L,60208L,60209L,60210L,60211L,60212L,60213L,60214L,
95817 60215L,60216L,60217L,60218L,60219L,60220L,60221L,60222L,60223L,60224L,
95818 60225L,60226L,60227L,60228L,60229L,60230L,60231L,60232L,60233L,60234L,
95819 60235L,60236L,60237L,60238L,60239L,60240L,60241L,60242L,60243L,60244L,
95820 60245L,60246L,60247L,60248L,60249L,60250L,60251L,60252L,60253L,60254L,
95821 60255L,60256L,60257L,60258L,60259L,60260L,60261L,60262L,60263L,60264L,
95822 60265L,60266L,60267L,60268L,60269L,60270L,60271L,60272L,60273L,60274L,
95823 60275L,60276L,60277L,60278L,60279L,60280L,60281L,60282L,60283L,60284L,
95824 60285L,60286L,60287L,60288L,60289L,60290L,60291L,60292L,60293L,60294L,
95825 60295L,60296L,60297L,60298L,60299L,60300L,60301L,60302L,60303L,60304L,
95826 60305L,60306L,60307L,60308L,60309L,60310L,60311L,60312L,60313L,60314L,
95827 60315L,60316L,60317L,60318L,60319L,60320L,60321L,60322L,60323L,60324L,
95828 60325L,60326L,60327L,60328L,60329L,60330L,60331L,60332L,60333L,60334L,
95829 60335L,60336L,60337L,60338L,60339L,60340L,60341L,60342L,60343L,60344L,
95830 60345L,60346L,60347L,60348L,60349L,60350L,60351L,60352L,60353L,60354L,
95831 60355L,60356L,60357L,60358L,60359L,60360L,60361L,60362L,60363L,60364L,
95832 60365L,60366L,60367L,60368L,60369L,60370L,60371L,60372L,60373L,60374L,
95833 60375L,60376L,60377L,60378L,60379L,60380L,60381L,60382L,60383L,60384L,
95834 60385L,60386L,60387L,60388L,60389L,60390L,60391L,60392L,60393L,60394L,
95835 60395L,60396L,60397L,60398L,60399L,60400L,60401L,60402L,60403L,60404L,
95836 60405L,60406L,60407L,60408L,60409L,60410L,60411L,60412L,60413L,60414L,
95837 60415L,60416L,60417L,60418L,60419L,60420L,60421L,60422L,60423L,60424L,
95838 60425L,60426L,60427L,60428L,60429L,60430L,60431L,60432L,60433L,60434L,
95839 60435L,60436L,60437L,60438L,60439L,60440L,60441L,60442L,60443L,60444L,
95840 60445L,60446L,60447L,60448L,60449L,60450L,60451L,60452L,60453L,60454L,
95841 60455L,60456L,60457L,60458L,60459L,60460L,60461L,60462L,60463L,60464L,
95842 60465L,60466L,60467L,60468L,60469L,60470L,60471L,60472L,60473L,60474L,
95843 60475L,60476L,60477L,60478L,60479L,60480L,60481L,60482L,60483L,60484L,
95844 60485L,60486L,60487L,60488L,60489L,60490L,60491L,60492L,60493L,60494L,
95845 60495L,60496L,60497L,60498L,60499L,60500L,60501L,60502L,60503L,60504L,
95846 60505L,60506L,60507L,60508L,60509L,60510L,60511L,60512L,60513L,60514L,
95847 60515L,60516L,60517L,60518L,60519L,60520L,60521L,60522L,60523L,60524L,
95848 60525L,60526L,60527L,60528L,60529L,60530L,60531L,60532L,60533L,60534L,
95849 60535L,60536L,60537L,60538L,60539L,60540L,60541L,60542L,60543L,60544L,
95850 60545L,60546L,60547L,60548L,60549L,60550L,60551L,60552L,60553L,60554L,
95851 60555L,60556L,60557L,60558L,60559L,60560L,60561L,60562L,60563L,60564L,
95852 60565L,60566L,60567L,60568L,60569L,60570L,60571L,60572L,60573L,60574L,
95853 60575L,60576L,60577L,60578L,60579L,60580L,60581L,60582L,60583L,60584L,
95854 60585L,60586L,60587L,60588L,60589L,60590L,60591L,60592L,60593L,60594L,
95855 60595L,60596L,60597L,60598L,60599L,60600L,60601L,60602L,60603L,60604L,
95856 60605L,60606L,60607L,60608L,60609L,60610L,60611L,60612L,60613L,60614L,
95857 60615L,60616L,60617L,60618L,60619L,60620L,60621L,60622L,60623L,60624L,
95858 60625L,60626L,60627L,60628L,60629L,60630L,60631L,60632L,60633L,60634L,
95859 60635L,60636L,60637L,60638L,60639L,60640L,60641L,60642L,60643L,60644L,
95860 60645L,60646L,60647L,60648L,60649L,60650L,60651L,60652L,60653L,60654L,
95861 60655L,60656L,60657L,60658L,60659L,60660L,60661L,60662L,60663L,60664L,
95862 60665L,60666L,60667L,60668L,60669L,60670L,60671L,60672L,60673L,60674L,
95863 60675L,60676L,60677L,60678L,60679L,60680L,60681L,60682L,60683L,60684L,
95864 60685L,60686L,60687L,60688L,60689L,60690L,60691L,60692L,60693L,60694L,
95865 60695L,60696L,60697L,60698L,60699L,60700L,60701L,60702L,60703L,60704L,
95866 60705L,60706L,60707L,60708L,60709L,60710L,60711L,60712L,60713L,60714L,
95867 60715L,60716L,60717L,60718L,60719L,60720L,60721L,60722L,60723L,60724L,
95868 60725L,60726L,60727L,60728L,60729L,60730L,60731L,60732L,60733L,60734L,
95869 60735L,60736L,60737L,60738L,60739L,60740L,60741L,60742L,60743L,60744L,
95870 60745L,60746L,60747L,60748L,60749L,60750L,60751L,60752L,60753L,60754L,
95871 60755L,60756L,60757L,60758L,60759L,60760L,60761L,60762L,60763L,60764L,
95872 60765L,60766L,60767L,60768L,60769L,60770L,60771L,60772L,60773L,60774L,
95873 60775L,60776L,60777L,60778L,60779L,60780L,60781L,60782L,60783L,60784L,
95874 60785L,60786L,60787L,60788L,60789L,60790L,60791L,60792L,60793L,60794L,
95875 60795L,60796L,60797L,60798L,60799L,60800L,60801L,60802L,60803L,60804L,
95876 60805L,60806L,60807L,60808L,60809L,60810L,60811L,60812L,60813L,60814L,
95877 60815L,60816L,60817L,60818L,60819L,60820L,60821L,60822L,60823L,60824L,
95878 60825L,60826L,60827L,60828L,60829L,60830L,60831L,60832L,60833L,60834L,
95879 60835L,60836L,60837L,60838L,60839L,60840L,60841L,60842L,60843L,60844L,
95880 60845L,60846L,60847L,60848L,60849L,60850L,60851L,60852L,60853L,60854L,
95881 60855L,60856L,60857L,60858L,60859L,60860L,60861L,60862L,60863L,60864L,
95882 60865L,60866L,60867L,60868L,60869L,60870L,60871L,60872L,60873L,60874L,
95883 60875L,60876L,60877L,60878L,60879L,60880L,60881L,60882L,60883L,60884L,
95884 60885L,60886L,60887L,60888L,60889L,60890L,60891L,60892L,60893L,60894L,
95885 60895L,60896L,60897L,60898L,60899L,60900L,60901L,60902L,60903L,60904L,
95886 60905L,60906L,60907L,60908L,60909L,60910L,60911L,60912L,60913L,60914L,
95887 60915L,60916L,60917L,60918L,60919L,60920L,60921L,60922L,60923L,60924L,
95888 60925L,60926L,60927L,60928L,60929L,60930L,60931L,60932L,60933L,60934L,
95889 60935L,60936L,60937L,60938L,60939L,60940L,60941L,60942L,60943L,60944L,
95890 60945L,60946L,60947L,60948L,60949L,60950L,60951L,60952L,60953L,60954L,
95891 60955L,60956L,60957L,60958L,60959L,60960L,60961L,60962L,60963L,60964L,
95892 60965L,60966L,60967L,60968L,60969L,60970L,60971L,60972L,60973L,60974L,
95893 60975L,60976L,60977L,60978L,60979L,60980L,60981L,60982L,60983L,60984L,
95894 60985L,60986L,60987L,60988L,60989L,60990L,60991L,60992L,60993L,60994L,
95895 60995L,60996L,60997L,60998L,60999L,61000L,61001L,61002L,61003L,61004L,
95896 61005L,61006L,61007L,61008L,61009L,61010L,61011L,61012L,61013L,61014L,
95897 61015L,61016L,61017L,61018L,61019L,61020L,61021L,61022L,61023L,61024L,
95898 61025L,61026L,61027L,61028L,61029L,61030L,61031L,61032L,61033L,61034L,
95899 61035L,61036L,61037L,61038L,61039L,61040L,61041L,61042L,61043L,61044L,
95900 61045L,61046L,61047L,61048L,61049L,61050L,61051L,61052L,61053L,61054L,
95901 61055L,61056L,61057L,61058L,61059L,61060L,61061L,61062L,61063L,61064L,
95902 61065L,61066L,61067L,61068L,61069L,61070L,61071L,61072L,61073L,61074L,
95903 61075L,61076L,61077L,61078L,61079L,61080L,61081L,61082L,61083L,61084L,
95904 61085L,61086L,61087L,61088L,61089L,61090L,61091L,61092L,61093L,61094L,
95905 61095L,61096L,61097L,61098L,61099L,61100L,61101L,61102L,61103L,61104L,
95906 61105L,61106L,61107L,61108L,61109L,61110L,61111L,61112L,61113L,61114L,
95907 61115L,61116L,61117L,61118L,61119L,61120L,61121L,61122L,61123L,61124L,
95908 61125L,61126L,61127L,61128L,61129L,61130L,61131L,61132L,61133L,61134L,
95909 61135L,61136L,61137L,61138L,61139L,61140L,61141L,61142L,61143L,61144L,
95910 61145L,61146L,61147L,61148L,61149L,61150L,61151L,61152L,61153L,61154L,
95911 61155L,61156L,61157L,61158L,61159L,61160L,61161L,61162L,61163L,61164L,
95912 61165L,61166L,61167L,61168L,61169L,61170L,61171L,61172L,61173L,61174L,
95913 61175L,61176L,61177L,61178L,61179L,61180L,61181L,61182L,61183L,61184L,
95914 61185L,61186L,61187L,61188L,61189L,61190L,61191L,61192L,61193L,61194L,
95915 61195L,61196L,61197L,61198L,61199L,61200L,61201L,61202L,61203L,61204L,
95916 61205L,61206L,61207L,61208L,61209L,61210L,61211L,61212L,61213L,61214L,
95917 61215L,61216L,61217L,61218L,61219L,61220L,61221L,61222L,61223L,61224L,
95918 61225L,61226L,61227L,61228L,61229L,61230L,61231L,61232L,61233L,61234L,
95919 61235L,61236L,61237L,61238L,61239L,61240L,61241L,61242L,61243L,61244L,
95920 61245L,61246L,61247L,61248L,61249L,61250L,61251L,61252L,61253L,61254L,
95921 61255L,61256L,61257L,61258L,61259L,61260L,61261L,61262L,61263L,61264L,
95922 61265L,61266L,61267L,61268L,61269L,61270L,61271L,61272L,61273L,61274L,
95923 61275L,61276L,61277L,61278L,61279L,61280L,61281L,61282L,61283L,61284L,
95924 61285L,61286L,61287L,61288L,61289L,61290L,61291L,61292L,61293L,61294L,
95925 61295L,61296L,61297L,61298L,61299L,61300L,61301L,61302L,61303L,61304L,
95926 61305L,61306L,61307L,61308L,61309L,61310L,61311L,61312L,61313L,61314L,
95927 61315L,61316L,61317L,61318L,61319L,61320L,61321L,61322L,61323L,61324L,
95928 61325L,61326L,61327L,61328L,61329L,61330L,61331L,61332L,61333L,61334L,
95929 61335L,61336L,61337L,61338L,61339L,61340L,61341L,61342L,61343L,61344L,
95930 61345L,61346L,61347L,61348L,61349L,61350L,61351L,61352L,61353L,61354L,
95931 61355L,61356L,61357L,61358L,61359L,61360L,61361L,61362L,61363L,61364L,
95932 61365L,61366L,61367L,61368L,61369L,61370L,61371L,61372L,61373L,61374L,
95933 61375L,61376L,61377L,61378L,61379L,61380L,61381L,61382L,61383L,61384L,
95934 61385L,61386L,61387L,61388L,61389L,61390L,61391L,61392L,61393L,61394L,
95935 61395L,61396L,61397L,61398L,61399L,61400L,61401L,61402L,61403L,61404L,
95936 61405L,61406L,61407L,61408L,61409L,61410L,61411L,61412L,61413L,61414L,
95937 61415L,61416L,61417L,61418L,61419L,61420L,61421L,61422L,61423L,61424L,
95938 61425L,61426L,61427L,61428L,61429L,61430L,61431L,61432L,61433L,61434L,
95939 61435L,61436L,61437L,61438L,61439L,61440L,61441L,61442L,61443L,61444L,
95940 61445L,61446L,61447L,61448L,61449L,61450L,61451L,61452L,61453L,61454L,
95941 61455L,61456L,61457L,61458L,61459L,61460L,61461L,61462L,61463L,61464L,
95942 61465L,61466L,61467L,61468L,61469L,61470L,61471L,61472L,61473L,61474L,
95943 61475L,61476L,61477L,61478L,61479L,61480L,61481L,61482L,61483L,61484L,
95944 61485L,61486L,61487L,61488L,61489L,61490L,61491L,61492L,61493L,61494L,
95945 61495L,61496L,61497L,61498L,61499L,61500L,61501L,61502L,61503L,61504L,
95946 61505L,61506L,61507L,61508L,61509L,61510L,61511L,61512L,61513L,61514L,
95947 61515L,61516L,61517L,61518L,61519L,61520L,61521L,61522L,61523L,61524L,
95948 61525L,61526L,61527L,61528L,61529L,61530L,61531L,61532L,61533L,61534L,
95949 61535L,61536L,61537L,61538L,61539L,61540L,61541L,61542L,61543L,61544L,
95950 61545L,61546L,61547L,61548L,61549L,61550L,61551L,61552L,61553L,61554L,
95951 61555L,61556L,61557L,61558L,61559L,61560L,61561L,61562L,61563L,61564L,
95952 61565L,61566L,61567L,61568L,61569L,61570L,61571L,61572L,61573L,61574L,
95953 61575L,61576L,61577L,61578L,61579L,61580L,61581L,61582L,61583L,61584L,
95954 61585L,61586L,61587L,61588L,61589L,61590L,61591L,61592L,61593L,61594L,
95955 61595L,61596L,61597L,61598L,61599L,61600L,61601L,61602L,61603L,61604L,
95956 61605L,61606L,61607L,61608L,61609L,61610L,61611L,61612L,61613L,61614L,
95957 61615L,61616L,61617L,61618L,61619L,61620L,61621L,61622L,61623L,61624L,
95958 61625L,61626L,61627L,61628L,61629L,61630L,61631L,61632L,61633L,61634L,
95959 61635L,61636L,61637L,61638L,61639L,61640L,61641L,61642L,61643L,61644L,
95960 61645L,61646L,61647L,61648L,61649L,61650L,61651L,61652L,61653L,61654L,
95961 61655L,61656L,61657L,61658L,61659L,61660L,61661L,61662L,61663L,61664L,
95962 61665L,61666L,61667L,61668L,61669L,61670L,61671L,61672L,61673L,61674L,
95963 61675L,61676L,61677L,61678L,61679L,61680L,61681L,61682L,61683L,61684L,
95964 61685L,61686L,61687L,61688L,61689L,61690L,61691L,61692L,61693L,61694L,
95965 61695L,61696L,61697L,61698L,61699L,61700L,61701L,61702L,61703L,61704L,
95966 61705L,61706L,61707L,61708L,61709L,61710L,61711L,61712L,61713L,61714L,
95967 61715L,61716L,61717L,61718L,61719L,61720L,61721L,61722L,61723L,61724L,
95968 61725L,61726L,61727L,61728L,61729L,61730L,61731L,61732L,61733L,61734L,
95969 61735L,61736L,61737L,61738L,61739L,61740L,61741L,61742L,61743L,61744L,
95970 61745L,61746L,61747L,61748L,61749L,61750L,61751L,61752L,61753L,61754L,
95971 61755L,61756L,61757L,61758L,61759L,61760L,61761L,61762L,61763L,61764L,
95972 61765L,61766L,61767L,61768L,61769L,61770L,61771L,61772L,61773L,61774L,
95973 61775L,61776L,61777L,61778L,61779L,61780L,61781L,61782L,61783L,61784L,
95974 61785L,61786L,61787L,61788L,61789L,61790L,61791L,61792L,61793L,61794L,
95975 61795L,61796L,61797L,61798L,61799L,61800L,61801L,61802L,61803L,61804L,
95976 61805L,61806L,61807L,61808L,61809L,61810L,61811L,61812L,61813L,61814L,
95977 61815L,61816L,61817L,61818L,61819L,61820L,61821L,61822L,61823L,61824L,
95978 61825L,61826L,61827L,61828L,61829L,61830L,61831L,61832L,61833L,61834L,
95979 61835L,61836L,61837L,61838L,61839L,61840L,61841L,61842L,61843L,61844L,
95980 61845L,61846L,61847L,61848L,61849L,61850L,61851L,61852L,61853L,61854L,
95981 61855L,61856L,61857L,61858L,61859L,61860L,61861L,61862L,61863L,61864L,
95982 61865L,61866L,61867L,61868L,61869L,61870L,61871L,61872L,61873L,61874L,
95983 61875L,61876L,61877L,61878L,61879L,61880L,61881L,61882L,61883L,61884L,
95984 61885L,61886L,61887L,61888L,61889L,61890L,61891L,61892L,61893L,61894L,
95985 61895L,61896L,61897L,61898L,61899L,61900L,61901L,61902L,61903L,61904L,
95986 61905L,61906L,61907L,61908L,61909L,61910L,61911L,61912L,61913L,61914L,
95987 61915L,61916L,61917L,61918L,61919L,61920L,61921L,61922L,61923L,61924L,
95988 61925L,61926L,61927L,61928L,61929L,61930L,61931L,61932L,61933L,61934L,
95989 61935L,61936L,61937L,61938L,61939L,61940L,61941L,61942L,61943L,61944L,
95990 61945L,61946L,61947L,61948L,61949L,61950L,61951L,61952L,61953L,61954L,
95991 61955L,61956L,61957L,61958L,61959L,61960L,61961L,61962L,61963L,61964L,
95992 61965L,61966L,61967L,61968L,61969L,61970L,61971L,61972L,61973L,61974L,
95993 61975L,61976L,61977L,61978L,61979L,61980L,61981L,61982L,61983L,61984L,
95994 61985L,61986L,61987L,61988L,61989L,61990L,61991L,61992L,61993L,61994L,
95995 61995L,61996L,61997L,61998L,61999L,62000L,62001L,62002L,62003L,62004L,
95996 62005L,62006L,62007L,62008L,62009L,62010L,62011L,62012L,62013L,62014L,
95997 62015L,62016L,62017L,62018L,62019L,62020L,62021L,62022L,62023L,62024L,
95998 62025L,62026L,62027L,62028L,62029L,62030L,62031L,62032L,62033L,62034L,
95999 62035L,62036L,62037L,62038L,62039L,62040L,62041L,62042L,62043L,62044L,
96000 62045L,62046L,62047L,62048L,62049L,62050L,62051L,62052L,62053L,62054L,
96001 62055L,62056L,62057L,62058L,62059L,62060L,62061L,62062L,62063L,62064L,
96002 62065L,62066L,62067L,62068L,62069L,62070L,62071L,62072L,62073L,62074L,
96003 62075L,62076L,62077L,62078L,62079L,62080L,62081L,62082L,62083L,62084L,
96004 62085L,62086L,62087L,62088L,62089L,62090L,62091L,62092L,62093L,62094L,
96005 62095L,62096L,62097L,62098L,62099L,62100L,62101L,62102L,62103L,62104L,
96006 62105L,62106L,62107L,62108L,62109L,62110L,62111L,62112L,62113L,62114L,
96007 62115L,62116L,62117L,62118L,62119L,62120L,62121L,62122L,62123L,62124L,
96008 62125L,62126L,62127L,62128L,62129L,62130L,62131L,62132L,62133L,62134L,
96009 62135L,62136L,62137L,62138L,62139L,62140L,62141L,62142L,62143L,62144L,
96010 62145L,62146L,62147L,62148L,62149L,62150L,62151L,62152L,62153L,62154L,
96011 62155L,62156L,62157L,62158L,62159L,62160L,62161L,62162L,62163L,62164L,
96012 62165L,62166L,62167L,62168L,62169L,62170L,62171L,62172L,62173L,62174L,
96013 62175L,62176L,62177L,62178L,62179L,62180L,62181L,62182L,62183L,62184L,
96014 62185L,62186L,62187L,62188L,62189L,62190L,62191L,62192L,62193L,62194L,
96015 62195L,62196L,62197L,62198L,62199L,62200L,62201L,62202L,62203L,62204L,
96016 62205L,62206L,62207L,62208L,62209L,62210L,62211L,62212L,62213L,62214L,
96017 62215L,62216L,62217L,62218L,62219L,62220L,62221L,62222L,62223L,62224L,
96018 62225L,62226L,62227L,62228L,62229L,62230L,62231L,62232L,62233L,62234L,
96019 62235L,62236L,62237L,62238L,62239L,62240L,62241L,62242L,62243L,62244L,
96020 62245L,62246L,62247L,62248L,62249L,62250L,62251L,62252L,62253L,62254L,
96021 62255L,62256L,62257L,62258L,62259L,62260L,62261L,62262L,62263L,62264L,
96022 62265L,62266L,62267L,62268L,62269L,62270L,62271L,62272L,62273L,62274L,
96023 62275L,62276L,62277L,62278L,62279L,62280L,62281L,62282L,62283L,62284L,
96024 62285L,62286L,62287L,62288L,62289L,62290L,62291L,62292L,62293L,62294L,
96025 62295L,62296L,62297L,62298L,62299L,62300L,62301L,62302L,62303L,62304L,
96026 62305L,62306L,62307L,62308L,62309L,62310L,62311L,62312L,62313L,62314L,
96027 62315L,62316L,62317L,62318L,62319L,62320L,62321L,62322L,62323L,62324L,
96028 62325L,62326L,62327L,62328L,62329L,62330L,62331L,62332L,62333L,62334L,
96029 62335L,62336L,62337L,62338L,62339L,62340L,62341L,62342L,62343L,62344L,
96030 62345L,62346L,62347L,62348L,62349L,62350L,62351L,62352L,62353L,62354L,
96031 62355L,62356L,62357L,62358L,62359L,62360L,62361L,62362L,62363L,62364L,
96032 62365L,62366L,62367L,62368L,62369L,62370L,62371L,62372L,62373L,62374L,
96033 62375L,62376L,62377L,62378L,62379L,62380L,62381L,62382L,62383L,62384L,
96034 62385L,62386L,62387L,62388L,62389L,62390L,62391L,62392L,62393L,62394L,
96035 62395L,62396L,62397L,62398L,62399L,62400L,62401L,62402L,62403L,62404L,
96036 62405L,62406L,62407L,62408L,62409L,62410L,62411L,62412L,62413L,62414L,
96037 62415L,62416L,62417L,62418L,62419L,62420L,62421L,62422L,62423L,62424L,
96038 62425L,62426L,62427L,62428L,62429L,62430L,62431L,62432L,62433L,62434L,
96039 62435L,62436L,62437L,62438L,62439L,62440L,62441L,62442L,62443L,62444L,
96040 62445L,62446L,62447L,62448L,62449L,62450L,62451L,62452L,62453L,62454L,
96041 62455L,62456L,62457L,62458L,62459L,62460L,62461L,62462L,62463L,62464L,
96042 62465L,62466L,62467L,62468L,62469L,62470L,62471L,62472L,62473L,62474L,
96043 62475L,62476L,62477L,62478L,62479L,62480L,62481L,62482L,62483L,62484L,
96044 62485L,62486L,62487L,62488L,62489L,62490L,62491L,62492L,62493L,62494L,
96045 62495L,62496L,62497L,62498L,62499L,62500L,62501L,62502L,62503L,62504L,
96046 62505L,62506L,62507L,62508L,62509L,62510L,62511L,62512L,62513L,62514L,
96047 62515L,62516L,62517L,62518L,62519L,62520L,62521L,62522L,62523L,62524L,
96048 62525L,62526L,62527L,62528L,62529L,62530L,62531L,62532L,62533L,62534L,
96049 62535L,62536L,62537L,62538L,62539L,62540L,62541L,62542L,62543L,62544L,
96050 62545L,62546L,62547L,62548L,62549L,62550L,62551L,62552L,62553L,62554L,
96051 62555L,62556L,62557L,62558L,62559L,62560L,62561L,62562L,62563L,62564L,
96052 62565L,62566L,62567L,62568L,62569L,62570L,62571L,62572L,62573L,62574L,
96053 62575L,62576L,62577L,62578L,62579L,62580L,62581L,62582L,62583L,62584L,
96054 62585L,62586L,62587L,62588L,62589L,62590L,62591L,62592L,62593L,62594L,
96055 62595L,62596L,62597L,62598L,62599L,62600L,62601L,62602L,62603L,62604L,
96056 62605L,62606L,62607L,62608L,62609L,62610L,62611L,62612L,62613L,62614L,
96057 62615L,62616L,62617L,62618L,62619L,62620L,62621L,62622L,62623L,62624L,
96058 62625L,62626L,62627L,62628L,62629L,62630L,62631L,62632L,62633L,62634L,
96059 62635L,62636L,62637L,62638L,62639L,62640L,62641L,62642L,62643L,62644L,
96060 62645L,62646L,62647L,62648L,62649L,62650L,62651L,62652L,62653L,62654L,
96061 62655L,62656L,62657L,62658L,62659L,62660L,62661L,62662L,62663L,62664L,
96062 62665L,62666L,62667L,62668L,62669L,62670L,62671L,62672L,62673L,62674L,
96063 62675L,62676L,62677L,62678L,62679L,62680L,62681L,62682L,62683L,62684L,
96064 62685L,62686L,62687L,62688L,62689L,62690L,62691L,62692L,62693L,62694L,
96065 62695L,62696L,62697L,62698L,62699L,62700L,62701L,62702L,62703L,62704L,
96066 62705L,62706L,62707L,62708L,62709L,62710L,62711L,62712L,62713L,62714L,
96067 62715L,62716L,62717L,62718L,62719L,62720L,62721L,62722L,62723L,62724L,
96068 62725L,62726L,62727L,62728L,62729L,62730L,62731L,62732L,62733L,62734L,
96069 62735L,62736L,62737L,62738L,62739L,62740L,62741L,62742L,62743L,62744L,
96070 62745L,62746L,62747L,62748L,62749L,62750L,62751L,62752L,62753L,62754L,
96071 62755L,62756L,62757L,62758L,62759L,62760L,62761L,62762L,62763L,62764L,
96072 62765L,62766L,62767L,62768L,62769L,62770L,62771L,62772L,62773L,62774L,
96073 62775L,62776L,62777L,62778L,62779L,62780L,62781L,62782L,62783L,62784L,
96074 62785L,62786L,62787L,62788L,62789L,62790L,62791L,62792L,62793L,62794L,
96075 62795L,62796L,62797L,62798L,62799L,62800L,62801L,62802L,62803L,62804L,
96076 62805L,62806L,62807L,62808L,62809L,62810L,62811L,62812L,62813L,62814L,
96077 62815L,62816L,62817L,62818L,62819L,62820L,62821L,62822L,62823L,62824L,
96078 62825L,62826L,62827L,62828L,62829L,62830L,62831L,62832L,62833L,62834L,
96079 62835L,62836L,62837L,62838L,62839L,62840L,62841L,62842L,62843L,62844L,
96080 62845L,62846L,62847L,62848L,62849L,62850L,62851L,62852L,62853L,62854L,
96081 62855L,62856L,62857L,62858L,62859L,62860L,62861L,62862L,62863L,62864L,
96082 62865L,62866L,62867L,62868L,62869L,62870L,62871L,62872L,62873L,62874L,
96083 62875L,62876L,62877L,62878L,62879L,62880L,62881L,62882L,62883L,62884L,
96084 62885L,62886L,62887L,62888L,62889L,62890L,62891L,62892L,62893L,62894L,
96085 62895L,62896L,62897L,62898L,62899L,62900L,62901L,62902L,62903L,62904L,
96086 62905L,62906L,62907L,62908L,62909L,62910L,62911L,62912L,62913L,62914L,
96087 62915L,62916L,62917L,62918L,62919L,62920L,62921L,62922L,62923L,62924L,
96088 62925L,62926L,62927L,62928L,62929L,62930L,62931L,62932L,62933L,62934L,
96089 62935L,62936L,62937L,62938L,62939L,62940L,62941L,62942L,62943L,62944L,
96090 62945L,62946L,62947L,62948L,62949L,62950L,62951L,62952L,62953L,62954L,
96091 62955L,62956L,62957L,62958L,62959L,62960L,62961L,62962L,62963L,62964L,
96092 62965L,62966L,62967L,62968L,62969L,62970L,62971L,62972L,62973L,62974L,
96093 62975L,62976L,62977L,62978L,62979L,62980L,62981L,62982L,62983L,62984L,
96094 62985L,62986L,62987L,62988L,62989L,62990L,62991L,62992L,62993L,62994L,
96095 62995L,62996L,62997L,62998L,62999L,63000L,63001L,63002L,63003L,63004L,
96096 63005L,63006L,63007L,63008L,63009L,63010L,63011L,63012L,63013L,63014L,
96097 63015L,63016L,63017L,63018L,63019L,63020L,63021L,63022L,63023L,63024L,
96098 63025L,63026L,63027L,63028L,63029L,63030L,63031L,63032L,63033L,63034L,
96099 63035L,63036L,63037L,63038L,63039L,63040L,63041L,63042L,63043L,63044L,
96100 63045L,63046L,63047L,63048L,63049L,63050L,63051L,63052L,63053L,63054L,
96101 63055L,63056L,63057L,63058L,63059L,63060L,63061L,63062L,63063L,63064L,
96102 63065L,63066L,63067L,63068L,63069L,63070L,63071L,63072L,63073L,63074L,
96103 63075L,63076L,63077L,63078L,63079L,63080L,63081L,63082L,63083L,63084L,
96104 63085L,63086L,63087L,63088L,63089L,63090L,63091L,63092L,63093L,63094L,
96105 63095L,63096L,63097L,63098L,63099L,63100L,63101L,63102L,63103L,63104L,
96106 63105L,63106L,63107L,63108L,63109L,63110L,63111L,63112L,63113L,63114L,
96107 63115L,63116L,63117L,63118L,63119L,63120L,63121L,63122L,63123L,63124L,
96108 63125L,63126L,63127L,63128L,63129L,63130L,63131L,63132L,63133L,63134L,
96109 63135L,63136L,63137L,63138L,63139L,63140L,63141L,63142L,63143L,63144L,
96110 63145L,63146L,63147L,63148L,63149L,63150L,63151L,63152L,63153L,63154L,
96111 63155L,63156L,63157L,63158L,63159L,63160L,63161L,63162L,63163L,63164L,
96112 63165L,63166L,63167L,63168L,63169L,63170L,63171L,63172L,63173L,63174L,
96113 63175L,63176L,63177L,63178L,63179L,63180L,63181L,63182L,63183L,63184L,
96114 63185L,63186L,63187L,63188L,63189L,63190L,63191L,63192L,63193L,63194L,
96115 63195L,63196L,63197L,63198L,63199L,63200L,63201L,63202L,63203L,63204L,
96116 63205L,63206L,63207L,63208L,63209L,63210L,63211L,63212L,63213L,63214L,
96117 63215L,63216L,63217L,63218L,63219L,63220L,63221L,63222L,63223L,63224L,
96118 63225L,63226L,63227L,63228L,63229L,63230L,63231L,63232L,63233L,63234L,
96119 63235L,63236L,63237L,63238L,63239L,63240L,63241L,63242L,63243L,63244L,
96120 63245L,63246L,63247L,63248L,63249L,63250L,63251L,63252L,63253L,63254L,
96121 63255L,63256L,63257L,63258L,63259L,63260L,63261L,63262L,63263L,63264L,
96122 63265L,63266L,63267L,63268L,63269L,63270L,63271L,63272L,63273L,63274L,
96123 63275L,63276L,63277L,63278L,63279L,63280L,63281L,63282L,63283L,63284L,
96124 63285L,63286L,63287L,63288L,63289L,63290L,63291L,63292L,63293L,63294L,
96125 63295L,63296L,63297L,63298L,63299L,63300L,63301L,63302L,63303L,63304L,
96126 63305L,63306L,63307L,63308L,63309L,63310L,63311L,63312L,63313L,63314L,
96127 63315L,63316L,63317L,63318L,63319L,63320L,63321L,63322L,63323L,63324L,
96128 63325L,63326L,63327L,63328L,63329L,63330L,63331L,63332L,63333L,63334L,
96129 63335L,63336L,63337L,63338L,63339L,63340L,63341L,63342L,63343L,63344L,
96130 63345L,63346L,63347L,63348L,63349L,63350L,63351L,63352L,63353L,63354L,
96131 63355L,63356L,63357L,63358L,63359L,63360L,63361L,63362L,63363L,63364L,
96132 63365L,63366L,63367L,63368L,63369L,63370L,63371L,63372L,63373L,63374L,
96133 63375L,63376L,63377L,63378L,63379L,63380L,63381L,63382L,63383L,63384L,
96134 63385L,63386L,63387L,63388L,63389L,63390L,63391L,63392L,63393L,63394L,
96135 63395L,63396L,63397L,63398L,63399L,63400L,63401L,63402L,63403L,63404L,
96136 63405L,63406L,63407L,63408L,63409L,63410L,63411L,63412L,63413L,63414L,
96137 63415L,63416L,63417L,63418L,63419L,63420L,63421L,63422L,63423L,63424L,
96138 63425L,63426L,63427L,63428L,63429L,63430L,63431L,63432L,63433L,63434L,
96139 63435L,63436L,63437L,63438L,63439L,63440L,63441L,63442L,63443L,63444L,
96140 63445L,63446L,63447L,63448L,63449L,63450L,63451L,63452L,63453L,63454L,
96141 63455L,63456L,63457L,63458L,63459L,63460L,63461L,63462L,63463L,63464L,
96142 63465L,63466L,63467L,63468L,63469L,63470L,63471L,63472L,63473L,63474L,
96143 63475L,63476L,63477L,63478L,63479L,63480L,63481L,63482L,63483L,63484L,
96144 63485L,63486L,63487L,63488L,63489L,63490L,63491L,63492L,63493L,63494L,
96145 63495L,63496L,63497L,63498L,63499L,63500L,63501L,63502L,63503L,63504L,
96146 63505L,63506L,63507L,63508L,63509L,63510L,63511L,63512L,63513L,63514L,
96147 63515L,63516L,63517L,63518L,63519L,63520L,63521L,63522L,63523L,63524L,
96148 63525L,63526L,63527L,63528L,63529L,63530L,63531L,63532L,63533L,63534L,
96149 63535L,63536L,63537L,63538L,63539L,63540L,63541L,63542L,63543L,63544L,
96150 63545L,63546L,63547L,63548L,63549L,63550L,63551L,63552L,63553L,63554L,
96151 63555L,63556L,63557L,63558L,63559L,63560L,63561L,63562L,63563L,63564L,
96152 63565L,63566L,63567L,63568L,63569L,63570L,63571L,63572L,63573L,63574L,
96153 63575L,63576L,63577L,63578L,63579L,63580L,63581L,63582L,63583L,63584L,
96154 63585L,63586L,63587L,63588L,63589L,63590L,63591L,63592L,63593L,63594L,
96155 63595L,63596L,63597L,63598L,63599L,63600L,63601L,63602L,63603L,63604L,
96156 63605L,63606L,63607L,63608L,63609L,63610L,63611L,63612L,63613L,63614L,
96157 63615L,63616L,63617L,63618L,63619L,63620L,63621L,63622L,63623L,63624L,
96158 63625L,63626L,63627L,63628L,63629L,63630L,63631L,63632L,63633L,63634L,
96159 63635L,63636L,63637L,63638L,63639L,63640L,63641L,63642L,63643L,63644L,
96160 63645L,63646L,63647L,63648L,63649L,63650L,63651L,63652L,63653L,63654L,
96161 63655L,63656L,63657L,63658L,63659L,63660L,63661L,63662L,63663L,63664L,
96162 63665L,63666L,63667L,63668L,63669L,63670L,63671L,63672L,63673L,63674L,
96163 63675L,63676L,63677L,63678L,63679L,63680L,63681L,63682L,63683L,63684L,
96164 63685L,63686L,63687L,63688L,63689L,63690L,63691L,63692L,63693L,63694L,
96165 63695L,63696L,63697L,63698L,63699L,63700L,63701L,63702L,63703L,63704L,
96166 63705L,63706L,63707L,63708L,63709L,63710L,63711L,63712L,63713L,63714L,
96167 63715L,63716L,63717L,63718L,63719L,63720L,63721L,63722L,63723L,63724L,
96168 63725L,63726L,63727L,63728L,63729L,63730L,63731L,63732L,63733L,63734L,
96169 63735L,63736L,63737L,63738L,63739L,63740L,63741L,63742L,63743L,63744L,
96170 63745L,63746L,63747L,63748L,63749L,63750L,63751L,63752L,63753L,63754L,
96171 63755L,63756L,63757L,63758L,63759L,63760L,63761L,63762L,63763L,63764L,
96172 63765L,63766L,63767L,63768L,63769L,63770L,63771L,63772L,63773L,63774L,
96173 63775L,63776L,63777L,63778L,63779L,63780L,63781L,63782L,63783L,63784L,
96174 63785L,63786L,63787L,63788L,63789L,63790L,63791L,63792L,63793L,63794L,
96175 63795L,63796L,63797L,63798L,63799L,63800L,63801L,63802L,63803L,63804L,
96176 63805L,63806L,63807L,63808L,63809L,63810L,63811L,63812L,63813L,63814L,
96177 63815L,63816L,63817L,63818L,63819L,63820L,63821L,63822L,63823L,63824L,
96178 63825L,63826L,63827L,63828L,63829L,63830L,63831L,63832L,63833L,63834L,
96179 63835L,63836L,63837L,63838L,63839L,63840L,63841L,63842L,63843L,63844L,
96180 63845L,63846L,63847L,63848L,63849L,63850L,63851L,63852L,63853L,63854L,
96181 63855L,63856L,63857L,63858L,63859L,63860L,63861L,63862L,63863L,63864L,
96182 63865L,63866L,63867L,63868L,63869L,63870L,63871L,63872L,63873L,63874L,
96183 63875L,63876L,63877L,63878L,63879L,63880L,63881L,63882L,63883L,63884L,
96184 63885L,63886L,63887L,63888L,63889L,63890L,63891L,63892L,63893L,63894L,
96185 63895L,63896L,63897L,63898L,63899L,63900L,63901L,63902L,63903L,63904L,
96186 63905L,63906L,63907L,63908L,63909L,63910L,63911L,63912L,63913L,63914L,
96187 63915L,63916L,63917L,63918L,63919L,63920L,63921L,63922L,63923L,63924L,
96188 63925L,63926L,63927L,63928L,63929L,63930L,63931L,63932L,63933L,63934L,
96189 63935L,63936L,63937L,63938L,63939L,63940L,63941L,63942L,63943L,63944L,
96190 63945L,63946L,63947L,63948L,63949L,63950L,63951L,63952L,63953L,63954L,
96191 63955L,63956L,63957L,63958L,63959L,63960L,63961L,63962L,63963L,63964L,
96192 63965L,63966L,63967L,63968L,63969L,63970L,63971L,63972L,63973L,63974L,
96193 63975L,63976L,63977L,63978L,63979L,63980L,63981L,63982L,63983L,63984L,
96194 63985L,63986L,63987L,63988L,63989L,63990L,63991L,63992L,63993L,63994L,
96195 63995L,63996L,63997L,63998L,63999L,64000L,64001L,64002L,64003L,64004L,
96196 64005L,64006L,64007L,64008L,64009L,64010L,64011L,64012L,64013L,64014L,
96197 64015L,64016L,64017L,64018L,64019L,64020L,64021L,64022L,64023L,64024L,
96198 64025L,64026L,64027L,64028L,64029L,64030L,64031L,64032L,64033L,64034L,
96199 64035L,64036L,64037L,64038L,64039L,64040L,64041L,64042L,64043L,64044L,
96200 64045L,64046L,64047L,64048L,64049L,64050L,64051L,64052L,64053L,64054L,
96201 64055L,64056L,64057L,64058L,64059L,64060L,64061L,64062L,64063L,64064L,
96202 64065L,64066L,64067L,64068L,64069L,64070L,64071L,64072L,64073L,64074L,
96203 64075L,64076L,64077L,64078L,64079L,64080L,64081L,64082L,64083L,64084L,
96204 64085L,64086L,64087L,64088L,64089L,64090L,64091L,64092L,64093L,64094L,
96205 64095L,64096L,64097L,64098L,64099L,64100L,64101L,64102L,64103L,64104L,
96206 64105L,64106L,64107L,64108L,64109L,64110L,64111L,64112L,64113L,64114L,
96207 64115L,64116L,64117L,64118L,64119L,64120L,64121L,64122L,64123L,64124L,
96208 64125L,64126L,64127L,64128L,64129L,64130L,64131L,64132L,64133L,64134L,
96209 64135L,64136L,64137L,64138L,64139L,64140L,64141L,64142L,64143L,64144L,
96210 64145L,64146L,64147L,64148L,64149L,64150L,64151L,64152L,64153L,64154L,
96211 64155L,64156L,64157L,64158L,64159L,64160L,64161L,64162L,64163L,64164L,
96212 64165L,64166L,64167L,64168L,64169L,64170L,64171L,64172L,64173L,64174L,
96213 64175L,64176L,64177L,64178L,64179L,64180L,64181L,64182L,64183L,64184L,
96214 64185L,64186L,64187L,64188L,64189L,64190L,64191L,64192L,64193L,64194L,
96215 64195L,64196L,64197L,64198L,64199L,64200L,64201L,64202L,64203L,64204L,
96216 64205L,64206L,64207L,64208L,64209L,64210L,64211L,64212L,64213L,64214L,
96217 64215L,64216L,64217L,64218L,64219L,64220L,64221L,64222L,64223L,64224L,
96218 64225L,64226L,64227L,64228L,64229L,64230L,64231L,64232L,64233L,64234L,
96219 64235L,64236L,64237L,64238L,64239L,64240L,64241L,64242L,64243L,64244L,
96220 64245L,64246L,64247L,64248L,64249L,64250L,64251L,64252L,64253L,64254L,
96221 64255L,64256L,64257L,64258L,64259L,64260L,64261L,64262L,64263L,64264L,
96222 64265L,64266L,64267L,64268L,64269L,64270L,64271L,64272L,64273L,64274L,
96223 64275L,64276L,64277L,64278L,64279L,64280L,64281L,64282L,64283L,64284L,
96224 64285L,64286L,64287L,64288L,64289L,64290L,64291L,64292L,64293L,64294L,
96225 64295L,64296L,64297L,64298L,64299L,64300L,64301L,64302L,64303L,64304L,
96226 64305L,64306L,64307L,64308L,64309L,64310L,64311L,64312L,64313L,64314L,
96227 64315L,64316L,64317L,64318L,64319L,64320L,64321L,64322L,64323L,64324L,
96228 64325L,64326L,64327L,64328L,64329L,64330L,64331L,64332L,64333L,64334L,
96229 64335L,64336L,64337L,64338L,64339L,64340L,64341L,64342L,64343L,64344L,
96230 64345L,64346L,64347L,64348L,64349L,64350L,64351L,64352L,64353L,64354L,
96231 64355L,64356L,64357L,64358L,64359L,64360L,64361L,64362L,64363L,64364L,
96232 64365L,64366L,64367L,64368L,64369L,64370L,64371L,64372L,64373L,64374L,
96233 64375L,64376L,64377L,64378L,64379L,64380L,64381L,64382L,64383L,64384L,
96234 64385L,64386L,64387L,64388L,64389L,64390L,64391L,64392L,64393L,64394L,
96235 64395L,64396L,64397L,64398L,64399L,64400L,64401L,64402L,64403L,64404L,
96236 64405L,64406L,64407L,64408L,64409L,64410L,64411L,64412L,64413L,64414L,
96237 64415L,64416L,64417L,64418L,64419L,64420L,64421L,64422L,64423L,64424L,
96238 64425L,64426L,64427L,64428L,64429L,64430L,64431L,64432L,64433L,64434L,
96239 64435L,64436L,64437L,64438L,64439L,64440L,64441L,64442L,64443L,64444L,
96240 64445L,64446L,64447L,64448L,64449L,64450L,64451L,64452L,64453L,64454L,
96241 64455L,64456L,64457L,64458L,64459L,64460L,64461L,64462L,64463L,64464L,
96242 64465L,64466L,64467L,64468L,64469L,64470L,64471L,64472L,64473L,64474L,
96243 64475L,64476L,64477L,64478L,64479L,64480L,64481L,64482L,64483L,64484L,
96244 64485L,64486L,64487L,64488L,64489L,64490L,64491L,64492L,64493L,64494L,
96245 64495L,64496L,64497L,64498L,64499L,64500L,64501L,64502L,64503L,64504L,
96246 64505L,64506L,64507L,64508L,64509L,64510L,64511L,64512L,64513L,64514L,
96247 64515L,64516L,64517L,64518L,64519L,64520L,64521L,64522L,64523L,64524L,
96248 64525L,64526L,64527L,64528L,64529L,64530L,64531L,64532L,64533L,64534L,
96249 64535L,64536L,64537L,64538L,64539L,64540L,64541L,64542L,64543L,64544L,
96250 64545L,64546L,64547L,64548L,64549L,64550L,64551L,64552L,64553L,64554L,
96251 64555L,64556L,64557L,64558L,64559L,64560L,64561L,64562L,64563L,64564L,
96252 64565L,64566L,64567L,64568L,64569L,64570L,64571L,64572L,64573L,64574L,
96253 64575L,64576L,64577L,64578L,64579L,64580L,64581L,64582L,64583L,64584L,
96254 64585L,64586L,64587L,64588L,64589L,64590L,64591L,64592L,64593L,64594L,
96255 64595L,64596L,64597L,64598L,64599L,64600L,64601L,64602L,64603L,64604L,
96256 64605L,64606L,64607L,64608L,64609L,64610L,64611L,64612L,64613L,64614L,
96257 64615L,64616L,64617L,64618L,64619L,64620L,64621L,64622L,64623L,64624L,
96258 64625L,64626L,64627L,64628L,64629L,64630L,64631L,64632L,64633L,64634L,
96259 64635L,64636L,64637L,64638L,64639L,64640L,64641L,64642L,64643L,64644L,
96260 64645L,64646L,64647L,64648L,64649L,64650L,64651L,64652L,64653L,64654L,
96261 64655L,64656L,64657L,64658L,64659L,64660L,64661L,64662L,64663L,64664L,
96262 64665L,64666L,64667L,64668L,64669L,64670L,64671L,64672L,64673L,64674L,
96263 64675L,64676L,64677L,64678L,64679L,64680L,64681L,64682L,64683L,64684L,
96264 64685L,64686L,64687L,64688L,64689L,64690L,64691L,64692L,64693L,64694L,
96265 64695L,64696L,64697L,64698L,64699L,64700L,64701L,64702L,64703L,64704L,
96266 64705L,64706L,64707L,64708L,64709L,64710L,64711L,64712L,64713L,64714L,
96267 64715L,64716L,64717L,64718L,64719L,64720L,64721L,64722L,64723L,64724L,
96268 64725L,64726L,64727L,64728L,64729L,64730L,64731L,64732L,64733L,64734L,
96269 64735L,64736L,64737L,64738L,64739L,64740L,64741L,64742L,64743L,64744L,
96270 64745L,64746L,64747L,64748L,64749L,64750L,64751L,64752L,64753L,64754L,
96271 64755L,64756L,64757L,64758L,64759L,64760L,64761L,64762L,64763L,64764L,
96272 64765L,64766L,64767L,64768L,64769L,64770L,64771L,64772L,64773L,64774L,
96273 64775L,64776L,64777L,64778L,64779L,64780L,64781L,64782L,64783L,64784L,
96274 64785L,64786L,64787L,64788L,64789L,64790L,64791L,64792L,64793L,64794L,
96275 64795L,64796L,64797L,64798L,64799L,64800L,64801L,64802L,64803L,64804L,
96276 64805L,64806L,64807L,64808L,64809L,64810L,64811L,64812L,64813L,64814L,
96277 64815L,64816L,64817L,64818L,64819L,64820L,64821L,64822L,64823L,64824L,
96278 64825L,64826L,64827L,64828L,64829L,64830L,64831L,64832L,64833L,64834L,
96279 64835L,64836L,64837L,64838L,64839L,64840L,64841L,64842L,64843L,64844L,
96280 64845L,64846L,64847L,64848L,64849L,64850L,64851L,64852L,64853L,64854L,
96281 64855L,64856L,64857L,64858L,64859L,64860L,64861L,64862L,64863L,64864L,
96282 64865L,64866L,64867L,64868L,64869L,64870L,64871L,64872L,64873L,64874L,
96283 64875L,64876L,64877L,64878L,64879L,64880L,64881L,64882L,64883L,64884L,
96284 64885L,64886L,64887L,64888L,64889L,64890L,64891L,64892L,64893L,64894L,
96285 64895L,64896L,64897L,64898L,64899L,64900L,64901L,64902L,64903L,64904L,
96286 64905L,64906L,64907L,64908L,64909L,64910L,64911L,64912L,64913L,64914L,
96287 64915L,64916L,64917L,64918L,64919L,64920L,64921L,64922L,64923L,64924L,
96288 64925L,64926L,64927L,64928L,64929L,64930L,64931L,64932L,64933L,64934L,
96289 64935L,64936L,64937L,64938L,64939L,64940L,64941L,64942L,64943L,64944L,
96290 64945L,64946L,64947L,64948L,64949L,64950L,64951L,64952L,64953L,64954L,
96291 64955L,64956L,64957L,64958L,64959L,64960L,64961L,64962L,64963L,64964L,
96292 64965L,64966L,64967L,64968L,64969L,64970L,64971L,64972L,64973L,64974L,
96293 64975L,64976L,64977L,64978L,64979L,64980L,64981L,64982L,64983L,64984L,
96294 64985L,64986L,64987L,64988L,64989L,64990L,64991L,64992L,64993L,64994L,
96295 64995L,64996L,64997L,64998L,64999L,65000L,65001L,65002L,65003L,65004L,
96296 65005L,65006L,65007L,65008L,65009L,65010L,65011L,65012L,65013L,65014L,
96297 65015L,65016L,65017L,65018L,65019L,65020L,65021L,65022L,65023L,65024L,
96298 65025L,65026L,65027L,65028L,65029L,65030L,65031L,65032L,65033L,65034L,
96299 65035L,65036L,65037L,65038L,65039L,65040L,65041L,65042L,65043L,65044L,
96300 65045L,65046L,65047L,65048L,65049L,65050L,65051L,65052L,65053L,65054L,
96301 65055L,65056L,65057L,65058L,65059L,65060L,65061L,65062L,65063L,65064L,
96302 65065L,65066L,65067L,65068L,65069L,65070L,65071L,65072L,65073L,65074L,
96303 65075L,65076L,65077L,65078L,65079L,65080L,65081L,65082L,65083L,65084L,
96304 65085L,65086L,65087L,65088L,65089L,65090L,65091L,65092L,65093L,65094L,
96305 65095L,65096L,65097L,65098L,65099L,65100L,65101L,65102L,65103L,65104L,
96306 65105L,65106L,65107L,65108L,65109L,65110L,65111L,65112L,65113L,65114L,
96307 65115L,65116L,65117L,65118L,65119L,65120L,65121L,65122L,65123L,65124L,
96308 65125L,65126L,65127L,65128L,65129L,65130L,65131L,65132L,65133L,65134L,
96309 65135L,65136L,65137L,65138L,65139L,65140L,65141L,65142L,65143L,65144L,
96310 65145L,65146L,65147L,65148L,65149L,65150L,65151L,65152L,65153L,65154L,
96311 65155L,65156L,65157L,65158L,65159L,65160L,65161L,65162L,65163L,65164L,
96312 65165L,65166L,65167L,65168L,65169L,65170L,65171L,65172L,65173L,65174L,
96313 65175L,65176L,65177L,65178L,65179L,65180L,65181L,65182L,65183L,65184L,
96314 65185L,65186L,65187L,65188L,65189L,65190L,65191L,65192L,65193L,65194L,
96315 65195L,65196L,65197L,65198L,65199L,65200L,65201L,65202L,65203L,65204L,
96316 65205L,65206L,65207L,65208L,65209L,65210L,65211L,65212L,65213L,65214L,
96317 65215L,65216L,65217L,65218L,65219L,65220L,65221L,65222L,65223L,65224L,
96318 65225L,65226L,65227L,65228L,65229L,65230L,65231L,65232L,65233L,65234L,
96319 65235L,65236L,65237L,65238L,65239L,65240L,65241L,65242L,65243L,65244L,
96320 65245L,65246L,65247L,65248L,65249L,65250L,65251L,65252L,65253L,65254L,
96321 65255L,65256L,65257L,65258L,65259L,65260L,65261L,65262L,65263L,65264L,
96322 65265L,65266L,65267L,65268L,65269L,65270L,65271L,65272L,65273L,65274L,
96323 65275L,65276L,65277L,65278L,65279L,65280L,65281L,65282L,65283L,65284L,
96324 65285L,65286L,65287L,65288L,65289L,65290L,65291L,65292L,65293L,65294L,
96325 65295L,65296L,65297L,65298L,65299L,65300L,65301L,65302L,65303L,65304L,
96326 65305L,65306L,65307L,65308L,65309L,65310L,65311L,65312L,65313L,65314L,
96327 65315L,65316L,65317L,65318L,65319L,65320L,65321L,65322L,65323L,65324L,
96328 65325L,65326L,65327L,65328L,65329L,65330L,65331L,65332L,65333L,65334L,
96329 65335L,65336L,65337L,65338L,65339L,65340L,65341L,65342L,65343L,65344L,
96330 65313L,65314L,65315L,65316L,65317L,65318L,65319L,65320L,65321L,65322L,
96331 65323L,65324L,65325L,65326L,65327L,65328L,65329L,65330L,65331L,65332L,
96332 65333L,65334L,65335L,65336L,65337L,65338L,65371L,65372L,65373L,65374L,
96333 65375L,65376L,65377L,65378L,65379L,65380L,65381L,65382L,65383L,65384L,
96334 65385L,65386L,65387L,65388L,65389L,65390L,65391L,65392L,65393L,65394L,
96335 65395L,65396L,65397L,65398L,65399L,65400L,65401L,65402L,65403L,65404L,
96336 65405L,65406L,65407L,65408L,65409L,65410L,65411L,65412L,65413L,65414L,
96337 65415L,65416L,65417L,65418L,65419L,65420L,65421L,65422L,65423L,65424L,
96338 65425L,65426L,65427L,65428L,65429L,65430L,65431L,65432L,65433L,65434L,
96339 65435L,65436L,65437L,65438L,65439L,65440L,65441L,65442L,65443L,65444L,
96340 65445L,65446L,65447L,65448L,65449L,65450L,65451L,65452L,65453L,65454L,
96341 65455L,65456L,65457L,65458L,65459L,65460L,65461L,65462L,65463L,65464L,
96342 65465L,65466L,65467L,65468L,65469L,65470L,65471L,65472L,65473L,65474L,
96343 65475L,65476L,65477L,65478L,65479L,65480L,65481L,65482L,65483L,65484L,
96344 65485L,65486L,65487L,65488L,65489L,65490L,65491L,65492L,65493L,65494L,
96345 65495L,65496L,65497L,65498L,65499L,65500L,65501L,65502L,65503L,65504L,
96346 65505L,65506L,65507L,65508L,65509L,65510L,65511L,65512L,65513L,65514L,
96347 65515L,65516L,65517L,65518L,65519L,65520L,65521L,65522L,65523L,65524L,
96348 65525L,65526L,65527L,65528L,65529L,65530L,65531L,65532L,65533L,65534L,
96349 65535L,
96350 };
96351 #endif
96352 
96353 #if defined(DUK_USE_REGEXP_CANON_BITMAP)
96354 /*
96355  *  Automatically generated by extract_caseconv.py, do not edit!
96356  */
96357 
96358 const duk_uint8_t duk_unicode_re_canon_bitmap[256] = {
96359 23,0,224,19,1,228,255,255,255,255,255,255,255,255,255,255,63,254,255,127,
96360 255,255,255,255,255,255,255,255,231,231,0,16,255,227,255,255,63,255,255,
96361 255,255,255,255,255,1,252,255,255,255,255,255,255,255,255,255,255,255,255,
96362 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
96363 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
96364 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
96365 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
96366 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
96367 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
96368 227,129,255,255,255,147,255,255,255,255,255,255,255,255,255,255,255,255,
96369 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
96370 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
96371 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
96372 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,251,
96373 };
96374 #endif
96375 /*
96376  *  Bitstream decoder.
96377  */
96378 
96379 /* #include duk_internal.h -> already included */
96380 
96381 /* Decode 'bits' bits from the input stream (bits must be 1...24).
96382  * When reading past bitstream end, zeroes are shifted in.  The result
96383  * is signed to match duk_bd_decode_flagged.
96384  */
96385 DUK_INTERNAL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits) {
96386 	duk_small_int_t shift;
96387 	duk_uint32_t mask;
96388 	duk_uint32_t tmp;
96389 
96390 	/* Note: cannot read more than 24 bits without possibly shifting top bits out.
96391 	 * Fixable, but adds complexity.
96392 	 */
96393 	DUK_ASSERT(bits >= 1 && bits <= 24);
96394 
96395 	while (ctx->currbits < bits) {
96396 #if 0
96397 		DUK_DDD(DUK_DDDPRINT("decode_bits: shift more data (bits=%ld, currbits=%ld)",
96398 		                     (long) bits, (long) ctx->currbits));
96399 #endif
96400 		ctx->currval <<= 8;
96401 		if (ctx->offset < ctx->length) {
96402 			/* If ctx->offset >= ctx->length, we "shift zeroes in"
96403 			 * instead of croaking.
96404 			 */
96405 			ctx->currval |= ctx->data[ctx->offset++];
96406 		}
96407 		ctx->currbits += 8;
96408 	}
96409 #if 0
96410 	DUK_DDD(DUK_DDDPRINT("decode_bits: bits=%ld, currbits=%ld, currval=0x%08lx",
96411 	                     (long) bits, (long) ctx->currbits, (unsigned long) ctx->currval));
96412 #endif
96413 
96414 	/* Extract 'top' bits of currval; note that the extracted bits do not need
96415 	 * to be cleared, we just ignore them on next round.
96416 	 */
96417 	shift = ctx->currbits - bits;
96418 	mask = (((duk_uint32_t) 1U) << bits) - 1U;
96419 	tmp = (ctx->currval >> shift) & mask;
96420 	ctx->currbits = shift;  /* remaining */
96421 
96422 #if 0
96423 	DUK_DDD(DUK_DDDPRINT("decode_bits: %ld bits -> 0x%08lx (%ld), currbits=%ld, currval=0x%08lx",
96424 	                     (long) bits, (unsigned long) tmp, (long) tmp, (long) ctx->currbits, (unsigned long) ctx->currval));
96425 #endif
96426 
96427 	return tmp;
96428 }
96429 
96430 DUK_INTERNAL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx) {
96431 	return (duk_small_uint_t) duk_bd_decode(ctx, 1);
96432 }
96433 
96434 /* Decode a one-bit flag, and if set, decode a value of 'bits', otherwise return
96435  * default value.
96436  */
96437 DUK_INTERNAL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value) {
96438 	if (duk_bd_decode_flag(ctx)) {
96439 		return duk_bd_decode(ctx, bits);
96440 	} else {
96441 		return def_value;
96442 	}
96443 }
96444 
96445 /* Signed variant, allows negative marker value. */
96446 DUK_INTERNAL duk_int32_t duk_bd_decode_flagged_signed(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value) {
96447 	return (duk_int32_t) duk_bd_decode_flagged(ctx, bits, (duk_uint32_t) def_value);
96448 }
96449 
96450 /* Shared varint encoding.  Match dukutil.py BitEncode.varuint(). */
96451 DUK_INTERNAL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx) {
96452 	duk_small_uint_t t;
96453 
96454 	/* The bit encoding choices here are based on manual testing against
96455 	 * the actual varuints generated by genbuiltins.py.
96456 	 */
96457 	switch (duk_bd_decode(ctx, 2)) {
96458 	case 0:
96459 		return 0;  /* [0,0] */
96460 	case 1:
96461 		return duk_bd_decode(ctx, 2) + 1;  /* [1,4] */
96462 	case 2:
96463 		return duk_bd_decode(ctx, 5) + 5;  /* [5,36] */
96464 	default:
96465 		t = duk_bd_decode(ctx, 7);
96466 		if (t == 0) {
96467 			return duk_bd_decode(ctx, 20);
96468 		}
96469 		return (t - 1) + 37;  /* [37,163] */
96470 	}
96471 }
96472 
96473 /* Decode a bit packed string from a custom format used by genbuiltins.py.
96474  * This function is here because it's used for both heap and thread inits.
96475  * Caller must supply the output buffer whose size is NOT checked!
96476  */
96477 
96478 #define DUK__BITPACK_LETTER_LIMIT  26
96479 #define DUK__BITPACK_LOOKUP1       26
96480 #define DUK__BITPACK_LOOKUP2       27
96481 #define DUK__BITPACK_SWITCH1       28
96482 #define DUK__BITPACK_SWITCH        29
96483 #define DUK__BITPACK_UNUSED1       30
96484 #define DUK__BITPACK_EIGHTBIT      31
96485 
96486 DUK_LOCAL const duk_uint8_t duk__bitpacked_lookup[16] = {
96487 	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
96488 	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
96489 	DUK_ASC_8, DUK_ASC_9, DUK_ASC_UNDERSCORE, DUK_ASC_SPACE,
96490 	0x82, 0x80, DUK_ASC_DOUBLEQUOTE, DUK_ASC_LCURLY
96491 };
96492 
96493 DUK_INTERNAL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out) {
96494 	duk_small_uint_t len;
96495 	duk_small_uint_t mode;
96496 	duk_small_uint_t t;
96497 	duk_small_uint_t i;
96498 
96499 	len = duk_bd_decode(bd, 5);
96500 	if (len == 31) {
96501 		len = duk_bd_decode(bd, 8);  /* Support up to 256 bytes; rare. */
96502 	}
96503 
96504 	mode = 32;  /* 0 = uppercase, 32 = lowercase (= 'a' - 'A') */
96505 	for (i = 0; i < len; i++) {
96506 		t = duk_bd_decode(bd, 5);
96507 		if (t < DUK__BITPACK_LETTER_LIMIT) {
96508 			t = t + DUK_ASC_UC_A + mode;
96509 		} else if (t == DUK__BITPACK_LOOKUP1) {
96510 			t = duk__bitpacked_lookup[duk_bd_decode(bd, 3)];
96511 		} else if (t == DUK__BITPACK_LOOKUP2) {
96512 			t = duk__bitpacked_lookup[8 + duk_bd_decode(bd, 3)];
96513 		} else if (t == DUK__BITPACK_SWITCH1) {
96514 			t = duk_bd_decode(bd, 5);
96515 			DUK_ASSERT_DISABLE(t >= 0);  /* unsigned */
96516 			DUK_ASSERT(t <= 25);
96517 			t = t + DUK_ASC_UC_A + (mode ^ 32);
96518 		} else if (t == DUK__BITPACK_SWITCH) {
96519 			mode = mode ^ 32;
96520 			t = duk_bd_decode(bd, 5);
96521 			DUK_ASSERT_DISABLE(t >= 0);
96522 			DUK_ASSERT(t <= 25);
96523 			t = t + DUK_ASC_UC_A + mode;
96524 		} else if (t == DUK__BITPACK_EIGHTBIT) {
96525 			t = duk_bd_decode(bd, 8);
96526 		}
96527 		out[i] = (duk_uint8_t) t;
96528 	}
96529 
96530 	return len;
96531 }
96532 
96533 /* automatic undefs */
96534 #undef DUK__BITPACK_EIGHTBIT
96535 #undef DUK__BITPACK_LETTER_LIMIT
96536 #undef DUK__BITPACK_LOOKUP1
96537 #undef DUK__BITPACK_LOOKUP2
96538 #undef DUK__BITPACK_SWITCH
96539 #undef DUK__BITPACK_SWITCH1
96540 #undef DUK__BITPACK_UNUSED1
96541 /*
96542  *  Bitstream encoder.
96543  */
96544 
96545 /* #include duk_internal.h -> already included */
96546 
96547 DUK_INTERNAL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits) {
96548 	duk_uint8_t tmp;
96549 
96550 	DUK_ASSERT(ctx != NULL);
96551 	DUK_ASSERT(ctx->currbits < 8);
96552 
96553 	/* This limitation would be fixable but adds unnecessary complexity. */
96554 	DUK_ASSERT(bits >= 1 && bits <= 24);
96555 
96556 	ctx->currval = (ctx->currval << bits) | data;
96557 	ctx->currbits += bits;
96558 
96559 	while (ctx->currbits >= 8) {
96560 		if (ctx->offset < ctx->length) {
96561 			tmp = (duk_uint8_t) ((ctx->currval >> (ctx->currbits - 8)) & 0xff);
96562 			ctx->data[ctx->offset++] = tmp;
96563 		} else {
96564 			/* If buffer has been exhausted, truncate bitstream */
96565 			ctx->truncated = 1;
96566 		}
96567 
96568 		ctx->currbits -= 8;
96569 	}
96570 }
96571 
96572 DUK_INTERNAL void duk_be_finish(duk_bitencoder_ctx *ctx) {
96573 	duk_small_int_t npad;
96574 
96575 	DUK_ASSERT(ctx != NULL);
96576 	DUK_ASSERT(ctx->currbits < 8);
96577 
96578 	npad = (duk_small_int_t) (8 - ctx->currbits);
96579 	if (npad > 0) {
96580 		duk_be_encode(ctx, 0, npad);
96581 	}
96582 	DUK_ASSERT(ctx->currbits == 0);
96583 }
96584 /*
96585  *  Fast buffer writer with slack management.
96586  */
96587 
96588 /* #include duk_internal.h -> already included */
96589 
96590 /* XXX: Avoid duk_{memcmp,memmove}_unsafe() by imposing a minimum length of
96591  * >0 for the underlying dynamic buffer.
96592  */
96593 
96594 /*
96595  *  Macro support functions (use only macros in calling code)
96596  */
96597 
96598 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) {
96599 	duk_uint8_t *p;
96600 
96601 	DUK_ASSERT(thr != NULL);
96602 	DUK_ASSERT(bw_ctx != NULL);
96603 	DUK_UNREF(thr);
96604 
96605 	/* 'p' might be NULL when the underlying buffer is zero size.  If so,
96606 	 * the resulting pointers are not used unsafely.
96607 	 */
96608 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, bw_ctx->buf);
96609 	DUK_ASSERT(p != NULL || (DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0 && curr_offset == 0 && new_length == 0));
96610 	bw_ctx->p = p + curr_offset;
96611 	bw_ctx->p_base = p;
96612 	bw_ctx->p_limit = p + new_length;
96613 }
96614 
96615 DUK_INTERNAL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf) {
96616 	DUK_ASSERT(thr != NULL);
96617 	DUK_ASSERT(bw_ctx != NULL);
96618 	DUK_ASSERT(h_buf != NULL);
96619 
96620 	bw_ctx->buf = h_buf;
96621 	duk__bw_update_ptrs(thr, bw_ctx, 0, DUK_HBUFFER_DYNAMIC_GET_SIZE(h_buf));
96622 }
96623 
96624 DUK_INTERNAL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size) {
96625 	DUK_ASSERT(thr != NULL);
96626 	DUK_ASSERT(bw_ctx != NULL);
96627 
96628 	(void) duk_push_dynamic_buffer(thr, buf_size);
96629 	bw_ctx->buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, -1);
96630 	DUK_ASSERT(bw_ctx->buf != NULL);
96631 	duk__bw_update_ptrs(thr, bw_ctx, 0, buf_size);
96632 }
96633 
96634 /* Resize target buffer for requested size.  Called by the macro only when the
96635  * fast path test (= there is space) fails.
96636  */
96637 DUK_INTERNAL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz) {
96638 	duk_size_t curr_off;
96639 	duk_size_t add_sz;
96640 	duk_size_t new_sz;
96641 
96642 	DUK_ASSERT(thr != NULL);
96643 	DUK_ASSERT(bw_ctx != NULL);
96644 
96645 	/* We could do this operation without caller updating bw_ctx->ptr,
96646 	 * but by writing it back here we can share code better.
96647 	 */
96648 
96649 	curr_off = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
96650 	add_sz = (curr_off >> DUK_BW_SLACK_SHIFT) + DUK_BW_SLACK_ADD;
96651 	new_sz = curr_off + sz + add_sz;
96652 	if (DUK_UNLIKELY(new_sz < curr_off)) {
96653 		/* overflow */
96654 		DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
96655 		DUK_WO_NORETURN(return NULL;);
96656 	}
96657 #if 0  /* for manual torture testing: tight allocation, useful with valgrind */
96658 	new_sz = curr_off + sz;
96659 #endif
96660 
96661 	/* This is important to ensure dynamic buffer data pointer is not
96662 	 * NULL (which is possible if buffer size is zero), which in turn
96663 	 * causes portability issues with e.g. memmove() and memcpy().
96664 	 */
96665 	DUK_ASSERT(new_sz >= 1);
96666 
96667 	DUK_DD(DUK_DDPRINT("resize bufferwriter from %ld to %ld (add_sz=%ld)", (long) curr_off, (long) new_sz, (long) add_sz));
96668 
96669 	duk_hbuffer_resize(thr, bw_ctx->buf, new_sz);
96670 	duk__bw_update_ptrs(thr, bw_ctx, curr_off, new_sz);
96671 	return bw_ctx->p;
96672 }
96673 
96674 /* Make buffer compact, matching current written size. */
96675 DUK_INTERNAL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx) {
96676 	duk_size_t len;
96677 
96678 	DUK_ASSERT(thr != NULL);
96679 	DUK_ASSERT(bw_ctx != NULL);
96680 	DUK_UNREF(thr);
96681 
96682 	len = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
96683 	duk_hbuffer_resize(thr, bw_ctx->buf, len);
96684 	duk__bw_update_ptrs(thr, bw_ctx, len, len);
96685 }
96686 
96687 DUK_INTERNAL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {
96688 	duk_uint8_t *p_base;
96689 
96690 	DUK_ASSERT(thr != NULL);
96691 	DUK_ASSERT(bw != NULL);
96692 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
96693 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
96694 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
96695 	DUK_UNREF(thr);
96696 
96697 	p_base = bw->p_base;
96698 	duk_memcpy_unsafe((void *) bw->p,
96699 	                  (const void *) (p_base + src_off),
96700 	                  (size_t) len);
96701 	bw->p += len;
96702 }
96703 
96704 DUK_INTERNAL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {
96705 	DUK_ASSERT(thr != NULL);
96706 	DUK_ASSERT(bw != NULL);
96707 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
96708 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
96709 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
96710 
96711 	DUK_BW_ENSURE(thr, bw, len);
96712 	duk_bw_write_raw_slice(thr, bw, src_off, len);
96713 }
96714 
96715 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) {
96716 	duk_uint8_t *p_base;
96717 	duk_size_t buf_sz, move_sz;
96718 
96719 	DUK_ASSERT(thr != NULL);
96720 	DUK_ASSERT(bw != NULL);
96721 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
96722 	DUK_ASSERT(buf != NULL);
96723 	DUK_UNREF(thr);
96724 
96725 	p_base = bw->p_base;
96726 	buf_sz = (duk_size_t) (bw->p - p_base);  /* constrained by maximum buffer size */
96727 	move_sz = buf_sz - dst_off;
96728 
96729 	DUK_ASSERT(p_base != NULL);  /* buffer size is >= 1 */
96730 	duk_memmove_unsafe((void *) (p_base + dst_off + len),
96731 	                   (const void *) (p_base + dst_off),
96732 	                   (size_t) move_sz);
96733 	duk_memcpy_unsafe((void *) (p_base + dst_off),
96734 	                  (const void *) buf,
96735 	                  (size_t) len);
96736 	bw->p += len;
96737 }
96738 
96739 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) {
96740 	DUK_ASSERT(thr != NULL);
96741 	DUK_ASSERT(bw != NULL);
96742 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
96743 	DUK_ASSERT(buf != NULL);
96744 
96745 	DUK_BW_ENSURE(thr, bw, len);
96746 	duk_bw_insert_raw_bytes(thr, bw, dst_off, buf, len);
96747 }
96748 
96749 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) {
96750 	duk_uint8_t *p_base;
96751 	duk_size_t buf_sz, move_sz;
96752 
96753 	DUK_ASSERT(thr != NULL);
96754 	DUK_ASSERT(bw != NULL);
96755 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
96756 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
96757 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
96758 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
96759 	DUK_UNREF(thr);
96760 
96761 	p_base = bw->p_base;
96762 
96763 	/* Don't support "straddled" source now. */
96764 	DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
96765 
96766 	if (dst_off <= src_off) {
96767 		/* Target is before source.  Source offset is expressed as
96768 		 * a "before change" offset.  Account for the memmove.
96769 		 */
96770 		src_off += len;
96771 	}
96772 
96773 	buf_sz = (duk_size_t) (bw->p - p_base);
96774 	move_sz = buf_sz - dst_off;
96775 
96776 	DUK_ASSERT(p_base != NULL);  /* buffer size is >= 1 */
96777 	duk_memmove_unsafe((void *) (p_base + dst_off + len),
96778 	                   (const void *) (p_base + dst_off),
96779 	                   (size_t) move_sz);
96780 	duk_memcpy_unsafe((void *) (p_base + dst_off),
96781 	                  (const void *) (p_base + src_off),
96782 	                  (size_t) len);
96783 	bw->p += len;
96784 }
96785 
96786 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) {
96787 	DUK_ASSERT(thr != NULL);
96788 	DUK_ASSERT(bw != NULL);
96789 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
96790 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
96791 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
96792 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
96793 
96794 	/* Don't support "straddled" source now. */
96795 	DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
96796 
96797 	DUK_BW_ENSURE(thr, bw, len);
96798 	duk_bw_insert_raw_slice(thr, bw, dst_off, src_off, len);
96799 }
96800 
96801 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) {
96802 	duk_uint8_t *p_base, *p_dst, *p_src;
96803 	duk_size_t buf_sz, move_sz;
96804 
96805 	DUK_ASSERT(thr != NULL);
96806 	DUK_ASSERT(bw != NULL);
96807 	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
96808 	DUK_UNREF(thr);
96809 
96810 	p_base = bw->p_base;
96811 	buf_sz = (duk_size_t) (bw->p - p_base);
96812 	move_sz = buf_sz - off;
96813 	p_dst = p_base + off + len;
96814 	p_src = p_base + off;
96815 	duk_memmove_unsafe((void *) p_dst, (const void *) p_src, (size_t) move_sz);
96816 	return p_src;  /* point to start of 'reserved area' */
96817 }
96818 
96819 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) {
96820 	DUK_ASSERT(thr != NULL);
96821 	DUK_ASSERT(bw != NULL);
96822 	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
96823 
96824 	DUK_BW_ENSURE(thr, bw, len);
96825 	return duk_bw_insert_raw_area(thr, bw, off, len);
96826 }
96827 
96828 DUK_INTERNAL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {
96829 	duk_size_t move_sz;
96830 
96831 	duk_uint8_t *p_base;
96832 	duk_uint8_t *p_src;
96833 	duk_uint8_t *p_dst;
96834 
96835 	DUK_ASSERT(thr != NULL);
96836 	DUK_ASSERT(bw != NULL);
96837 	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
96838 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
96839 	DUK_ASSERT(off + len <= DUK_BW_GET_SIZE(thr, bw));
96840 	DUK_UNREF(thr);
96841 
96842 	p_base = bw->p_base;
96843 	p_dst = p_base + off;
96844 	p_src = p_dst + len;
96845 	move_sz = (duk_size_t) (bw->p - p_src);
96846 	duk_memmove_unsafe((void *) p_dst,
96847 	                   (const void *) p_src,
96848 	                   (size_t) move_sz);
96849 	bw->p -= len;
96850 }
96851 
96852 /*
96853  *  Macro support functions for reading/writing raw data.
96854  *
96855  *  These are done using mempcy to ensure they're valid even for unaligned
96856  *  reads/writes on platforms where alignment counts.  On x86 at least gcc
96857  *  is able to compile these into a bswap+mov.  "Always inline" is used to
96858  *  ensure these macros compile to minimal code.
96859  *
96860  *  Not really bufwriter related, but currently used together.
96861  */
96862 
96863 DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p) {
96864 	union {
96865 		duk_uint8_t b[2];
96866 		duk_uint16_t x;
96867 	} u;
96868 
96869 	duk_memcpy((void *) u.b, (const void *) (*p), (size_t) 2);
96870 	u.x = DUK_NTOH16(u.x);
96871 	*p += 2;
96872 	return u.x;
96873 }
96874 
96875 DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p) {
96876 	union {
96877 		duk_uint8_t b[4];
96878 		duk_uint32_t x;
96879 	} u;
96880 
96881 	duk_memcpy((void *) u.b, (const void *) (*p), (size_t) 4);
96882 	u.x = DUK_NTOH32(u.x);
96883 	*p += 4;
96884 	return u.x;
96885 }
96886 
96887 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_read_double_be(duk_uint8_t **p) {
96888 	duk_double_union du;
96889 	union {
96890 		duk_uint8_t b[4];
96891 		duk_uint32_t x;
96892 	} u;
96893 
96894 	duk_memcpy((void *) u.b, (const void *) (*p), (size_t) 4);
96895 	u.x = DUK_NTOH32(u.x);
96896 	du.ui[DUK_DBL_IDX_UI0] = u.x;
96897 	duk_memcpy((void *) u.b, (const void *) (*p + 4), (size_t) 4);
96898 	u.x = DUK_NTOH32(u.x);
96899 	du.ui[DUK_DBL_IDX_UI1] = u.x;
96900 	*p += 8;
96901 
96902 	return du.d;
96903 }
96904 
96905 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val) {
96906 	union {
96907 		duk_uint8_t b[2];
96908 		duk_uint16_t x;
96909 	} u;
96910 
96911 	u.x = DUK_HTON16(val);
96912 	duk_memcpy((void *) (*p), (const void *) u.b, (size_t) 2);
96913 	*p += 2;
96914 }
96915 
96916 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val) {
96917 	union {
96918 		duk_uint8_t b[4];
96919 		duk_uint32_t x;
96920 	} u;
96921 
96922 	u.x = DUK_HTON32(val);
96923 	duk_memcpy((void *) (*p), (const void *) u.b, (size_t) 4);
96924 	*p += 4;
96925 }
96926 
96927 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val) {
96928 	duk_double_union du;
96929 	union {
96930 		duk_uint8_t b[4];
96931 		duk_uint32_t x;
96932 	} u;
96933 
96934 	du.d = val;
96935 	u.x = du.ui[DUK_DBL_IDX_UI0];
96936 	u.x = DUK_HTON32(u.x);
96937 	duk_memcpy((void *) (*p), (const void *) u.b, (size_t) 4);
96938 	u.x = du.ui[DUK_DBL_IDX_UI1];
96939 	u.x = DUK_HTON32(u.x);
96940 	duk_memcpy((void *) (*p + 4), (const void *) u.b, (size_t) 4);
96941 	*p += 8;
96942 }
96943 
96944 /*
96945  *  Assertion helpers
96946  */
96947 
96948 #if defined(DUK_USE_ASSERTIONS)
96949 DUK_INTERNAL void duk_bw_assert_valid(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx) {
96950 	DUK_UNREF(thr);
96951 	DUK_ASSERT(bw_ctx != NULL);
96952 	DUK_ASSERT(bw_ctx->buf != NULL);
96953 	DUK_ASSERT((DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0) ||
96954 	           (bw_ctx->p != NULL &&
96955 	            bw_ctx->p_base != NULL &&
96956 	            bw_ctx->p_limit != NULL &&
96957 	            bw_ctx->p_limit >= bw_ctx->p_base &&
96958 	            bw_ctx->p >= bw_ctx->p_base &&
96959 	            bw_ctx->p <= bw_ctx->p_limit));
96960 }
96961 #endif
96962 /*
96963  *  Cast helpers.
96964  *
96965  *  C99+ coercion is challenging portability-wise because out-of-range casts
96966  *  may invoke implementation defined or even undefined behavior.  See e.g.
96967  *  http://blog.frama-c.com/index.php?post/2013/10/09/Overflow-float-integer.
96968  *
96969  *  Provide explicit cast helpers which try to avoid implementation defined
96970  *  or undefined behavior.  These helpers can then be simplified in the vast
96971  *  majority of cases where the implementation defined or undefined behavior
96972  *  is not problematic.
96973  */
96974 
96975 /* #include duk_internal.h -> already included */
96976 
96977 /* Portable double-to-integer cast which avoids undefined behavior and avoids
96978  * relying on fmin(), fmax(), or other intrinsics.  Out-of-range results are
96979  * not assumed by caller, but here value is clamped, NaN converts to minval.
96980  */
96981 #define DUK__DOUBLE_INT_CAST1(tname,minval,maxval)  do { \
96982 		if (DUK_LIKELY(x >= (duk_double_t) (minval))) { \
96983 			DUK_ASSERT(!DUK_ISNAN(x)); \
96984 			if (DUK_LIKELY(x <= (duk_double_t) (maxval))) { \
96985 				return (tname) x; \
96986 			} else { \
96987 				return (tname) (maxval); \
96988 			} \
96989 		} else { \
96990 			/* NaN or below minval.  Since we don't care about the result \
96991 			 * for out-of-range values, just return the minimum value for \
96992 			 * both. \
96993 			 */ \
96994 			return (tname) (minval); \
96995 		} \
96996 	} while (0)
96997 
96998 /* Rely on specific NaN behavior for duk_double_{fmin,fmax}(): if either
96999  * argument is a NaN, return the second argument.  This avoids a
97000  * NaN-to-integer cast which is undefined behavior.
97001  */
97002 #define DUK__DOUBLE_INT_CAST2(tname,minval,maxval)  do { \
97003 		return (tname) duk_double_fmin(duk_double_fmax(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
97004 	} while (0)
97005 
97006 /* Another solution which doesn't need C99+ behavior for fmin() and fmax(). */
97007 #define DUK__DOUBLE_INT_CAST3(tname,minval,maxval)  do { \
97008 		if (DUK_ISNAN(x)) { \
97009 			/* 0 or any other value is fine. */ \
97010 			return (tname) 0; \
97011 		} else \
97012 			return (tname) DUK_FMIN(DUK_FMAX(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
97013 		} \
97014 	} while (0)
97015 
97016 /* C99+ solution: relies on specific fmin() and fmax() behavior in C99: if
97017  * one argument is NaN but the other isn't, the non-NaN argument is returned.
97018  * Because the limits are non-NaN values, explicit NaN check is not needed.
97019  * This may not work on all legacy platforms, and also doesn't seem to inline
97020  * the fmin() and fmax() calls (unless one uses -ffast-math which we don't
97021  * support).
97022  */
97023 #define DUK__DOUBLE_INT_CAST4(tname,minval,maxval)  do { \
97024 		return (tname) DUK_FMIN(DUK_FMAX(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
97025 	} while (0)
97026 
97027 DUK_INTERNAL duk_int_t duk_double_to_int_t(duk_double_t x) {
97028 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
97029 	/* Real world solution: almost any practical platform will provide
97030 	 * an integer value without any guarantees what it is (which is fine).
97031 	 */
97032 	return (duk_int_t) x;
97033 #else
97034 	DUK__DOUBLE_INT_CAST1(duk_int_t, DUK_INT_MIN, DUK_INT_MAX);
97035 #endif
97036 }
97037 
97038 DUK_INTERNAL duk_uint_t duk_double_to_uint_t(duk_double_t x) {
97039 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
97040 	return (duk_uint_t) x;
97041 #else
97042 	DUK__DOUBLE_INT_CAST1(duk_uint_t, DUK_UINT_MIN, DUK_UINT_MAX);
97043 #endif
97044 }
97045 
97046 DUK_INTERNAL duk_int32_t duk_double_to_int32_t(duk_double_t x) {
97047 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
97048 	return (duk_int32_t) x;
97049 #else
97050 	DUK__DOUBLE_INT_CAST1(duk_int32_t, DUK_INT32_MIN, DUK_INT32_MAX);
97051 #endif
97052 }
97053 
97054 DUK_INTERNAL duk_uint32_t duk_double_to_uint32_t(duk_double_t x) {
97055 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
97056 	return (duk_uint32_t) x;
97057 #else
97058 	DUK__DOUBLE_INT_CAST1(duk_uint32_t, DUK_UINT32_MIN, DUK_UINT32_MAX);
97059 #endif
97060 }
97061 
97062 /* Largest IEEE double that doesn't round to infinity in the default rounding
97063  * mode.  The exact midpoint between (1 - 2^(-24)) * 2^128 and 2^128 rounds to
97064  * infinity, at least on x64.  This number is one double unit below that
97065  * midpoint.  See misc/float_cast.c.
97066  */
97067 #define DUK__FLOAT_ROUND_LIMIT      340282356779733623858607532500980858880.0
97068 
97069 /* Maximum IEEE float.  Double-to-float conversion above this would be out of
97070  * range and thus technically undefined behavior.
97071  */
97072 #define DUK__FLOAT_MAX              340282346638528859811704183484516925440.0
97073 
97074 DUK_INTERNAL duk_float_t duk_double_to_float_t(duk_double_t x) {
97075 	/* Even a double-to-float cast is technically undefined behavior if
97076 	 * the double is out-of-range.  C99 Section 6.3.1.5:
97077 	 *
97078 	 *   If the value being converted is in the range of values that can
97079 	 *   be represented but cannot be represented exactly, the result is
97080 	 *   either the nearest higher or nearest lower representable value,
97081 	 *   chosen in an implementation-defined manner.  If the value being
97082 	 *   converted is outside the range of values that can be represented,
97083 	 *   the behavior is undefined.
97084 	 */
97085 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
97086 	return (duk_float_t) x;
97087 #else
97088 	duk_double_t t;
97089 
97090 	t = DUK_FABS(x);
97091 	DUK_ASSERT((DUK_ISNAN(x) && DUK_ISNAN(t)) ||
97092 	           (!DUK_ISNAN(x) && !DUK_ISNAN(t)));
97093 
97094 	if (DUK_LIKELY(t <= DUK__FLOAT_MAX)) {
97095 		/* Standard in-range case, try to get here with a minimum
97096 		 * number of checks and branches.
97097 		 */
97098 		DUK_ASSERT(!DUK_ISNAN(x));
97099 		return (duk_float_t) x;
97100 	} else if (t <= DUK__FLOAT_ROUND_LIMIT) {
97101 		/* Out-of-range, but rounds to min/max float. */
97102 		DUK_ASSERT(!DUK_ISNAN(x));
97103 		if (x < 0.0) {
97104 			return (duk_float_t) -DUK__FLOAT_MAX;
97105 		} else {
97106 			return (duk_float_t) DUK__FLOAT_MAX;
97107 		}
97108 	} else if (DUK_ISNAN(x)) {
97109 		/* Assumes double NaN -> float NaN considered "in range". */
97110 		DUK_ASSERT(DUK_ISNAN(x));
97111 		return (duk_float_t) x;
97112 	} else {
97113 		/* Out-of-range, rounds to +/- Infinity. */
97114 		if (x < 0.0) {
97115 			return (duk_float_t) -DUK_DOUBLE_INFINITY;
97116 		} else {
97117 			return (duk_float_t) DUK_DOUBLE_INFINITY;
97118 		}
97119 	}
97120 #endif
97121 }
97122 
97123 /* automatic undefs */
97124 #undef DUK__DOUBLE_INT_CAST1
97125 #undef DUK__DOUBLE_INT_CAST2
97126 #undef DUK__DOUBLE_INT_CAST3
97127 #undef DUK__DOUBLE_INT_CAST4
97128 #undef DUK__FLOAT_MAX
97129 #undef DUK__FLOAT_ROUND_LIMIT
97130 /*
97131  *  IEEE double helpers.
97132  */
97133 
97134 /* #include duk_internal.h -> already included */
97135 
97136 DUK_INTERNAL duk_bool_t duk_double_is_anyinf(duk_double_t x) {
97137 	duk_double_union du;
97138 	du.d = x;
97139 	return DUK_DBLUNION_IS_ANYINF(&du);
97140 }
97141 
97142 DUK_INTERNAL duk_bool_t duk_double_is_posinf(duk_double_t x) {
97143 	duk_double_union du;
97144 	du.d = x;
97145 	return DUK_DBLUNION_IS_POSINF(&du);
97146 }
97147 
97148 DUK_INTERNAL duk_bool_t duk_double_is_neginf(duk_double_t x) {
97149 	duk_double_union du;
97150 	du.d = x;
97151 	return DUK_DBLUNION_IS_NEGINF(&du);
97152 }
97153 
97154 DUK_INTERNAL duk_bool_t duk_double_is_nan(duk_double_t x) {
97155 	duk_double_union du;
97156 	du.d = x;
97157 	/* Assumes we're dealing with a Duktape internal NaN which is
97158 	 * NaN normalized if duk_tval requires it.
97159 	 */
97160 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
97161 	return DUK_DBLUNION_IS_NAN(&du);
97162 }
97163 
97164 DUK_INTERNAL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x) {
97165 	duk_double_union du;
97166 	du.d = x;
97167 	/* Assumes we're dealing with a Duktape internal NaN which is
97168 	 * NaN normalized if duk_tval requires it.
97169 	 */
97170 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
97171 	return DUK_DBLUNION_IS_NAN(&du) || DUK_DBLUNION_IS_ANYZERO(&du);
97172 }
97173 
97174 DUK_INTERNAL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x) {
97175 	duk_double_union du;
97176 	du.d = x;
97177 	/* If exponent is 0x7FF the argument is either a NaN or an
97178 	 * infinity.  We don't need to check any other fields.
97179 	 */
97180 #if defined(DUK_USE_64BIT_OPS)
97181 #if defined(DUK_USE_DOUBLE_ME)
97182 	return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000);
97183 #else
97184 	return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000);
97185 #endif
97186 #else
97187 	return (du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL;
97188 #endif
97189 }
97190 
97191 DUK_INTERNAL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x) {
97192 	duk_double_union du;
97193 #if defined(DUK_USE_64BIT_OPS)
97194 	duk_uint64_t t;
97195 #else
97196 	duk_uint32_t t;
97197 #endif
97198 	du.d = x;
97199 #if defined(DUK_USE_64BIT_OPS)
97200 #if defined(DUK_USE_DOUBLE_ME)
97201 	t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000);
97202 	if (t == DUK_U64_CONSTANT(0x0000000000000000)) {
97203 		t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x0000000080000000);
97204 		return t == 0;
97205 	}
97206 	if (t == DUK_U64_CONSTANT(0x000000007ff00000)) {
97207 		return 1;
97208 	}
97209 #else
97210 	t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000);
97211 	if (t == DUK_U64_CONSTANT(0x0000000000000000)) {
97212 		t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000);
97213 		return t == 0;
97214 	}
97215 	if (t == DUK_U64_CONSTANT(0x7ff0000000000000)) {
97216 		return 1;
97217 	}
97218 #endif
97219 #else
97220 	t = du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL;
97221 	if (t == 0x00000000UL) {
97222 		return DUK_DBLUNION_IS_ANYZERO(&du);
97223 	}
97224 	if (t == 0x7ff00000UL) {
97225 		return 1;
97226 	}
97227 #endif
97228 	return 0;
97229 }
97230 
97231 DUK_INTERNAL duk_small_uint_t duk_double_signbit(duk_double_t x) {
97232 	duk_double_union du;
97233 	du.d = x;
97234 	return (duk_small_uint_t) DUK_DBLUNION_GET_SIGNBIT(&du);
97235 }
97236 
97237 DUK_INTERNAL duk_double_t duk_double_trunc_towards_zero(duk_double_t x) {
97238 	/* XXX: optimize */
97239 	duk_small_uint_t s = duk_double_signbit(x);
97240 	x = DUK_FLOOR(DUK_FABS(x));  /* truncate towards zero */
97241 	if (s) {
97242 		x = -x;
97243 	}
97244 	return x;
97245 }
97246 
97247 DUK_INTERNAL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y) {
97248 	duk_double_union du1;
97249 	duk_double_union du2;
97250 	du1.d = x;
97251 	du2.d = y;
97252 
97253 	return (((du1.ui[DUK_DBL_IDX_UI0] ^ du2.ui[DUK_DBL_IDX_UI0]) & 0x80000000UL) == 0);
97254 }
97255 
97256 DUK_INTERNAL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y) {
97257 	/* Doesn't replicate fmin() behavior exactly: for fmin() if one
97258 	 * argument is a NaN, the other argument should be returned.
97259 	 * Duktape doesn't rely on this behavior so the replacement can
97260 	 * be simplified.
97261 	 */
97262 	return (x < y ? x : y);
97263 }
97264 
97265 DUK_INTERNAL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y) {
97266 	/* Doesn't replicate fmax() behavior exactly: for fmax() if one
97267 	 * argument is a NaN, the other argument should be returned.
97268 	 * Duktape doesn't rely on this behavior so the replacement can
97269 	 * be simplified.
97270 	 */
97271 	return (x > y ? x : y);
97272 }
97273 
97274 DUK_INTERNAL duk_bool_t duk_double_is_finite(duk_double_t x) {
97275 	return !duk_double_is_nan_or_inf(x);
97276 }
97277 
97278 DUK_INTERNAL duk_bool_t duk_double_is_integer(duk_double_t x) {
97279 	if (duk_double_is_nan_or_inf(x)) {
97280 		return 0;
97281 	} else {
97282 		return duk_js_tointeger_number(x) == x;
97283 	}
97284 }
97285 
97286 DUK_INTERNAL duk_bool_t duk_double_is_safe_integer(duk_double_t x) {
97287 	/* >>> 2**53-1
97288 	 * 9007199254740991
97289 	 */
97290 	return duk_double_is_integer(x) && DUK_FABS(x) <= 9007199254740991.0;
97291 }
97292 
97293 /* Check whether a duk_double_t is a whole number in the 32-bit range (reject
97294  * negative zero), and if so, return a duk_int32_t.
97295  * For compiler use: don't allow negative zero as it will cause trouble with
97296  * LDINT+LDINTX, positive zero is OK.
97297  */
97298 DUK_INTERNAL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival) {
97299 	duk_int32_t t;
97300 
97301 	t = duk_double_to_int32_t(x);
97302 	if (!((duk_double_t) t == x)) {
97303 		return 0;
97304 	}
97305 	if (t == 0) {
97306 		duk_double_union du;
97307 		du.d = x;
97308 		if (DUK_DBLUNION_HAS_SIGNBIT(&du)) {
97309 			return 0;
97310 		}
97311 	}
97312 	*ival = t;
97313 	return 1;
97314 }
97315 
97316 /* Check whether a duk_double_t is a whole number in the 32-bit range, and if
97317  * so, return a duk_int32_t.
97318  */
97319 DUK_INTERNAL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival) {
97320 	duk_int32_t t;
97321 
97322 	t = duk_double_to_int32_t(x);
97323 	if (!((duk_double_t) t == x)) {
97324 		return 0;
97325 	}
97326 	*ival = t;
97327 	return 1;
97328 }
97329 
97330 /* Division: division by zero is undefined behavior (and may in fact trap)
97331  * so it needs special handling for portability.
97332  */
97333 
97334 DUK_INTERNAL DUK_INLINE duk_double_t duk_double_div(duk_double_t x, duk_double_t y) {
97335 #if !defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
97336 	if (DUK_UNLIKELY(y == 0.0)) {
97337 		/* In C99+ division by zero is undefined behavior so
97338 		 * avoid it entirely.  Hopefully the compiler is
97339 		 * smart enough to avoid emitting any actual code
97340 		 * because almost all practical platforms behave as
97341 		 * expected.
97342 		 */
97343 		if (x > 0.0) {
97344 			if (DUK_SIGNBIT(y)) {
97345 				return -DUK_DOUBLE_INFINITY;
97346 			} else {
97347 				return DUK_DOUBLE_INFINITY;
97348 			}
97349 		} else if (x < 0.0) {
97350 			if (DUK_SIGNBIT(y)) {
97351 				return DUK_DOUBLE_INFINITY;
97352 			} else {
97353 				return -DUK_DOUBLE_INFINITY;
97354 			}
97355 		} else {
97356 			/* +/- 0, NaN */
97357 			return DUK_DOUBLE_NAN;
97358 		}
97359 	}
97360 #endif
97361 
97362 	return x / y;
97363 }
97364 /*
97365  *  Hash function duk_util_hashbytes().
97366  *
97367  *  Currently, 32-bit MurmurHash2.
97368  *
97369  *  Don't rely on specific hash values; hash function may be endianness
97370  *  dependent, for instance.
97371  */
97372 
97373 /* #include duk_internal.h -> already included */
97374 
97375 #if defined(DUK_USE_STRHASH_DENSE)
97376 /* 'magic' constants for Murmurhash2 */
97377 #define DUK__MAGIC_M  ((duk_uint32_t) 0x5bd1e995UL)
97378 #define DUK__MAGIC_R  24
97379 
97380 DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed) {
97381 	duk_uint32_t h = seed ^ ((duk_uint32_t) len);
97382 
97383 	while (len >= 4) {
97384 		/* Portability workaround is required for platforms without
97385 		 * unaligned access.  The replacement code emulates little
97386 		 * endian access even on big endian architectures, which is
97387 		 * OK as long as it is consistent for a build.
97388 		 */
97389 #if defined(DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS)
97390 		duk_uint32_t k = *((const duk_uint32_t *) (const void *) data);
97391 #else
97392 		duk_uint32_t k = ((duk_uint32_t) data[0]) |
97393 		                 (((duk_uint32_t) data[1]) << 8) |
97394 		                 (((duk_uint32_t) data[2]) << 16) |
97395 		                 (((duk_uint32_t) data[3]) << 24);
97396 #endif
97397 
97398 		k *= DUK__MAGIC_M;
97399 		k ^= k >> DUK__MAGIC_R;
97400 		k *= DUK__MAGIC_M;
97401 		h *= DUK__MAGIC_M;
97402 		h ^= k;
97403 		data += 4;
97404 		len -= 4;
97405 	}
97406 
97407 	switch (len) {
97408 	case 3: h ^= data[2] << 16;
97409 	case 2: h ^= data[1] << 8;
97410 	case 1: h ^= data[0];
97411 	        h *= DUK__MAGIC_M;
97412         }
97413 
97414 	h ^= h >> 13;
97415 	h *= DUK__MAGIC_M;
97416 	h ^= h >> 15;
97417 
97418 	return h;
97419 }
97420 #endif  /* DUK_USE_STRHASH_DENSE */
97421 
97422 /* automatic undefs */
97423 #undef DUK__MAGIC_M
97424 #undef DUK__MAGIC_R
97425 /*
97426  *  Memory utils.
97427  */
97428 
97429 /* #include duk_internal.h -> already included */
97430 
97431 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
97432 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len) {
97433 	DUK_ASSERT(s1 != NULL || len == 0U);
97434 	DUK_ASSERT(s2 != NULL || len == 0U);
97435 	return DUK_MEMCMP(s1, s2, (size_t) len);
97436 }
97437 
97438 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len) {
97439 	DUK_ASSERT(s1 != NULL);
97440 	DUK_ASSERT(s2 != NULL);
97441 	return DUK_MEMCMP(s1, s2, (size_t) len);
97442 }
97443 #else  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
97444 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len) {
97445 	DUK_ASSERT(s1 != NULL || len == 0U);
97446 	DUK_ASSERT(s2 != NULL || len == 0U);
97447 	if (DUK_UNLIKELY(len == 0U)) {
97448 		return 0;
97449 	}
97450 	DUK_ASSERT(s1 != NULL);
97451 	DUK_ASSERT(s2 != NULL);
97452 	return duk_memcmp(s1, s2, len);
97453 }
97454 
97455 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len) {
97456 	DUK_ASSERT(s1 != NULL);
97457 	DUK_ASSERT(s2 != NULL);
97458 	return DUK_MEMCMP(s1, s2, (size_t) len);
97459 }
97460 #endif  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
97461 /*
97462  *  A tiny random number generator used for Math.random() and other internals.
97463  *
97464  *  Default algorithm is xoroshiro128+: http://xoroshiro.di.unimi.it/xoroshiro128plus.c
97465  *  with SplitMix64 seed preparation: http://xorshift.di.unimi.it/splitmix64.c.
97466  *
97467  *  Low memory targets and targets without 64-bit types use a slightly smaller
97468  *  (but slower) algorithm by Adi Shamir:
97469  *  http://www.woodmann.com/forum/archive/index.php/t-3100.html.
97470  *
97471  */
97472 
97473 /* #include duk_internal.h -> already included */
97474 
97475 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
97476 
97477 #if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
97478 #define DUK__RANDOM_SHAMIR3OP
97479 #else
97480 #define DUK__RANDOM_XOROSHIRO128PLUS
97481 #endif
97482 
97483 #if defined(DUK__RANDOM_SHAMIR3OP)
97484 #define DUK__UPDATE_RND(rnd) do { \
97485 		(rnd) += ((rnd) * (rnd)) | 0x05UL; \
97486 		(rnd) = ((rnd) & 0xffffffffUL);       /* if duk_uint32_t is exactly 32 bits, this is a NOP */ \
97487 	} while (0)
97488 
97489 #define DUK__RND_BIT(rnd)  ((rnd) >> 31)  /* only use the highest bit */
97490 
97491 DUK_INTERNAL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr) {
97492 	DUK_UNREF(thr);  /* Nothing now. */
97493 }
97494 
97495 DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
97496 	duk_double_t t;
97497 	duk_small_int_t n;
97498 	duk_uint32_t rnd;
97499 
97500 	rnd = thr->heap->rnd_state;
97501 
97502 	n = 53;  /* enough to cover the whole mantissa */
97503 	t = 0.0;
97504 
97505 	do {
97506 		DUK__UPDATE_RND(rnd);
97507 		t += DUK__RND_BIT(rnd);
97508 		t /= 2.0;
97509 	} while (--n);
97510 
97511 	thr->heap->rnd_state = rnd;
97512 
97513 	DUK_ASSERT(t >= (duk_double_t) 0.0);
97514 	DUK_ASSERT(t < (duk_double_t) 1.0);
97515 
97516 	return t;
97517 }
97518 #endif  /* DUK__RANDOM_SHAMIR3OP */
97519 
97520 #if defined(DUK__RANDOM_XOROSHIRO128PLUS)
97521 DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_splitmix64(duk_uint64_t *x) {
97522 	duk_uint64_t z;
97523 	z = (*x += DUK_U64_CONSTANT(0x9E3779B97F4A7C15));
97524 	z = (z ^ (z >> 30U)) * DUK_U64_CONSTANT(0xBF58476D1CE4E5B9);
97525 	z = (z ^ (z >> 27U)) * DUK_U64_CONSTANT(0x94D049BB133111EB);
97526 	return z ^ (z >> 31U);
97527 }
97528 
97529 DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_rotl(const duk_uint64_t x, duk_small_uint_t k) {
97530 	return (x << k) | (x >> (64U - k));
97531 }
97532 
97533 DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__xoroshiro128plus(duk_uint64_t *s) {
97534 	duk_uint64_t s0;
97535 	duk_uint64_t s1;
97536 	duk_uint64_t res;
97537 
97538 	s0 = s[0];
97539 	s1 = s[1];
97540 	res = s0 + s1;
97541 	s1 ^= s0;
97542 	s[0] = duk__rnd_rotl(s0, 55) ^ s1 ^ (s1 << 14U);
97543 	s[1] = duk__rnd_rotl(s1, 36);
97544 
97545 	return res;
97546 }
97547 
97548 DUK_INTERNAL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr) {
97549 	duk_small_uint_t i;
97550 	duk_uint64_t x;
97551 
97552 	/* Mix both halves of the initial seed with SplitMix64.  The intent
97553 	 * is to ensure that very similar raw seeds (which is usually the case
97554 	 * because current seed is Date.now()) result in different xoroshiro128+
97555 	 * seeds.
97556 	 */
97557 	x = thr->heap->rnd_state[0];  /* Only [0] is used as input here. */
97558 	for (i = 0; i < 64; i++) {
97559 		thr->heap->rnd_state[i & 0x01] = duk__rnd_splitmix64(&x);  /* Keep last 2 values. */
97560 	}
97561 }
97562 
97563 DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
97564 	duk_uint64_t v;
97565 	duk_double_union du;
97566 
97567 	/* For big and little endian the integer and IEEE double byte order
97568 	 * is the same so a direct assignment works.  For mixed endian the
97569 	 * 32-bit parts must be swapped.
97570 	 */
97571 	v = (DUK_U64_CONSTANT(0x3ff) << 52U) | (duk__xoroshiro128plus((duk_uint64_t *) thr->heap->rnd_state) >> 12U);
97572 	du.ull[0] = v;
97573 #if defined(DUK_USE_DOUBLE_ME)
97574 	do {
97575 		duk_uint32_t tmp;
97576 		tmp = du.ui[0];
97577 		du.ui[0] = du.ui[1];
97578 		du.ui[1] = tmp;
97579 	} while (0);
97580 #endif
97581 	return du.d - 1.0;
97582 }
97583 #endif  /* DUK__RANDOM_XOROSHIRO128PLUS */
97584 
97585 #endif  /* !DUK_USE_GET_RANDOM_DOUBLE */
97586 
97587 /* automatic undefs */
97588 #undef DUK__RANDOM_SHAMIR3OP
97589 #undef DUK__RANDOM_XOROSHIRO128PLUS
97590 #undef DUK__RND_BIT
97591 #undef DUK__UPDATE_RND
97592 #endif
97593